This repository contains a C++ trading bot for Coinbase Advanced Trade. It uses moving average crossovers to determine buy/sell actions and places limit maker orders using authenticated JWT-based API requests.
- Implements two moving averages:
- Short-Term MA: Based on 1-minute candles.
- Long-Term MA: Based on 5-minute candles.
- Trades with a small fixed USD amount (e.g., $5) based on crossover logic.
- All orders are posted maker-only (
post_only=true) to minimize taker fees.
coinbase-trading-bot/
├── main.cpp
├── CMakeLists.txt (if applicable)
├── README.md
└── ...
main.cpp- Implements:
- JWT creation using
jwt-cppand OpenSSL. - Authenticated HTTP requests with
libcurl. - Candle fetching, MA calculations, and basic crossover trading logic.
- JWT creation using
- Continuously loops with a 30-second delay to monitor market conditions and place orders as needed.
- Implements:
This bot uses the following C++ libraries:
- C++17 compiler
jwt-cpp— JWT creation & ES256 signing- OpenSSL (
libssl,libcrypto) — cryptography & RAND_bytes libcurl— HTTP / HTTPS requestsnlohmann/json— JSON parsingpthread(Linux) — required by jwt-cpp / OpenSSL Make sure these libraries are installed and linked when building.
The bot never embeds secrets in source code. Instead it reads your Coinbase Advanced Trade API key and EC private key from environment variables:
std::string keyName = std::getenv("KEY_NAME"); // Your Key ID (In Coinbase Api Key: "name")
std::string privateKeyPem = std::getenv("PRIVATE_KEY_PEM"); // Your Private Key (In Coinbase Api Key: "privateKey")The code also injects a 16-byte nonce into the JWT header to prevent replay attacks.
Note: Ensure your API key from Coinbase is generated with **ECDSA selected.
export KEY_NAME="your_api_key_name"
export PRIVATE_KEY_PEM=$'-----BEGIN EC PRIVATE KEY-----\n...\n-----END EC PRIVATE KEY-----'Before running:
- Set both variables in your shell,
.env, or a secret manager. - Never commit the PEM string to Git (it grants signing authority).
- Rotate keys in Coinbase if you suspect they were exposed.
You can store sensitive variables in a .env-style file and configure your IDE (like CLion) to load them during runtime.
Example keys.env:
KEY_NAME=your_api_key_name
PRIVATE_KEY_PEM=-----BEGIN EC PRIVATE KEY-----
...
-----END EC PRIVATE KEY------ Open Run/Debug Configurations.
- Go to Environment Variables -> “Load variables from file”.
- Point to
keys.env.
This keeps secrets out of source code while allowing local development.
- Clone this repository.
- Install dependencies.
- Use your preferred C++ build system (e.g.,
g++,CMake) to compile the program.
g++ -std=c++17 main.cpp -o trading_bot -lcurl -lssl -lcrypto -pthread./trading_bot- Buy Condition:
- Short-term MA crosses above long-term MA.
- You are not already holding a position.
- Sell Condition:
- Short-term MA falls below long-term MA.
- You are holding a position.
- Current price is sufficiently above the last buy price to cover fees and earn profit (default multiplier is 1.013).
During execution, the bot prints logs such as:
- Current short and long MAs
- Placed buy/sell orders
- Error messages (e.g., failed JSON parse, HTTP failures)
These are written to
stdoutfor real-time monitoring.
- Trade Amount: Modify
quoteAmountUsdinplaceLimitOrder(). - Profit Threshold: Adjust
minSellPrice = lastBuyPrice * 1.013. - Sleep Interval: Change the
std::this_thread::sleep_for(...)value in the main loop.
- JWT creation fails: Usually caused by an invalid private key or malformed JWT structure.
- HTTP 401/403 responses: Ensure your credentials are correct and that JWTs are signed properly.
- libcurl errors: Check network connection or API rate limits.
- JSON parsing issues: Validate Coinbase API hasn’t changed response structure.