SignalBet · systematic spot trading on Coinbase Advanced Trade — rule-based EMA, optional AI (OpenRouter), or side-by-side compare mode.
| Repository | github.com/signalbetorg/coinbase-trading-agent |
| Clone | git clone https://github.com/signalbetorg/coinbase-trading-agent.git |
| Issues / PRs | signalbetorg/coinbase-trading-agent |
Keywords: coinbase coinbase-api coinbase-bot advanced-trade cdp-api trading-agent trading-bot ema-crossover atr trend-filter ai-trading openrouter llm hybrid-strategy compare-mode paper-trading market-ioc typescript btc eth sol crypto algorithmic-trading automated-trading quant fintech risk-sizing zod nodejs open-source spot signalbet
Jump to: What you get · Strategy modes · Quick start · Configuration · AI setup · Compare mode · Troubleshooting
A single-process trading agent that polls Coinbase candles, evaluates signals, sizes risk from your .env, and places market IOC orders when you opt in.
| Layer | What it does |
|---|---|
| Exchange | Coinbase Advanced Trade REST via coinbase-advanced-node |
| Rules | EMA crossover + long-term trend filter + ATR logging |
| AI (optional) | OpenRouter-backed LLM for ai, hybrid, or compare modes |
| Safety | Paper trading on by default; confidence gate on AI signals |
Lineage: Evolved from pro-tech-killers/coinbase-trading-bot with AI strategy modes and OpenRouter defaults. This repo (signalbetorg/coinbase-trading-agent) is the maintained home going forward.
Most trading tools ask you to trust a logo. This one asks you to read the code.
- Clarity you can build on — One loop, one strategy module, and configuration that is validated at startup (so bad env vars fail fast, not in production).
- Discipline, baked in — Paper trading is the default. You opt in to live orders with a single flag—on purpose.
- Risk you define — Size entries with a per-trade risk fraction and an optional hard cap per order in your quote currency. The bot does not “guess” your tolerance.
- A strategy people actually recognize — EMA cross + long-term EMA filter and ATR logging mirror ideas you will find in books, courses, and prop-style playbooks: trend follow when the market agrees, step aside when the cross says to exit.
- Serious stack — TypeScript 5, Node 20+, and coinbase-advanced-node talking to the real Advanced Trade API—the same class of building blocks used by developers who treat execution as software engineering.
Ideal if you want to automate a rule you understand, learn systematic trading on real infrastructure, or ship a v1 you can later upgrade with your own risk engine—without starting from a fragile script you found in a forum thread.
| You want to… | What this gives you |
|---|---|
| Get going in one session | npm install → copy .env → npm run dev and you are pulling candles. |
| See signals before you risk capital | Paper mode on by default — logs what would have traded. |
| Own your stack | Full source: indicators, strategy, execution—fork it, don’t rent it. |
| Stay in control | Tweak EMAs, pair, and poll interval in .env without touching the exchange UI every hour. |
| Grow from prototype to system | Clean folders so you can add stops, websockets, or a second strategy without a rewrite. |
Under the hood (one sentence): a production-style client that runs a trend-following EMA rule, applies position sizing from your settings, and only sends live market orders when you say so.
- Connect in minutes — Add keys to
.env, runnpm run dev, and you are already streaming real market structure into your terminal—not a demo with fake prices. - Watch the rules work in plain sight — Every cycle logs close, EMAs, ATR, signal, balances. The story is in the data, not in someone else’s “AI.”
- Tune like a product — Swap pair, timeframes, and EMAs from configuration; iterate without rebuilding your idea from scratch every week.
- Promote to live on your terms — Paper is default for a reason. When the logs still make sense to you, you flip one flag. That’s the bar.
That’s the hook: not “magic money,” but a machine you understand that can keep watching when you need to work, sleep, or think.
| You are… | You’ll care because… |
|---|---|
| A developer | You want Git, TypeScript, and a real REST client next to your trading idea—not a binary blob called “strategies.dll.” |
| A self-directed trader | You want a documented rule and reproducible logs you can review when emotions have cooled. |
| A learner | You want the full path: candles → math → intent → (optional) order—on the same exchange serious traders use. |
| A builder / side-project founder | You need a credible v1 you can show: “this places orders through Coinbase; here’s the repo.” |
| Anyone burned by “bots” in a box | You hold the code. If something is wrong, you can find the line—not file a support ticket and hope. |
- We do not claim guaranteed profits, “passive income,” or a secret edge. Markets change; rules break; capital is at risk.
- We do offer full transparency, paper-by-default execution, and a serious starting point to learn and extend—if you put in the work on testing and risk.
- The goal isn’t a lottery ticket. It’s ownership of your process in a form you can run, measure, and improve.
| Goal | How this project helps |
|---|---|
| Clarity | One strategy, one loop, explicit env-driven configuration (validated with Zod). |
| Safety | Paper trading is the default; real orders require you to opt in explicitly. |
| Control | Risk per trade and optional per-order caps are separate from the signal logic. |
| Maintenance | Typed code, coinbase-advanced-node for the exchange API, Node 20+. |
Important: Marketing copy does not change market reality. Trading involves risk of loss. Past results do not predict future results. This repository is not financial, tax, or legal advice. You are responsible for API keys, permissions, product choice, fees, and compliance with law and Coinbase terms. Nothing here promises profit.
The bot supports three strategy modes (set STRATEGY_MODE in .env):
| Mode | Behavior |
|---|---|
ema (default) |
Classic double EMA crossover with a long-term EMA trend filter — no AI calls. |
ai |
An LLM (OpenAI-compatible API) reads indicators, balances, and recent price action and returns buy / sell / hold. |
hybrid |
EMA rules generate signals; the LLM confirms or rejects each BUY/SELL before execution. |
compare |
Runs both EMA and AI each tick, logs them side-by-side (strategy-compare), and never places orders (observation / A-B mode). |
- Entry (buy signal): Shorter EMA crosses above longer EMA and price is on the “right side” of the trend EMA (configurable, default: above the 200-period EMA on your chosen candle size).
- Exit (sell signal): Shorter EMA crosses below longer EMA (full base exit, subject to min order sizes).
- Fetch candles and compute EMAs + ATR.
- Build a market context prompt (price, indicators, balances, recent closes).
- Call the LLM with a strict JSON schema:
{ action, confidence, reasoning }. - If
confidenceis belowAI_MIN_CONFIDENCE, downgrade toHOLD. - Engine applies existing risk sizing and paper/live execution unchanged.
ATR (Average True Range) is calculated for each cycle and logged so you can extend the bot (e.g. dynamic stops, volatility-scaled size) without reverse-engineering the code.
This is not a guarantee of positive returns. Edge in live markets depends on product, timeframe, costs, slippage, and regime—and must be measured (backtest, walk-forward, paper trade) for your market and your parameters.
flowchart LR
subgraph config [Config]
ENV[".env"]
end
subgraph exchange [Coinbase Advanced Trade]
API["REST API"]
end
subgraph bot [Bot]
Candles["Fetch candles"]
Indicators["EMA + ATR"]
Rules["Strategy (EMA / AI / hybrid)"]
Risk["Size & limits"]
Exec["Market IOC orders"]
end
ENV --> Candles
Candles --> Indicators
Indicators --> Rules
Rules --> Risk
Risk --> Exec
Candles --> API
Risk --> API
Exec --> API
- Node.js 20+
- A Coinbase account with Advanced Trade access
- An API key with appropriate permissions (read balances, read market data, trade only if you disable paper mode)
From package.json (package: coinbase-adv-trade-bot):
| Script | Command | Purpose |
|---|---|---|
npm run dev |
node --import tsx src/index.ts |
Run TypeScript without a separate compile step. |
npm run build |
tsc |
Emit JavaScript to dist/ (npm start expects dist/index.js). |
npm start |
node dist/index.js |
Production-style run after npm run build. |
npm run typecheck |
tsc --noEmit |
CI / local compile validation only. |
Main runtime dependencies:
| Dependency | Role |
|---|---|
| coinbase-advanced-node | Typed client for Coinbase Advanced Trade REST endpoints. |
| zod | Validates .env once at startup. |
| dotenv | Loads .env locally. |
- Products:
PRODUCT_IDmust be a live Advanced Trade product ID (e.g.BTC-USD). The bot validates format at startup—typos fail fast rather than silently polling the wrong instrument. - Candles: The loop requests historical candles until the strategy has enough bars for
EMA_TRENDand the crossover logic; coarse granularities (ONE_DAY) mean slower “strategy-ready” startup thanONE_MINUTE/FIVE_MINUTE. - Orders: Entries use market IOC with
quote_size; sizing mergesRISK_PER_TRADEwith optionalMAX_QUOTE_PER_ORDER. Coinbase minimum increments (quote_min_size,base_min_size) still apply—the README troubleshooting lists rejects tied to minima. - Rate limits: Advanced Trade applies REST rate limits per key and endpoint class. For a single pair and one poll every
POLL_MS, traffic is modest; if you shortenPOLL_MSaggressively or run many forks of this bot on the same key, watch for429-style throttling in logs and back off. - Not modeled here: Full order book, historical fill reconstruction, or sub-account routing—extend the client layer if you need them.
git clone https://github.com/signalbetorg/coinbase-trading-agent.git
cd coinbase-trading-agent
npm installcopy .env.example .envOn macOS or Linux:
cp .env.example .envEdit .env and add credentials (see Authentication below). Leave PAPER_TRADING=1 until you are ready.
npm run build
npm startDevelopment (TypeScript without a separate build):
npm run devYou should see timestamped log lines: closes, EMAs, ATR, signal, and balances. In paper mode, no orders are sent.
The first time you see a full tick in the log—price, EMAs, ATR, signal, balances—you’ve turned a loose idea into a pipeline you can re-run any day. That is the feeling most people are chasing when they say they want a bot. This repo is built to get you to that moment fast, then help you not ruin it with rushed live size.
The bot supports the same two styles supported by the underlying client:
| Method | Environment variables | Notes |
|---|---|---|
| CDP (recommended) | CDP_API_KEY_NAME, CDP_API_KEY_SECRET |
Modern Coinbase Developer Platform / Cloud API keys. |
| Legacy HMAC | API_KEY, API_SECRET |
Older key format, where still supported. |
Never commit .env or keys. The repository includes .gitignore rules for .env.
Permissions: For paper trading you still need valid keys so the client can read candles and balances (same as live). Ensure your key’s scopes match what you intend (view vs trade).
| Variable | Default | Description |
|---|---|---|
PAPER_TRADING |
1 (on) |
1 / true = log only; set to 0 to send real orders. |
PRODUCT_ID |
BTC-USD |
e.g. ETH-USD, SOL-USD (use Coinbase’s product IDs). |
CANDLE_GRANULARITY |
FIVE_MINUTE |
ONE_MINUTE, FIVE_MINUTE, FIFTEEN_MINUTE, THIRTY_MINUTE, ONE_HOUR, TWO_HOUR, SIX_HOUR, ONE_DAY. |
POLL_MS |
60000 |
Milliseconds between loop iterations. |
STRATEGY_MODE |
ema |
ema = rules only; ai = LLM decides; hybrid = EMA + AI confirm; compare = log both, no orders. |
EMA_FAST |
12 |
Fast EMA length (closes). |
EMA_SLOW |
26 |
Slow EMA length (same window family as many MACD definitions). |
EMA_TREND |
200 |
Trend EMA; long entries require price context vs this line (see code). |
ATR_PERIOD |
14 |
ATR lookback; used in logs; extend the code for risk logic. |
RISK_PER_TRADE |
0.02 |
Fraction of available quote balance used to size a new buy (e.g. 0.02 = 2%). |
MAX_QUOTE_PER_ORDER |
(optional) | Hard cap in quote currency on each buy (e.g. 500 for 500 USD). |
AI_API_KEY |
(optional) | OpenAI-compatible API key. Also accepts OPENROUTER_API_KEY or OPENAI_API_KEY. Required for ai/hybrid. |
AI_BASE_URL |
https://openrouter.ai/api/v1 |
API base URL (OpenRouter default; override for OpenAI, etc.). |
AI_MODEL |
openai/gpt-4o-mini |
Model name (OpenRouter format by default). |
AI_MIN_CONFIDENCE |
0.55 |
Trades below this confidence are downgraded to HOLD. |
AI_TIMEOUT_MS |
30000 |
Max wait for an LLM response per tick. |
# In .env — get a key at https://openrouter.ai/keys
STRATEGY_MODE=hybrid
OPENROUTER_API_KEY=sk-or-...
# AI_BASE_URL and AI_MODEL already default to OpenRouter + gpt-4o-miniTo use OpenAI directly, override the defaults:
AI_BASE_URL=https://api.openai.com/v1
AI_MODEL=gpt-4o-mini
OPENAI_API_KEY=sk-...Leave STRATEGY_MODE=ema (default) to run without any AI API key.
STRATEGY_MODE=compare
OPENROUTER_API_KEY=sk-or-...Each tick logs a strategy-compare line with emaSignal, aiSignal, agree, and both reasons. Execution is always HOLD — use this to evaluate AI vs rules before switching to hybrid or ai.
- Buys use market IOC with
quote_size(spend up to the risk- and cap-limited amount). - Sells use market IOC with
base_size, using nearly all base balance on exit (minus rounding); minimum sizes come from the product API. - The bot does not manage partial take-profits, stop-loss orders, or pending-order reconciliation in the current version; treat it as a minimal v1 you can extend.
Profitable process in real markets usually combines:
- Explicit costs — fees, spread, and (for some products) funding; compare to the average trade’s expected move.
- Stability of rules — avoid changing parameters on every red day; document what you test.
- Out-of-sample checks — walk-forward or paper after any parameter search.
- Risk of ruin — keep per-trade risk small relative to what you can afford to lose.
This README is written so you can align expectations with that workflow—not with hype.
| Path | Role |
|---|---|
src/index.ts |
Loads env, starts the engine. |
src/config.ts |
Validated environment and PRODUCT_ID parsing. |
src/coinbase/createClient.ts |
Authenticated Coinbase client. |
src/strategy/emaCrossTrendStrategy.ts |
EMA/ATR signal logic. |
src/strategy/evaluateStrategy.ts |
Strategy mode dispatcher (ema / ai / hybrid). |
src/ai/ |
OpenAI-compatible client, prompts, and AI decision parsing. |
src/engine/botEngine.ts |
Polling loop, balances, order placement, logging. |
src/indicators/ |
EMA and ATR helpers. |
src/utils/sizeFormat.ts |
Order size strings vs exchange minima. |
| Command | Description |
|---|---|
npm run build |
Compile to dist/. |
npm start |
Run compiled dist/index.js (use after build). |
npm run dev |
Run TypeScript with tsx (no build required). |
npm run typecheck |
Type-check only. |
- Confirm paper logs match your intent for several sessions and products.
- Set
PAPER_TRADING=0in.env. - Use only capital you can afford to lose; start with small
RISK_PER_TRADEand optionalMAX_QUOTE_PER_ORDER. - Monitor the first live sessions; consider running on a small VPS or home machine you control, with a locked-down key.
Stop the bot with Ctrl+C in the terminal (SIGINT).
| Symptom | What to check |
|---|---|
Set CDP API keys... |
Missing or misnamed env vars; use .env in the project root. |
Unknown product |
PRODUCT_ID must match a live Advanced Trade product (e.g. BTC-USD). |
| Orders rejected / below minimum | Check Coinbase base_min_size / quote_min_size for that product; increase balance or RISK_PER_TRADE slightly if appropriate. |
| “Need N candles” | The strategy needs a minimum history; wait for the feed to return enough bars or use a coarser CANDLE_GRANULARITY if the API limit is an issue. |
| Too many requests / throttling | Short POLL_MS or multiple processes on one key |
401 / auth after key rotation |
Stale env or wrong key pair |
STRATEGY_MODE ai/hybrid/compare requires AI_API_KEY |
Missing LLM key |
LLM HTTP 401 / AI errors |
Bad API key or wrong AI_BASE_URL |
AI always HOLD |
Low confidence or rejections |
- Star signalbetorg/coinbase-trading-agent if you plan to run or fork it.
- Try compare mode first — log EMA vs AI side-by-side before enabling
hybridorai. - Open an issue on this repo for bugs or feature requests.
See the repository license if provided. Dependencies (coinbase-advanced-node, etc.) remain under their own licenses.
Exchange connectivity uses coinbase-advanced-node — not affiliated with Coinbase, Inc. Rule-based core derived from pro-tech-killers/coinbase-trading-bot.
If you use this in production, log retention, key rotation, and incident response are your responsibility.
Questions? Open an issue or adapt src/strategy and src/ai after paper testing.