EventTrader
AI-Native Trading
PAPER
Menu
Dark Mode
Plain English Mode
PAPER TRADING MODE — Enable real trading on your Account page
Back
REST + WebSocket + MCP

Backtest API & SDK

Run strategy backtests, browse the bot leaderboard, clone bots, and paper trade — all via API.

11
API Endpoints
3
Strategy Types
20
Max Concurrent
WS
Real-Time Stream

Quick Start

# Run a funding rate backtest
curl -X POST https://cymetica.com/api/v1/backtest-labs/run \
  -H "Content-Type: application/json" \
  -d '{"type":"funding_rate","params":{"coin":"BTC","days":30,"capital":10000,"leverage":1,"strategy":"cross_exchange"}}'

# Get bot leaderboard
curl https://cymetica.com/api/v1/backtest/leaderboard?sort=return&limit=10
from event_trader import EventTrader

client = EventTrader(api_key="evt_...")

# Run a backtest
result = await client.backtest.run_lab(
    type="funding_rate",
    params={"coin": "BTC", "days": 30, "capital": 10000}
)

# Get leaderboard
leaderboard = await client.backtest.leaderboard(sort="return", limit=10)

# Get bot profile
bot = await client.backtest.bot("cryptobull-blue")

The JS/TS SDK's npm release is in progress — these snippets show the interface it ships with. The Python SDK and the REST API are live today.

import { EventTrader } from "cymetica-eventtrader";

const client = new EventTrader({ apiKey: "evt_..." });

// Run a backtest
const result = await client.backtest.runLab({
  type: "funding_rate",
  params: { coin: "BTC", days: 30, capital: 10000 }
});

// Get leaderboard
const leaderboard = await client.backtest.leaderboard({ sort: "return", limit: 10 });

// Get bot profile
const bot = await client.backtest.bot("cryptobull-blue");
# Python
pip install cymetica-eventtrader

# TypeScript / Node.js — npm release in progress; Python SDK is live today
# npm install cymetica-eventtrader

Authentication

Most read endpoints are public (no auth required). Write operations use one of two methods depending on the endpoint family: Backtest Labs runs (/api/v1/backtest-labs/*) authenticate with an API key (X-API-Key header), while bot management (clone, trigger run, update settings) requires a Bearer token from a logged-in session.

# Authenticated request
curl -H "Authorization: Bearer $EVENTTRADER_API_KEY" \
  https://cymetica.com/api/v1/backtest/bots/your-bot-slug/run-backtest

Get your API key from /account → API Keys.

Which backtest surface?

Five surfaces, all current, each answering a different question. None supersedes another. The machine-readable spec of record is openapi-public.json, llms.txt and the MCP tools list_backtest_surfaces / get_backtest_models; this page mirrors them.

PageAnswersAPIAuth
/backtestHow has a specific clone-able bot performed, and can I clone it?GET /api/v1/backtest/bots/{slug}, /equity, /trades, GET /api/v1/backtest/leaderboard, POST /api/v1/backtest/clonereads: none · writes: Bearer
/backtest-labsWhat would one parameterised strategy have returned on one asset?POST /api/v1/backtest-labs/runtype: cross_exchange_arb | funding_rate | dex_replayX-API-Key
/backtest-rallyWhich theme basket beat BTC under a research model, then launch it as a rally card?GET /api/v1/research-backtest/models, /themes, POST /api/v1/research-backtest/run, GET /runs, /runs/{run_id}, /queue, /leaderboardnone (30/min per IP; 2 in-flight runs per anonymous IP, 5 per account)
/events/builderWould an event-card idea have paid off historically?POST /api/v1/event-cards/backtest-ideanone (30/min per IP)
/macromarketBuild an AI Index Basket from a macro theme, backtest and paper-trade it.POST /api/v1/macromarket/build, /backtest, /paper-tradeBearer

Backtest Labs

Run one parameterised strategy on one asset. Accepted type values: cross_exchange_arb (cross-exchange arbitrage), funding_rate (perp funding-rate capture) and dex_replay (DEX trade replay with params.strategy = mean_reversion | momentum | lp_vs_hold). Any other type returns {"error":"Unknown backtest type. Supported: cross_exchange_arb, funding_rate, dex_replay"}. Max 20 concurrent backtests via Redis queue.

POST /api/v1/backtest-labs/run Run a strategy backtest

Request Body

typestringStrategy type: cross_exchange_arb, funding_rate, dex_replay (for dex_replay, params.strategy = mean_reversion | momentum | lp_vs_hold)
params.coinstringAsset symbol (BTC, ETH, SOL, etc.)
params.daysintegerLookback period in days
params.capitalnumberStarting capital in USDC
params.leveragenumberLeverage multiplier
params.strategystringStrategy variant (e.g., cross_exchange)
curl -X POST https://cymetica.com/api/v1/backtest-labs/run \
  -H "Content-Type: application/json" \
  -d '{
    "type": "funding_rate",
    "params": {
      "coin": "BTC",
      "days": 30,
      "capital": 10000,
      "leverage": 1,
      "strategy": "cross_exchange"
    }
  }'
result = await client.backtest.run_lab(
    type="funding_rate",
    params={"coin": "BTC", "days": 30, "capital": 10000, "leverage": 1, "strategy": "cross_exchange"}
)
const result = await client.backtest.runLab({
  type: "funding_rate",
  params: { coin: "BTC", days: 30, capital: 10000, leverage: 1, strategy: "cross_exchange" }
});

Multi-Leg Backtesting — Baskets, AIBs and Themes

Backtest Labs above runs a strategy against one asset. To backtest a basket — several legs with weights — use the endpoints below. Basket symbols (AIB-, TREND-, EVCDX-, RALLY-, MM-) are not accepted by the single-asset endpoints. All results describe the past and are never a predicted return.

POST /api/v1/event-cards/backtest-idea Backtest a basket you define (no auth)

The API behind the “Backtest this idea” widget on /events/builder. Read-only: no card is created, no ledger or on-chain write happens, no money moves. Runs the same engine as the saved-card backtest, so an idea and a published card holding the same basket return identical numbers.

Request Body

constituentsarray2–20 legs of {symbol, weight} (optional coingecko_id). Weights are relative and renormalized, so 50/30/20 equals 5/3/2.
period_daysintegerOne of 7, 30, 90, 180, 365. Anything else returns 422.
starting_capitalnumberNotional to simulate. 0 < x ≤ 1,000,000.
fee_ratenumberPer-trade fee, 0–0.1 (0.001 = 10bps). Optional.
slippage_bpsnumberSlippage in basis points, 0–500. Optional.

Response

total_return_pctnumberReturn over the window, in percent.
sharpe_rationumberRisk-adjusted return.
max_drawdown_pctnumberDeepest peak-to-trough decline.
starting_capital_usdc
ending_capital_usdc
numberSimulated capital at each end of the window.
equity_curvearrayCurve points (count in n_points).
unresolved_symbols
dropped_symbols
arrayLegs that could not be priced and were excluded. Always check these before trusting the numbers.
curl -X POST https://cymetica.com/api/v1/event-cards/backtest-idea \
  -H "Content-Type: application/json" \
  -d '{
    "constituents": [
      {"symbol": "BTC", "weight": 50},
      {"symbol": "ETH", "weight": 30},
      {"symbol": "SOL", "weight": 20}
    ],
    "period_days": 90,
    "starting_capital": 10000
  }'
result = await client.basket_backtest.run(
    constituents=[("BTC", 50), ("ETH", 30), ("SOL", 20)],
    period_days=90,
    starting_capital=10_000,
)
print(result["total_return_pct"], result["sharpe_ratio"])
print(result["unresolved_symbols"], result["dropped_symbols"])
const result = await client.basketBacktest.run({
  constituents: [
    { symbol: "BTC", weight: 50 },
    { symbol: "ETH", weight: 30 },
    { symbol: "SOL", weight: 20 },
  ],
  periodDays: 90,
  startingCapital: 10000,
});
console.log(result.total_return_pct, result.sharpe_ratio);
et_basket_backtest(
  constituents=[
    {"symbol": "BTC", "weight": 50},
    {"symbol": "ETH", "weight": 30},
    {"symbol": "SOL", "weight": 20}
  ],
  period_days=90,
  starting_capital=10000
)
POST /api/v1/macromarket/build Build an AI Index Basket from a theme

Give it a plain-language theme and the Tuatara semantic model selects real trading vehicles (stocks, ETFs, crypto) and weights them by relevance. The basket gets an MM-… symbol and a /macromarket page.

Request Body

themestringe.g. "AI infrastructure".
num_assetsintegerHow many legs to select. Default 6.
weightingstringtuatara (relevance-weighted) or equal.
asset_classesarraySubset of crypto, equity. Omit for both.
curl -X POST https://cymetica.com/api/v1/macromarket/build \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $EVENTTRADER_API_KEY" \
  -d '{"theme": "AI infrastructure", "num_assets": 8, "weighting": "tuatara"}'
aib = await client.macromarket.build("AI infrastructure", num_assets=8)
print(aib["symbol"])   # e.g. "MM-AIINFRA"
const aib = await client.macromarket.build({
  theme: "AI infrastructure",
  numAssets: 8,
});
et_aib_build(theme="AI infrastructure", num_assets=8, weighting="tuatara")
POST /api/v1/macromarket/backtest Backtest an AIB by symbol, or a theme

Pass aib_symbol for an existing basket, or theme to build and persist one first. Quota-gated: an over-quota caller gets 402 before any expensive work runs. Results are simulated, not investment advice.

Request Body

aib_symbolstringAn existing MM-… symbol. Required unless theme is given.
themestringBuild a basket from this theme, then backtest it.
period_daysintegerLookback window. Default 365.
curl -X POST https://cymetica.com/api/v1/macromarket/backtest \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $EVENTTRADER_API_KEY" \
  -d '{"aib_symbol": "MM-AIINFRA", "period_days": 365}'
bt = await client.macromarket.backtest(aib_symbol="MM-AIINFRA", period_days=365)

# Or skip the build entirely and backtest a theme directly:
bt = await client.macromarket.backtest(theme="uranium miners")
const bt = await client.macromarket.backtest({
  aibSymbol: "MM-AIINFRA",
  periodDays: 365,
});
et_aib_backtest(aib_symbol="MM-AIINFRA", period_days=365)
et_aib_backtest(theme="uranium miners")
POST /api/v1/research-backtest/run Backtest a theme or ticker list (Rally engine)

The headline-basket research engine behind /backtest-rally. Races strategies against BTC and can launch the winner as a Rally Card. Signal/backtest only — no orders are placed. Full reference: /backtest-rally/api.

curl -X POST https://cymetica.com/api/v1/research-backtest/run \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $EVENTTRADER_API_KEY" \
  -d '{"themes": ["ai tokens"], "algo_model": "aib_sentiment", "hold_days": 2}'
run = await client.research_backtest.run(
    themes=["defi tokens", "ai tokens"], hold_days=2)
result = await client.research_backtest.get(run["run_id"])
await client.research_backtest.launch_rally_card(run["run_id"], basket_index=0)
const run = await client.researchBacktest.run({
  themes: ["defi tokens", "ai tokens"],
  params: { hold_days: 2 },
});
const result = await client.researchBacktest.get(run.run_id);
et_research_backtest_run(params={"themes": ["ai tokens"], "hold_days": 2})
et_research_backtest_launch_rally_card(run_id="<run_id>", basket_index=0)

Bot Leaderboard

Browse ranked AI trading bots with sorting and filtering. 60-second cache on leaderboard results.

GET /api/v1/backtest/leaderboard Get bot leaderboard

Query Parameters

sortstringSort by: return (headline return, desc), clones, win_rate, drawdown (asc). Default: return. Unknown values fall back to return.
categorystringFilter by category: all, crypto, politics, sports, finance (default: all)
teamstringFilter by team: all, red, blue
limitintegerMax results, 1–100 (default: 20)
offsetintegerPagination offset (default: 0)
periodstringHeadline-period filter, e.g. 30d, 6m, 24h (default: all). headline_return_pct is measured over each bot's own window and is NOT comparable across periods, so rank within one. Every row carries headline_period and headline_period_hours.
curl "https://cymetica.com/api/v1/backtest/leaderboard?sort=return&team=red&period=30d&limit=10"
leaderboard = await client.backtest.leaderboard(sort="return", team="red", limit=10)
const lb = await client.backtest.leaderboard({ sort: "return", team: "red", limit: 10 });

Bot Profiles

Get bot details, equity curves, and trade history. 60-second cache on profile data.

GET /api/v1/backtest/bots/{slug} Get bot profile

Path Parameters

slugstringBot slug identifier
curl https://cymetica.com/api/v1/backtest/bots/cryptobull-blue
GET /api/v1/backtest/bots/{slug}/equity Get equity curve

Returns time-series equity data for charting the bot's portfolio value over time.

curl https://cymetica.com/api/v1/backtest/bots/cryptobull-blue/equity
GET /api/v1/backtest/bots/{slug}/trades Get trade history

Query Parameters

limitintegerMax trades (default: 50)
offsetintegerPagination offset (default: 0)
curl "https://cymetica.com/api/v1/backtest/bots/cryptobull-blue/trades?limit=10"

Bot Operations

Run backtests and update settings. These endpoints require authentication.

POST /api/v1/backtest/bots/{slug}/run-backtest Run backtest AUTH

Triggers a new backtest run for the specified bot (Bearer token; no request body — the bot's own strategy, top-10 asset universe and a 30-day window are used). Responds immediately with {"run_id", "status": "queued", "slug"}; the refreshed results appear on the bot's profile and the leaderboard when the async run completes. Also callable as the MCP tool et_backtest_bot_run.

curl -X POST https://cymetica.com/api/v1/backtest/bots/your-bot-slug/run-backtest \
  -H "Authorization: Bearer $EVENTTRADER_API_KEY"

# 200 → {"run_id": "…", "status": "queued", "slug": "your-bot-slug"}
# then stream progress on wss://cymetica.com/ws/backtest/{instance_id}?run_id={run_id}
PATCH /api/v1/backtest/bots/{slug}/settings Update bot settings AUTH

Request Body

namestringNew bot name (optional)
avatar_urlstringNew avatar URL (optional)
curl -X PATCH https://cymetica.com/api/v1/backtest/bots/your-bot-slug/settings \
  -H "Authorization: Bearer $EVENTTRADER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Alpha Bot v3"}'

Bot Cloning

Clone bot species into new instances. Cloned bots get dedicated HD wallets (account 4 derivation path). Requires authentication.

POST /api/v1/backtest/clone Clone a bot AUTH

Request Body

species_slugstringSpecies slug to clone from
namestringName for the new cloned bot
curl -X POST https://cymetica.com/api/v1/backtest/clone \
  -H "Authorization: Bearer $EVENTTRADER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"species_slug": "cryptobull-blue", "name": "My Momentum Clone"}'
GET /api/v1/backtest/clone/deposit-info/{species_slug} Get clone deposit info AUTH

Returns deposit address and minimum deposit required to activate a cloned bot.

curl https://cymetica.com/api/v1/backtest/clone/deposit-info/cryptobull-blue \
  -H "Authorization: Bearer $EVENTTRADER_API_KEY"

Paper Trading

View paper trades and paper trading status for bots running in simulation mode.

GET /api/v1/backtest/bots/{slug}/paper-trades Get paper trades

Query Parameters

statusstringFilter: open, closed, all
limitintegerMax trades (default: 50)
offsetintegerPagination offset (default: 0)
curl "https://cymetica.com/api/v1/backtest/bots/cryptobull-blue/paper-trades?status=open&limit=20"
GET /api/v1/backtest/bots/{slug}/paper-status Get paper trading status

Returns current paper trading status including P&L, open positions, and account balance.

curl https://cymetica.com/api/v1/backtest/bots/cryptobull-blue/paper-status

WebSocket — Real-Time Backtest Updates

Stream real-time backtest progress and results via WebSocket.

WS wss://cymetica.com/ws/backtest/{instance_id}?run_id={run_id} Backtest progress stream

Message Types

stateeventBacktest state change (queued, running, completed, failed)
progresseventProgress update with percentage and current step
completedeventFinal results with performance metrics
failedeventError details on failure
heartbeateventKeep-alive ping
// JavaScript WebSocket example
const ws = new WebSocket("wss://cymetica.com/ws/backtest/bot-123?run_id=run-456");
ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  switch (msg.type) {
    case "progress":
      console.log(`${msg.percent}% — ${msg.step}`);
      break;
    case "completed":
      console.log("Results:", msg.results);
      break;
    case "failed":
      console.error("Error:", msg.error);
      break;
  }
};

Rate Limits

Backtest runslimitMax 20 concurrent backtests (Redis queue). Additional requests are queued.
Leaderboardcache60-second cache on leaderboard and profile data.
API callslimitStandard rate limits apply (60 req/min for authenticated, 30 req/min for public).

MCP Tools

Two MCP surfaces. The hosted server at https://cymetica.com/mcp/v1 (JSON-RPC tools/list / tools/call, no install) exposes list_backtest_surfaces, get_backtest_models and get_strategy_returns (accepts cryptobull-blue, cryptobull_blue or bt-cryptobull-blue; returns the latest run's metrics with its measurement period plus the leaderboard headline figure and its window). The installable server (pip install cymetica-eventtrader-mcp) ships the full endpoint mirror below — these et_backtest_* names come from that package.

et_backtest_runtoolRun a backtest in Backtest Labs
et_backtest_leaderboardtoolGet bot leaderboard
et_backtest_bot_profiletoolGet bot profile
et_backtest_bot_equitytoolGet bot equity curve
et_backtest_bot_tradestoolGet bot trade history
et_backtest_bot_runtoolTrigger a backtest run
et_backtest_bot_settingstoolUpdate bot settings
et_backtest_clonetoolClone a bot
et_backtest_clone_deposit_infotoolGet clone deposit info
et_backtest_paper_tradestoolGet paper trades
et_backtest_paper_statustoolGet paper trading status