Skip to content

Latest commit

 

History

History
303 lines (241 loc) · 8.95 KB

File metadata and controls

303 lines (241 loc) · 8.95 KB

API Reference

All endpoints are served by the FastAPI backend under the version prefix /api/v1. Interactive docs are always available while the backend runs:

Base URL (local): http://localhost:8000/api/v1

Routes are thin — they validate input, call a service, and return a Pydantic schema. This reference is hand-maintained; the live /docs is the source of truth for exact field types.


Conventions

  • All request/response bodies are JSON.
  • Timestamps are ISO-8601 UTC strings; some market fields use Unix ms.
  • Money is USDT; percentages are decimals (0.015 = 1.5%) unless a field name ends in _pct and is documented as already-multiplied.
  • Errors return { "detail": "<message>" } with a 4xx/5xx status.

System

GET /health

Liveness check (note: not under /api/v1).

{ "status": "ok", "version": "0.1.0", "env": "development", "testnet": true }

Auth — /auth

Binance API key management. Keys are validated against Binance before saving; the secret is never returned.

POST /auth/keys — validate & save credentials

// request
{ "api_key": "", "api_secret": "", "testnet": true }
// response 200
{ "configured": true, "testnet": true, "key_preview": "abcd1234…" }
// 400 if Binance rejects the keys

GET /auth/keys — credential status

{ "configured": true, "testnet": true, "key_preview": "abcd1234…" }

DELETE /auth/keys — clear credentials → 204 No Content


Bot — /bot

Lifecycle control. State machine lives in services/bot_engine.py.

GET /bot/status

{
  "state": "running",            // running | stopped | paused | error
  "uptime_seconds": 3600,
  "current_cycle": 12,
  "circuit_breaker_active": false,
  "last_error": null,
  "last_cycle_time": "2026-06-18T00:30:00+00:00",
  "open_position": {
    "symbol": "BTCUSDT", "side": "BUY", "entry_price": 65000.0,
    "quantity": 0.001, "entry_time": "", "order_id": "123"
  }
}

POST /bot/command — start / stop / pause / resume

// request
{ "command": "start" }   // start | stop | pause | resume
// response: a BotStatus object (as above)
  • start fetches the opening balance (circuit-breaker baseline) and runs the strategy loop immediately, then every 15 min.
  • resume lifts a manual pause but not a circuit-breaker pause.

POST /bot/kill — emergency stop

Cancels all open Binance orders, clears the position, stops the bot. Returns a BotStatus.

POST /bot/reset-circuit-breaker

Clears the circuit-breaker flag and resumes. Investigate the root cause first; if the account is still down ≥ 2% it re-trips. Returns a BotStatus.


Strategy — /strategy

GET /strategy/

{
  "symbol": "BTCUSDT", "timeframe": "15m",
  "bb_period": 20, "bb_std_dev": 2.0,
  "volume_ma_period": 30, "stop_loss_pct": 0.015
}

PUT /strategy/ — update parameters

Body = a full StrategyConfig (same shape as above). Takes effect on the next cycle; the live strategy singleton is rebuilt immediately. Returns the saved config.

GET /strategy/preview — dry-run the current strategy

Runs the strategy against current Binance data without placing an order.

{
  "direction": "long",            // long | short | neutral
  "reason": "Price 64000 crossed below lower band 64200 …",
  "confidence": 0.42,
  "metadata": { "upper_band": 65800.0, "middle_band": 65000.0, "lower_band": 64200.0,
                "std_dev": 312.8, "percent_b": -0.05, "volume_filter_ok": true }
}

Trades — /trades

Read-only. Writes happen via the bot engine → repository, never here.

GET /trades/ — paginated history

Query: page (≥1), page_size (1–200), symbol (optional), status (open|closed, optional).

{
  "total": 42, "page": 1, "page_size": 50,
  "trades": [{
    "id": 1, "symbol": "BTCUSDT", "side": "BUY",
    "entry_price": 65000.0, "exit_price": 65800.0, "quantity": 0.001,
    "entry_time": "", "exit_time": "",
    "pnl_usdt": 0.8, "pnl_pct": 0.0123,
    "exit_reason": "mean_revert", "status": "closed"
  }]
}

GET /trades/open — open positions (enriched with live price)

[{
  "symbol": "BTCUSDT", "side": "BUY", "entry_price": 65000.0, "quantity": 0.001,
  "entry_time": "", "current_price": 65500.0,
  "unrealised_pnl_usdt": 0.5, "unrealised_pnl_pct": 0.0077
}]

Falls back to the stored snapshot price if the live lookup fails.

GET /trades/{trade_id} — one trade (404 if missing)


Performance — /performance

Computed from closed trades via services/performance_service.py + backtest/metrics.py. Requires the database.

GET /performance/

Query: from_date, to_date (optional ISO dates; all-time by default).

{
  "total_pnl_usdt": 25.0, "total_pnl_pct": 0.025,
  "win_rate": 0.66, "total_trades": 9, "winning_trades": 6, "losing_trades": 3,
  "avg_win_usdt": 8.0, "avg_loss_usdt": -4.0,
  "profit_factor": 3.0, "sharpe_ratio": 1.85, "max_drawdown_pct": 0.04,
  "best_trade_pnl_usdt": 17.5, "worst_trade_pnl_usdt": -9.0,
  "daily_pnl": [{ "date": "2026-06-16", "pnl_usdt": 5.0, "pnl_pct": 0.0, "trade_count": 2 }]
}

profit_factor and sharpe_ratio are null when undefined (no losses / <2 data points).

GET /performance/today

{ "date": "2026-06-18", "pnl_usdt": 3.0, "pnl_pct": 0.003, "trade_count": 1 }

Alerts — /alerts

Telegram notification toggles. Bot token + chat id come from .env, not these endpoints.

GET /alerts/

{ "enabled": true, "trade_notifications": true, "daily_summary": true,
  "circuit_breaker_alerts": true, "error_alerts": true }

PUT /alerts/ — update toggles (takes effect immediately)

Body = an AlertConfig (same shape). Returns the updated config.

POST /alerts/test — send a test message

{ "success": true, "message": "Test message sent — check Telegram." }
// success:false with the reason if creds are missing or Telegram rejects it

Backtest — /backtest

Runs as a background job; poll for the result.

POST /backtest/202 Accepted

// request
{
  "symbol": "BTCUSDT", "timeframe": "15m",
  "from_date": "2026-05-18", "to_date": "2026-06-17",
  "bb_period": 20, "bb_std_dev": 2.0, "volume_ma_period": 30,
  "stop_loss_pct": 0.015, "initial_capital": 10000, "fee_pct": 0.001
}
// response
{ "job_id": "0455dc63a333", "status": "pending", "trades": [] }

GET /backtest/{job_id} — poll for results

{
  "job_id": "0455dc63a333", "status": "complete",  // pending|running|complete|failed
  "symbol": "BTCUSDT", "timeframe": "15m",
  "initial_capital": 10000, "final_capital": 10061.21, "candles_processed": 1356,
  "total_pnl_usdt": 61.21, "total_pnl_pct": 0.0061,
  "win_rate": 0.72, "total_trades": 25,
  "profit_factor": 2.09, "sharpe_ratio": 5.45, "max_drawdown_pct": 0.0019,
  "trades": [{ "entry_time": "", "exit_time": "", "side": "BUY",
               "entry_price": 63387.96, "exit_price": 63500.0,
               "quantity": 0.015, "pnl_usdt": 1.5, "pnl_pct": 0.0017,
               "exit_reason": "mean_revert" }]
}
// on failure: { "job_id": "…", "status": "failed", "error": "…", "trades": [] }

Jobs are held in a process-local dict (fine for single-user; move to Redis/DB for multi-worker).


Market — /market

Live Binance data. Public endpoints (ticker/price/candles) work without API keys; account/balance requires them.

GET /market/ticker/{symbol}

{ "symbol": "BTCUSDT", "price": 65802.3, "price_change_24h_pct": -0.03,
  "high_24h": 66984.4, "low_24h": 54616.9, "volume_24h": 747.99 }

GET /market/price/{symbol} — lightweight

{ "symbol": "BTCUSDT", "price": 65802.3 }

GET /market/candles/{symbol}

Query: timeframe (default 15m), limit (1–1000). Returns closed candles (the open candle is dropped).

[{ "open_time": 1781541584284, "open": 65000.0, "high": 65100.0, "low": 64900.0,
   "close": 65050.0, "volume": 12.3, "close_time": 1781542484283 }]

GET /market/bollinger/{symbol} — live BB snapshot + signal

{ "upper_band": 65800.0, "middle_band": 65000.0, "lower_band": 64200.0,
  "current_price": 65050.0, "std_dev": 312.8, "signal": "neutral" }

GET /market/account/balance — requires API keys

{ "free_usdt": 9000.0, "locked_usdt": 0.0, "total_usdt": 9000.0,
  "free_btc": 0.015, "locked_btc": 0.0, "total_btc": 0.015,
  "btc_price": 65000.0, "portfolio_value_usdt": 9975.0 }

GET /market/server/status

{ "server_time_ms": 1781541584284, "testnet": true }

Error responses

Status Meaning
400 Bad request (e.g. Binance rejected API keys)
404 Resource not found (unknown trade id / backtest job)
422 Validation error (bad query/body params)
502 Upstream Binance call failed
500 Server/DB error (e.g. Postgres not running for /trades, /performance)