Skip to content

Latest commit

 

History

History
236 lines (183 loc) · 6.9 KB

File metadata and controls

236 lines (183 loc) · 6.9 KB

API Reference

Base URL (development): http://localhost:8000

Interactive documentation generated by FastAPI is available at /docs (Swagger UI) and /redoc while the server runs. This file is a hand-written companion describing the shapes the official clients rely on.

All endpoints exist under a versioned prefix (/api/v1/...). Non-versioned aliases (/api/...) are also mounted for backward compatibility and are hidden from the schema.

Conventions

  • Requests and responses are JSON.
  • Money and ratios are numbers, not strings. Percentages in allocation are 0–100; fractions like maxDrawdown and volatility are 0–1 unless noted.
  • The data endpoints (portfolio, strategies, risk, backtest, market data, trading, research, alternative data) are currently open. Authentication applies to /api/auth.

Health

GET /health
GET /

Returns a small status object indicating the service is alive.

Authentication - /api/auth

Tokens are HS256 JWTs. Send the token as Authorization: Bearer <token> on subsequent requests.

Register

POST /api/auth/register
{
  "email": "trader@example.com",   // email or username
  "name": "Ada Lovelace",          // optional
  "password": "a-strong-password"
}
→ 201 { "token": "<jwt>", "user": { "id", "email", "name" } }

Login

POST /api/auth/login
{ "email": "trader@example.com", "password": "a-strong-password" }
→ 200 { "token": "<jwt>", "user": { ... } }
→ 401 on bad credentials

Refresh / Profile

POST /api/auth/refresh   → { "token": "<jwt>" }
GET  /api/auth/profile   → { "id", "email", "name" }

Portfolio - /api/v1/portfolio

GET /api/v1/portfolio/
→ {
    "totalValue": number,
    "cash": number,
    "dailyPnL": number,
    "totalPnL": number,
    "allocation": [ { "ticker": string, "value": number, "percentage": number } ]
  }

GET /api/v1/portfolio/positions
→ [ { "ticker", "quantity", "entryPrice", "currentPrice", "unrealizedPnL", "weight" } ]

GET /api/v1/portfolio/holdings
→ [ { "symbol", "value", "weight" } ]

GET /api/v1/portfolio/performance
→ {
    "equityCurve": [ { "timestamp": string, "value": number } ],
    "metrics": { "sharpeRatio": number, ... }
  }

Strategies - /api/v1/strategies

GET /api/v1/strategies/
→ [ {
    "id", "name", "status",
    "performance": {
      "sharpeRatio", "maxDrawdown", "profitFactor",
      "winRate", "totalReturn", "volatility", "alpha", "beta"
    }
  } ]

GET /api/v1/strategies/{id}/equity-curve
→ { "equityCurve": [ { "day": number, "value": number, "benchmark": number } ] }

Risk - /api/v1/risk

GET /api/v1/risk/metrics
→ {
    "var": number,           // value at risk (% of NAV)
    "cvar": number,
    "sharpeRatio": number,
    "sortinoRatio": number,
    "maxDrawdown": number,   // fraction
    "beta": number,
    "correlation": number,
    "volatility": number     // fraction
  }

GET /api/v1/risk/stress-scenarios
→ [ { "name", "pnl", "duration", "recovery", "portfolioImpact" } ]

GET /api/v1/risk/radar
→ [ { "metric": string, "value": number } ]

Backtest - /api/v1/backtest

POST /api/v1/backtest/
{
  "strategyId": string,
  "startDate": "YYYY-MM-DD",
  "endDate": "YYYY-MM-DD",
  "initialCapital": number
}
→ {
    "id", "strategyId", "startDate", "endDate", "initialCapital", "finalCapital",
    "totalReturn", "annualisedReturn", "sharpeRatio", "sortinoRatio", "calmarRatio",
    "maxDrawdown", "maxDrawdownDuration", "winRate", "profitFactor", "totalTrades",
    "avgWin", "avgLoss", "bestMonth", "worstMonth",
    "equityCurve": [ { "date", "equity", "benchmark", "drawdown" } ]
  }

The result fields are flat (not nested under a metrics object). This genuinely executes the strategy via app/services/backtest_runner.py: rl_agent and ml_alpha strategies train and evaluate a real ai_models agent/forecaster, while momentum and mean_reversion run rule-based logic - all against a synthetic (seeded, reproducible) price series. Because training happens synchronously in the request, an rl_agent/ml_alpha backtest can take a few seconds; see POST /api/v1/strategies/backtest below for a fire-and-forget alternative.

Returns 404 if strategyId doesn't exist, 422 if the strategy's type isn't one of momentum / mean_reversion / ml_alpha / rl_agent.

Alternative: async backtest via the strategies router

POST /api/v1/strategies/backtest
{ "strategyId": string, "startDate": "YYYY-MM-DD", "endDate": "YYYY-MM-DD", "initialCapital": number }
→ 202 { "id", "strategyId", "status": "pending", ... }

Returns immediately with status: "pending" and runs the same simulation as a background task, moving through "running" to "completed"/"failed". Poll GET /api/v1/strategies/backtests/{id} for the result, which has a smaller field set: finalCapital, totalReturn, sharpeRatio, maxDrawdown, totalTrades, winRate, status, errorMessage (set if status is "failed").

Market Data - /api/v1/market-data

GET /api/v1/market-data/quotes
→ [ {
    "ticker", "timestamp", "bid", "ask", "last",
    "volume", "high", "low", "open", "close",
    "source": "live" | "synthetic"
  } ]

GET /api/v1/market-data/quote/{ticker}
→ single quote object (shape as above)

GET /api/v1/market-data/historical/{ticker}?days=90
→ [ { "timestamp", "open", "high", "low", "close", "volume" } ]

source reports whether the row came from a live connector (Yahoo Finance / Polygon) or the synthetic fallback.

Trading - /api/v1/trading

Trading is simulated in-process; there is no live broker.

GET    /api/v1/trading/orders            → [ Order ]
GET    /api/v1/trading/orders/{id}       → Order
POST   /api/v1/trading/orders            → 201 Order
DELETE /api/v1/trading/orders/{id}       → 204

OrderCreate (POST body):
{
  "ticker": string,
  "side": "BUY" | "SELL",
  "quantity": number,
  "orderType": "MARKET" | "LIMIT" | "STOP",
  "price": number        // required for LIMIT and STOP
}

Order:
{
  "id", "ticker", "side", "quantity", "orderType",
  "price?", "filledPrice?", "status", "timestamp?", "filledAt?"
}

MARKET orders fill immediately and cannot be cancelled. LIMIT and STOP orders stay pending and can be cancelled with DELETE.

Research - /api/v1/research

GET /api/v1/research/papers
→ [ { "id", "title", "authors": [string], "abstract", "category", "year", "url?" } ]

Also available as /api/research/papers.

Alternative Data - /api/v1/alternative-data

GET /api/v1/alternative-data/sources
→ [ {
    "id", "name",
    "type": "satellite" | "sentiment" | "sec" | "social",
    "status": "active" | "inactive",
    "lastUpdate", "dataPoints",
    "description?", "latency?"
  } ]

CORS

In development the API accepts cross-origin requests from localhost, 127.0.0.1, and private LAN IP ranges on any port, so the web dashboard (port 3000) and the Expo web build (port 8081) can both call it. Configure with CORS_ORIGINS.