trader-agent
by TimLiuDream
README.md
# Binance MCP Trader Agent
English | [简体中文](README.zh-CN.md)
Risk-gated AI trading agent for the Binance Agent OS mini hackathon (Track 2: Connect MCP and trade — see `docs/submission.md`).
It connects to the official Binance Agent OS MCP endpoint and turns natural trading intent into policy-checked, user-confirmed MCP tool calls. The local `trader-agent` server researches, enforces risk gates, and builds **executable Binance MCP requests**; it never places orders itself. Everything is **dry-run by default**, and live execution additionally requires five explicit gates (see [Live Trading Gates](#live-trading-gates)).
Docs map:
- `AGENTS.md` — first-read rules for coding agents.
- `docs/operator-manual.md` — complete commands, config keys, safety gates, demos, troubleshooting.
- `docs/mcp-server-development.md` — build notes and security rules for the local `trader-agent` MCP server.
- `docs/submission.md` — hackathon submission notes.
- `docs/TODO.md` — code-review findings backlog.
Official Binance MCP endpoint (the only one; no local Binance package, no API keys in this repo):
```text
https://agent.binance.com/mcp/agentic
```
## Architecture
Two MCP servers in the same AI client:
```text
AI client (Claude Code / Codex / ...)
|-- binance-mcp-server official Binance MCP: OAuth, market/account data, confirmed execution
|-- trader-agent local stdio server (this repo): research, policy, order planning, ledgers
```
The local server is a planner/auditor/researcher and the source of the approved execution request. It stores no Binance credentials, never calls Binance, and never places orders itself. After research and explicit user approval, the AI client calls the official Binance MCP order tool, then calls `trader-agent.record_mcp_execution` to archive the result. Live CLI execution also exists behind five gates.
Typical loop:
```text
fetch klines via binance-mcp-server -> save CSV under data/ ->
trader-agent research (backtest / gridsim / significance) -> policy_check ->
propose_order_plan (returns the executable request) -> user confirms the exact request ->
binance-mcp-server order/strategy tool -> record_mcp_execution (append-only archive)
```
## Highlights
**Research engine (local, offline candle files)**
- MA, RSI, MACD, Bollinger indicators and buy/sell/hold signals.
- MA/RSI strategy backtests with fees, slippage, and gap-aware fills (a stop filled through a gap takes the worse open price); entry semantics are identical to the live signal (fresh golden cross + RSI band), so backtests measure exactly the strategy that `propose-from-signal` follows.
- Triple-barrier exits: fixed stop-loss/take-profit, optional time limit, optional trailing stop, and an optional time-decaying ROI table (`roiTable`, freqtrade `minimal_roi` style).
- Parameter grid optimization with six selectable scoring losses: `default` (composite), `sharpe`, `sortino`, `calmar`, `maxdrawdown`, `onlyprofit`; constraints on return/drawdown/trades/win-rate/Sharpe are always enforced.
- Walk-forward train/test validation; randomized return-path significance tests (seeded, p-value with +1 correction).
- Grid planning: budget-driven level count (investment vs exchange min-notional vs min spacing), prices/amounts quantized to exchange rules, per-level take-profit coerced to the grid step (`coerce_tp_to_step`), and a state-machine fill simulation over candles (`research gridsim`) with cycle counts, realized PnL, and per-level state histogram.
- HTML reports with candlesticks, trade markers, and equity curves.
**Risk and policy gates (single entry: `evaluatePolicy`)**
- Allowlists for venues and symbols; market orders disabled by default; single-order quote cap; futures leverage cap; opening shorts require `reduceOnly`; position cap via `maxOpenPositions`; futures `positionMode` (one-way/hedge) derived into `positionSide`.
- Order throttle: per-symbol open-order cap (`maxOpenOrdersPerSymbol`) and minimum seconds between live orders (`minSecondsBetweenLiveOrders`).
- Fail-closed budget pre-check: `executable=true` requires `accountFreeQuote` (free balance reported by the AI client from the official Binance MCP account tool) covering the quote amount, and respect of the exchange `minNotional` when `exchangeRules` are provided. Missing balance data keeps `executable=false`. Grid plans check balance against the total investment and `minNotional` per level; reduce-only exits skip the balance cap (they release margin instead of spending it).
- Performance circuit breakers (freqtrade-Protections style), evaluated from the local execution ledger: per-symbol cooldown after a recorded exit (`cooldownMinutesAfterExit`), StoplossGuard stop-loss counting per pair and globally within a lookback window, and a realized-PnL drawdown breaker (`maxDrawdownQuoteUsdt`). Breakers gate opening orders only — `reduceOnly` exits always pass.
- Every proposal returns an `executableRequest` object (`executable`, `server: "binance-mcp-server"`, `toolName`, `arguments`, `confirmationText`, `reason`) — the exact request the AI client may submit after the user confirms it. `confirmationText` never contains the confirmation phrase itself.
- Demo-friendly multi-agent decision chain: `Signal -> Bull -> Bear -> Risk Judge -> Distribution`.
**Execution and records**
- Dynamic `tools/list` discovery; schema-aware mapping of trading intent (or grid bounds) to the best matching order tool; grid level tables are attached to tool arguments when the selected tool exposes a levels-like property.
- Every proposal/execution is a task with id, status, decision chain, and classified error details; authentication/insufficient-funds failures can pause the trader until `trader resume`.
- Stop-loss/take-profit protection is planned as a linked group (native OCO when the MCP server exposes one); quantities are hydrated from the actual entry fill. With `submitProtectiveOrders=false` (default) the group is archived as skipped and live fills are marked `completed_unprotected`.
- Exit-role records (`role: "exit"`) accept `realizedPnlQuote` and feed the cooldown/StoplossGuard/drawdown breakers.
- All CLI JSON output and ledgers are redacted for secret-like fields before printing or writing; smoke tests run on fully isolated ledgers (`runs-smoke/`) and pin the real Binance MCP tool surface (tool names and argument keys captured from production) as regression fixtures.
## Quick Start
```bash
npm install
copy config\agent.example.json config\agent.local.json
copy .env.example .env
npm run typecheck
npm run build
npm run smoke
```
`npm start` and `npm run smoke` import compiled files from `dist/`, so always `build` first. Node >= 20.
Offline policy check and dry-run proposal:
```bash
npm start -- policy --config config/agent.local.json --symbol BTCUSDT --side buy --type limit --quote 20 --price 65000
npm start -- propose --config config/agent.local.json --symbol BTCUSDT --side buy --type limit --quote 20 --price 65000
```
`policy` is offline and never connects to MCP. `propose` connects to Binance MCP, discovers order tools, and builds the candidate MCP call without trading. `propose` fails the budget pre-check until you pass `--accountFree <free-quote-usdt>` (and optionally `--tickSize/--stepSize/--minNotional`):
```bash
npm start -- propose --symbol BTCUSDT --side buy --type limit --quote 20 --price 65000 --accountFree 100 --minNotional 5
```
Offline research on a CSV/JSON OHLCV file:
```bash
npm start -- research backtest --file data/BTCUSDT-15m.csv --symbol BTCUSDT --timeframe 15m
npm start -- research gridsim --file data/BTCUSDT-15m.csv --symbol BTCUSDT --timeframe 15m --priceLow 76500 --priceHigh 79500 --quote 1000
npm start -- research optimize --file data/BTCUSDT-15m.csv --symbol BTCUSDT --timeframe 15m --loss calmar
```
## CLI Command Reference
| Command | Purpose |
|---------|---------|
| `tools` | Connect to Binance MCP and list discovered tools |
| `account` | Call the best matching account/balance tool |
| `quote` | Fetch market data for a symbol |
| `policy` | Offline safety check for a manual trade intent (auto-reviews the execution ledger for breakers) |
| `propose` | Risk-checked order proposal + executable request; never trades |
| `execute` | Live order only when all five gates pass |
| `research` | `signal`, `backtest`, `optimize`, `walkforward`, `significance`, `report`, `gridsim`, `propose-from-signal`, `sessions` |
| `tasks` | Show recent local trade task records |
| `executions` | Show recent submitted MCP execution archive records |
| `trader status` / `trader resume` | Show or clear the trader pause state |
Notable flags:
- Trade intent (policy/propose/execute): `--symbol/-s`, `--side`, `--venue`, `--type`, `--quote`, `--price`, `--amount`, `--leverage`, `--reduceOnly`, `--openPositions`, `--strategyType spot|futures|grid`.
- Pre-check inputs: `--accountFree` (free quote balance), `--openOrders`, `--lastOrderAt`, `--tickSize`, `--stepSize`, `--minNotional` (the latter three also quantize grid levels).
- Grid proposals: `--priceLow`, `--priceHigh`, `--gridLevels`, `--coerceTp`.
- Research parameters: `--fast`, `--slow`, `--rsi`, `--rsiMin`, `--rsiMax`, `--takeProfit`, `--stopLoss`, `--timeLimitBars`, `--trailingStopActivation`, `--trailingStopDelta`, `--roiTable '<json>'`, `--quote`, `--initialCash`, `--feeRate`, `--slippageRate`; optimization constraints `--minReturn/--maxDrawdown/--minTrades/--minWinRate/--minSharpe`; `research optimize --loss <name>`; `research significance --simulations/--seed`; `research report --out`.
Full command and config reference: `docs/operator-manual.md`.
## Using with an AI Client
### 1. Add the official Binance MCP server
Claude Code (verified working):
```bash
claude mcp add -s user -t http binance-mcp-server https://agent.binance.com/mcp/agentic
```
Codex CLI:
```bash
codex mcp add binance-mcp-server --url https://agent.binance.com/mcp/agentic
codex mcp login binance-mcp-server
```
Generic JSON MCP clients:
```json
{
"mcpServers": {
"binance-mcp-server": {
"url": "https://agent.binance.com/mcp/agentic"
}
}
}
```
Do not paste the endpoint into a normal AI chat and ask the model to install it. Add it through the client's MCP/server settings. `-s user` registers the server globally; without it the server only loads in sessions started from that project directory. Restart the client after adding — the MCP server list loads at client startup.
### 2. Authenticate and pick scopes
Open the MCP menu in the AI client, select `binance-mcp-server`, run the OAuth flow, and grant the least scope needed:
- **Market data** — tickers, order books, candles, funding rates. Start here.
- **Account** — Agentic sub-account balances, positions, bills. Needed for `accountFreeQuote`.
- **Trade** — spot, margin, convert, USD-M / COIN-M futures; only when ready to test live trading.
- **Transfer** — wallet-to-wallet inside the same Agentic sub-account only.
Binance Agent OS MCP does not expose withdrawal permission. It cannot withdraw funds to an external address.
### 3. Add the local trader-agent MCP server
Claude Code (verified working; `--prefix` makes the script run with the repo as cwd so config/data/runs resolve correctly from anywhere):
```bash
claude mcp add -s user trader-agent -- npm --prefix D:/GOPATH/src/github.com/sereneFIREGroup/trading/binance-mcp-trader-agent run mcp-server
```
Codex CLI (run from the repo root):
```bash
codex mcp add trader-agent -- npm run mcp-server
```
The server is a stdio MCP server built on the official TypeScript MCP SDK (`@modelcontextprotocol/sdk`), started via `npm run mcp-server`. Tool surface (15 tools) — research tools accept offline candle files only (`file` under `data/`, `reports/`, or `runs/`) and never fetch from Binance:
- `research_signal`, `research_backtest`, `research_optimize`, `research_walkforward`, `research_significance`, `research_report`, `research_gridsim`
- `policy_check` (gates + ledger-derived breakers), `propose_order_plan` (task/order plan + `executableRequest` + grid level table; never calls Binance itself)
- `record_mcp_execution` (archives the result after the AI client calls the official Binance MCP; `role: "exit"` + `realizedPnlQuote` feed the breakers)
- `list_tasks`, `list_research_sessions`, `list_executions`
- `trader_status`, `trader_resume`
`propose_order_plan` inputs mirror the CLI pre-check inputs (`accountFreeQuote`, `exchangeRules`, `openOrders`, `lastOrderAt`, `strategyType`, grid bounds) plus `binanceTools` metadata from the official server's `tools/list`, so tool selection and argument mapping run locally. Full input schemas: `docs/mcp-server-development.md`.
### 4. Agent runtime prompt
Paste into the AI client:
```text
You have two MCP servers:
1. binance-mcp-server: official Binance MCP. Use it for market data, account reads, and order execution only after explicit user confirmation.
2. trader-agent: local risk/research agent. Use it first for research, backtests, policy checks, order plans, task ledgers, and execution records.
Required order for any trade:
trader-agent.research_backtest / research_significance / research_gridsim
-> trader-agent.propose_order_plan (returns the executable request)
-> show the executableRequest.confirmationText to the user and wait for explicit approval
-> binance-mcp-server order tool
-> trader-agent.record_mcp_execution (role "exit" with realizedPnlQuote after a position closes)
Never call Binance order tools before trader-agent returns a passing policy, an order plan, and the exact executable request, and the user confirms that request.
```
### 5. Fund the Agentic sub-account (live testing only)
Trading happens inside a dedicated Agentic sub-account isolated from the main account; the agent cannot pull funds from the main account. For live tests, manually transfer a small test amount:
```text
Profile -> Dashboard -> Sub-account -> Asset Management -> Transfer
```
Skip this for read-only market-data tests and dry-run demos.
### 6. Verify connectivity
```bash
npm run build
npm start -- tools --config config/agent.local.json
```
A healthy connection prints Binance MCP tools. HTTP 401 → re-authenticate the MCP server in the AI client or refresh `BINANCE_MCP_AUTH_TOKEN`. Then test read-only market data (`quote`, `research signal`) before any account or trading tests. If market data works but account/order commands fail, grant the missing Account or Trade scope and confirm the sub-account is eligible for the venue.
## Standalone CLI Direct-HTTP Mode
The standalone `npm start -- ...` CLI can also talk to Binance MCP directly. It cannot read OAuth tokens from Codex CLI's encrypted MCP auth store; set a short-lived bearer token only in your shell or ignored `.env`:
```powershell
$env:BINANCE_MCP_AUTH_TOKEN="your_short_lived_mcp_token_here"
```
- `npm start -- policy ...` — fully offline; no MCP auth needed.
- `npm start -- research ... --file data/BTCUSDT-15m.csv` — offline research/backtest/report; no MCP auth needed.
- `npm start -- tools|quote|account|propose|execute ...` — direct MCP HTTP mode; needs `BINANCE_MCP_AUTH_TOKEN` until a dedicated OAuth bridge exists.
## Live Trading Gates
Live execution is intentionally hard to trigger. All five must agree:
1. `config/agent.local.json`: `"mode": "live"`
2. CLI flag: `--live`
3. Environment variable: `BINANCE_AGENT_LIVE=1`
4. Confirmation phrase: `--confirm I_ACCEPT_BINANCE_LIVE_TRADING_RISK`
5. Finished research proof: `--researchSession <id>` from `research backtest | optimize | walkforward | significance | report | gridsim | propose-from-signal` (a plain `research signal` id is not accepted)
```bash
set BINANCE_AGENT_LIVE=1
npm start -- execute --config config/agent.local.json --live --researchSession research_backtest_... --confirm I_ACCEPT_BINANCE_LIVE_TRADING_RISK --symbol BTCUSDT --side buy --type limit --quote 20 --price 65000
```
## Safety Model
- Default mode is dry-run; market orders disabled; single order capped at 25 USDT by default (grid: the cap applies per level, the balance pre-check to the total investment).
- Futures short opening disabled unless reduce-only; performance breakers never block reduce-only exits.
- `executable=true` is fail-closed: without reported balance the request stays non-executable with an explicit reason.
- Live execution records stop-loss/take-profit protection as a linked order group but does not submit those extra orders. Add `--submitProtection` only when the discovered Binance MCP tools clearly support OCO / stop-loss / take-profit placement. Native OCO tools delegate sibling cancellation to the exchange; linked non-OCO orders are archived with an explicit operator cancellation policy.
- Monitoring-level barriers (time limit, trailing stop, ROI table) are surfaced in order plans as warnings — they are not exchange-native orders and require the operator/AI client to watch and act.
- No private key, mnemonic, Binance API key, or long-lived token is required by the repo; real `.env` and local config are git-ignored. Never store secrets in tracked files.
- The local MCP server never stores Binance OAuth tokens or API keys, never adds Binance REST API-key support, and never calls Binance directly; all exchange actions go through the official `binance-mcp-server` connection owned by the AI client after explicit user confirmation, or stay CLI-only.
- All CLI JSON output and runtime ledgers redact secret-like fields before printing or writing; the confirmation phrase is never embedded in tool output.
- Research MCP tools accept offline files only, confined to `data/`, `reports/`, and `runs/` (path traversal and absolute paths rejected), and must never call order/account/transfer tools.
- Authentication and insufficient-funds failures are classified and can pause the trader.
- Smoke tests run on isolated `runs-smoke/` ledgers and never touch the production `runs/` audit trail.
## Demo Script
1. `npm start -- tools` — dynamic Binance MCP tool discovery.
2. Dry-run `propose` (with `--accountFree`) — show the policy decision and the `executableRequest` with its confirmation text.
3. Oversized quote or missing `--accountFree` — show the fail-closed blocker.
4. `research backtest` — strategy validated before trading (fees, slippage, gap-aware stops).
5. `research gridsim` — grid level table + state-machine replay over candles.
6. `research optimize --loss maxdrawdown` — parameter search under a chosen scoring loss.
7. `research significance` + `research report` — statistical validation and the HTML chart.
8. Record exits via `record_mcp_execution` (`role: "exit"`, `realizedPnlQuote`), then show `policy_check` firing cooldown / StoplossGuard / drawdown breakers.
9. `tasks --limit 5` and `executions --limit 5` — every proposal has a task id, decision chain, and order plan; every submitted call is archived.
10. Switch config to live — execution still fails until env + confirmation + research session are present.
11. Tiny live limit order — only if the contest sub-account is authorized and funded.
## Project Structure
```text
binance-mcp-trader-agent/
LICENSE MIT
AGENTS.md first-read rules for coding agents
src/
cli.ts command-line agent
mcp-server.ts local stdio trader-agent MCP server entrypoint (15 tools)
mcp-tools/ MCP input validation (zod), path confinement, tool registrations
mcp-client.ts Streamable HTTP MCP JSON-RPC client (SSE-aware)
tool-router.ts dynamic Binance MCP tool selection and argument mapping (order/OCO/protection/grid)
payload.ts helpers for reading unknown MCP payloads
policy.ts the single safety-policy entry: allowlists, caps, throttle, breakers, live gates
safety.ts output and ledger redaction helpers
research/ indicators, market data parsing, backtest (triple barrier + ROI table),
grid-plan (level tables), grid-simulator, optimization losses,
significance tests, sessions, HTML reports
trading/ trading workflow, executable-request builder, order plan (OCO/protection),
decision chain, task/execution ledgers, recent-exit lookups, failure handling
config/
agent.example.json safe template config (includes breaker + roiTable defaults)
scripts/smoke.mjs end-to-end smoke tests on isolated runs-smoke/ ledgers
docs/
operator-manual.md full operator manual (commands, config keys, troubleshooting)
mcp-server-development.md local MCP server tool schemas and security rules
submission.md hackathon submission notes
TODO.md code-review findings backlog
```
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues