EventTrader

Prediction Market Platform
PAPER
Menu
Trade
Home How It Works AI Hedge Fund Backtest Backtest Labs Neural Trading (BCI) Exchange LP Rewards Perpetuals Markets Winner Takes All AI Agent Liquidity Tokens About ET10 Vaults Swap Terminal
Agents
AI Agents (Blue Team) AI Agents (Red Team) AgentBook Marketplace Algos, Data & Models Skills & Tools
Launchpad
Launch Prediction Market Launch Token Dashboard
Compete
Competitions Backtest Leaderboard Feature Leaderboard Robinhood Testnet Agents Bug Leaderboard
Vote
Token Vote Voting Hub Trend Voting
Learn
Beginner's Guide Trading Guide Clone a Bot Guide Market Making Guide Profit Guide Launch Guide Backtest Guide Swap Guide Robinhood Chain Guide
Explore
Satellite Intelligence Backtest Robinhood Testnet Analytics API About
Account
Log In Sign Up My Account Transactions My Agents My Profile
Voting Rewards Log Out
Connect
Discord Telegram X (Twitter) Contact
PAPER TRADING MODE — Enable real trading on your Account page
Back
REST + WebSocket + MCP + SDK

CyMetica-42 Arena API

Trade shares on Blue Team vs Red Team AI hedge fund agents. CLOB orderbook, real-time WebSocket, MCP tools for AI agents, and Python SDK with copy/paste bot examples.

11
REST Endpoints
5
WebSocket Channels
7
MCP Tools
5
Bot Examples

Quick Start

# Get arena market state (teams, NAVs, scoreboard)
curl https://cymetica.com/api/v1/arena/market

# Get BLUE team orderbook
curl https://cymetica.com/api/v1/arena/orderbook/BLUE?levels=30

# Place a limit buy on BLUE at $0.55
curl -X POST https://cymetica.com/api/v1/arena/order \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"team_symbol":"BLUE","side":"buy","price":0.55,"size":10,"user_address":"0x...","order_type":"limit"}'

# Get your positions
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://cymetica.com/api/v1/arena/positions
from event_trader import EventTrader

async with EventTrader(api_key="evt_...") as client:
    # Get market state
    state = await client.arena.market()
    blue = state["blue_team"]
    print(f"Blue NAV: ${blue['nav']:.2f}  PnL: {blue['epoch_pnl_pct']:+.2f}%")

    # Get orderbook
    book = await client.arena.orderbook("BLUE", levels=10)

    # Place a limit buy — $10 of BLUE at $0.55 (55% implied probability)
    order = await client.arena.place_order("BLUE", "buy", 10.0, price=0.55)
    print(f"Order: {order['order_id'][:8]}  fills={len(order['fills'])}")

    # Cancel order
    await client.arena.cancel_order(order["order_id"])

    # Check positions
    pos = await client.arena.positions()
    for p in pos["positions"]:
        print(f"  {p['team_symbol']}: {p['shares']} shares @ ${p['avg_entry_price']}")
// Connect to Arena WebSocket
const ws = new WebSocket("wss://cymetica.com/ws/arena?token=YOUR_JWT");

ws.onmessage = (event) => {
    const msg = JSON.parse(event.data);

    switch (msg.type) {
        case "arena_state":       // Full state on connect
            console.log("Blue NAV:", msg.data.blue_team.nav);
            break;
        case "team_performance":  // Real-time NAV updates
            console.log("Update:", msg.data);
            break;
        case "orderbook_update":  // Book changes
            console.log(msg.team, "book:", msg.data);
            break;
        case "trade":             // Fill events
            console.log("Trade:", msg.data);
            break;
        case "epoch_resolved":    // Epoch result
            console.log("Winner:", msg.data.winning_team);
            break;
    }
};

// Heartbeat — send ping every 25s
setInterval(() => ws.send(JSON.stringify({type: "ping"})), 25000);
# Python SDK
pip install event-trader

# Production client
from event_trader import EventTrader
client = EventTrader.production(api_key="evt_...")

# Or with credentials
client = await EventTrader.from_credentials("user@email.com", "password")

Authentication

Market data endpoints (market state, orderbook, teams, epoch, history) are public. Trading and position endpoints require a Bearer token or API key.

# Bearer token (JWT)
curl -H "Authorization: Bearer YOUR_TOKEN" https://cymetica.com/api/v1/arena/positions

# API key
curl -H "X-API-Key: evt_..." https://cymetica.com/api/v1/arena/positions

Get your API key from /account → API Keys. Keys support permissions: read, trade.

Market Data (Public)

Public endpoints for arena state, teams, orderbook, epochs, and headlines. No authentication required.

GET /api/v1/arena/market Arena market state — teams, NAVs, epoch, scoreboard

Returns the full arena state including both team NAVs, epoch PnL, win counts, current epoch countdown, and arena configuration.

curl https://cymetica.com/api/v1/arena/market
Response
{
  "arena": { "id": "...", "blue_team_name": "Blue Team", "red_team_name": "Red Team", ... },
  "current_epoch": { "epoch_number": 42, "start_time": "...", "end_time": "..." },
  "blue_team": { "name": "Blue Team", "nav": 107.42, "epoch_pnl_pct": 2.15, "epoch_wins": 3 },
  "red_team": { "name": "Red Team", "nav": 94.18, "epoch_pnl_pct": -1.82, "epoch_wins": 2 }
}
GET /api/v1/arena/teams Team details + portfolio composition

Returns team names, NAV, PnL, win count, and the asset basket driving each team's performance.

curl https://cymetica.com/api/v1/arena/teams
Response
{
  "blue": {
    "name": "Blue Team", "nav": 107.42, "pnl_pct": 7.42, "epoch_wins": 3,
    "portfolio": { "BTC": {"weight": 0.3}, "ETH": {"weight": 0.3}, "SOL": {"weight": 0.2}, "SUI": {"weight": 0.2} }
  },
  "red": {
    "name": "Red Team", "nav": 94.18, "pnl_pct": -5.82, "epoch_wins": 2,
    "portfolio": { "AVAX": {"weight": 0.3}, "LINK": {"weight": 0.3}, "DOGE": {"weight": 0.2}, "PEPE": {"weight": 0.2} }
  }
}
GET /api/v1/arena/orderbook/{team} Live orderbook depth for BLUE or RED

Returns bids, asks, spread, best bid/ask for the specified team. Uses the WTA CLOB matching engine.

teampathBLUE or RED
levelsqueryMinimum price levels (default 30, max 1000)
curl https://cymetica.com/api/v1/arena/orderbook/BLUE?levels=10
Response
{
  "symbol": "BLUE",
  "bids": [{"price": "0.54", "size": "100.00", "cumulative": "100.00"}, ...],
  "asks": [{"price": "0.56", "size": "75.00", "cumulative": "75.00"}, ...],
  "spread": "0.02",
  "best_bid": "0.54",
  "best_ask": "0.56"
}
GET /api/v1/arena/epoch/current Current epoch info + countdown
curl https://cymetica.com/api/v1/arena/epoch/current
Response
{
  "epoch": {
    "epoch_number": 42,
    "start_time": "2026-04-02T12:00:00+00:00",
    "end_time": "2026-04-02T13:00:00+00:00",
    "total_pool": 5420.50,
    "resolved": false
  }
}
GET /api/v1/arena/epoch/{epoch_number} Historical epoch result
curl https://cymetica.com/api/v1/arena/epoch/41
Response
{
  "epoch_number": 41,
  "winning_symbol": "BLUE",
  "winning_pct_gain": 3.42,
  "total_pool": 4800.00,
  "resolved": true
}
GET /api/v1/arena/history Epoch history with winners
limitqueryMax epochs (1-100, default 20)
curl https://cymetica.com/api/v1/arena/history?limit=5
GET /api/v1/arena/headlines Headlines driving team performance

Returns recent headlines that influence team portfolios through hidden connections.

limitqueryMax headlines (1-50, default 10)
curl https://cymetica.com/api/v1/arena/headlines?limit=5

Trading (Authenticated)

Place and cancel orders, view positions. Requires Bearer token or API key with trade permission.

POST /api/v1/arena/order AUTH Place limit order on BLUE or RED book
team_symbolstring"BLUE" or "RED"
sidestring"buy" or "sell"
pricefloat$0.01 – $1.00 (implied win probability)
sizefloatOrder size in dollars (min: market min_bet)
user_addressstringUser wallet address
order_typestring"limit" (default) or "market"
post_onlyboolReject if order would cross book (default false)
curl -X POST https://cymetica.com/api/v1/arena/order \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "team_symbol": "BLUE",
    "side": "buy",
    "price": 0.55,
    "size": 10,
    "user_address": "0x...",
    "order_type": "limit"
  }'
order = await client.arena.place_order(
    "BLUE", "buy", 10.0, price=0.55
)
print(f"Order: {order['order_id']}")
print(f"Fills: {len(order['fills'])}")
print(f"Remaining: ${order['remaining']:.2f}")
const resp = await fetch("/api/v1/arena/order", {
    method: "POST",
    headers: {
        "Authorization": "Bearer " + token,
        "Content-Type": "application/json",
    },
    body: JSON.stringify({
        team_symbol: "BLUE",
        side: "buy",
        price: 0.55,
        size: 10,
        user_address: walletAddr,
        order_type: "limit",
    }),
});
const data = await resp.json();
Response
{
  "order_id": "a1b2c3d4-...",
  "status": "resting",
  "fills": [],
  "remaining": 10.0
}
DELETE /api/v1/arena/order/{order_id} AUTH Cancel a resting order
order_idpathOrder ID to cancel
user_addressqueryUser wallet address
curl -X DELETE "https://cymetica.com/api/v1/arena/order/a1b2c3d4?user_address=0x..."  \
  -H "Authorization: Bearer YOUR_TOKEN"
GET /api/v1/arena/positions AUTH User's arena positions (persistent across epochs)

Arena positions persist across epoch boundaries — they are NOT liquidated at resolution. Share value adjusts based on team NAV performance.

curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://cymetica.com/api/v1/arena/positions
Response
{
  "positions": [
    {
      "team_symbol": "BLUE",
      "shares": 20.0,
      "avg_entry_price": 0.52,
      "realized_pnl": 1.40,
      "entered_epoch_id": 38,
      "last_rollover_epoch_id": 41
    }
  ]
}
POST /api/v1/arena/seed AUTH Create initial arena market (idempotent)

Creates the arena WTA market, BLUE/RED assets, ArenaMarket config, and first epoch. Returns existing arena if one already exists.

blue_team_namestringDisplay name (max 200 chars, default "Blue Team")
red_team_namestringDisplay name (max 200 chars, default "Red Team")
epoch_duration_secondsint60 – 86400 seconds (default 3600 = 1 hour)
portfolio_configobjectOptional asset baskets per team

WebSocket

Real-time streaming at wss://cymetica.com/ws/arena. Optional JWT token via query param for authenticated streams.

WS /ws/arena Arena real-time stream

Message Types

arena_stateon connectFull arena state sent immediately on connection
team_performanceperiodicReal-time team NAV and PnL updates
orderbook_updateon changeOrderbook depth change for BLUE or RED (includes team field)
tradeon fillTrade fill event with price, size, side, team
epoch_resolvedon resolveEpoch resolution result with winning_team, NAVs
headline_eventon eventHeadline affecting team portfolio performance
heartbeat30sServer heartbeat (send {"type":"ping"} for pong)

MCP Tools (AI Agent Integration)

Model Context Protocol tools for AI agents. Discover at /.well-known/mcp. Public tools require no auth.

get_arena_statePUBLICGet Arena market state — teams, NAVs, epoch, scoreboard
get_arena_teamsPUBLICGet team details and portfolio composition
get_arena_orderbookPUBLICGet orderbook depth for BLUE or RED team
get_arena_epochPUBLICGet current epoch info with countdown
get_arena_historyPUBLICGet epoch history with winners
get_arena_positionsAUTHGet user's Arena positions
place_arena_orderAUTHPlace order on BLUE/RED orderbook
# MCP Discovery
curl https://cymetica.com/.well-known/mcp

# Direct MCP tool call
curl https://cymetica.com/mcp/tools/arena/state
curl https://cymetica.com/mcp/tools/arena/orderbook/BLUE?levels=10
curl https://cymetica.com/mcp/tools/arena/history?limit=5

Python SDK

All Arena endpoints are available via client.arena.* in the EventTrader Python SDK.

Installation

pip install event-trader

SDK Methods

arena.market()publicGet market state (teams, NAVs, epoch, scoreboard)
arena.teams()publicGet team details + portfolio composition
arena.orderbook(team, levels)publicGet orderbook depth for BLUE or RED
arena.current_epoch()publicGet current epoch + countdown
arena.epoch_result(n)publicGet historical epoch result
arena.history(limit)publicEpoch history with winners
arena.headlines(limit)publicHeadlines driving team performance
arena.place_order(...)authPlace limit/market order on BLUE or RED book
arena.cancel_order(id)authCancel a resting order
arena.positions()authGet your positions (persistent across epochs)
arena.seed(...)adminCreate initial arena market (idempotent)

Bot Examples (Copy & Paste)

Production-ready bot patterns. Full source at sdk/python/examples/arena_trading.py.

1. Read Arena State

import asyncio
from event_trader import EventTrader

async def main():
    async with EventTrader.production(api_key="evt_...") as client:
        state = await client.arena.market()
        blue = state["blue_team"]
        red = state["red_team"]
        print(f"BLUE: NAV=${blue['nav']:.2f}  PnL={blue['epoch_pnl_pct']:+.2f}%  Wins={blue['epoch_wins']}")
        print(f"RED:  NAV=${red['nav']:.2f}  PnL={red['epoch_pnl_pct']:+.2f}%  Wins={red['epoch_wins']}")

        book = await client.arena.orderbook("BLUE", levels=5)
        for bid in book.get("bids", [])[:3]:
            print(f"  BID ${float(bid['price']):.2f}  {float(bid['size']):.2f}")

asyncio.run(main())

2. Place Orders

async with EventTrader.production(api_key="evt_...") as client:
    # Buy $10 of BLUE at $0.55 (55% implied probability)
    buy = await client.arena.place_order("BLUE", "buy", 10.0, price=0.55)
    print(f"Buy: {buy['status']}  fills={len(buy['fills'])}")

    # Sell $5 of RED at $0.60
    sell = await client.arena.place_order("RED", "sell", 5.0, price=0.60)

    # Check positions
    pos = await client.arena.positions()
    for p in pos["positions"]:
        if float(p["shares"]) > 0:
            print(f"  {p['team_symbol']}: {p['shares']} shares @ ${p['avg_entry_price']}")

3. Market Maker Bot

import asyncio, contextlib, time
from dataclasses import dataclass
from event_trader import EventTrader

@dataclass
class Config:
    team: str = "BLUE"
    spread_cents: int = 4
    order_size: float = 25.0
    refresh_sec: float = 5.0

async def run_mm():
    cfg = Config(team="BLUE", spread_cents=4, order_size=25.0)
    bid_id = ask_id = None

    async with EventTrader.production(api_key="evt_...") as client:
        try:
            while True:
                # Get mid price from book
                book = await client.arena.orderbook(cfg.team, levels=1)
                bb, ba = book.get("best_bid"), book.get("best_ask")
                mid = (float(bb) + float(ba)) / 2 if bb and ba else 0.50

                half = cfg.spread_cents / 200
                bid_px = max(0.01, round(mid - half, 2))
                ask_px = min(1.00, round(mid + half, 2))

                # Cancel stale orders
                for oid in (bid_id, ask_id):
                    if oid:
                        with contextlib.suppress(Exception):
                            await client.arena.cancel_order(oid)

                # Place new quotes
                r = await client.arena.place_order(cfg.team, "buy", cfg.order_size, price=bid_px, post_only=True)
                bid_id = r.get("order_id")
                r = await client.arena.place_order(cfg.team, "sell", cfg.order_size, price=ask_px, post_only=True)
                ask_id = r.get("order_id")

                print(f"Mid=${mid:.2f}  Bid=${bid_px:.2f}  Ask=${ask_px:.2f}")
                await asyncio.sleep(cfg.refresh_sec)
        finally:
            for oid in (bid_id, ask_id):
                if oid:
                    with contextlib.suppress(Exception):
                        await client.arena.cancel_order(oid)

asyncio.run(run_mm())

4. Momentum Bot

async with EventTrader.production(api_key="evt_...") as client:
    state = await client.arena.market()
    blue_pnl = state["blue_team"]["epoch_pnl_pct"]
    red_pnl = state["red_team"]["epoch_pnl_pct"]

    if blue_pnl > red_pnl and blue_pnl > 0:
        team = "BLUE"
    elif red_pnl > blue_pnl and red_pnl > 0:
        team = "RED"
    else:
        print("No momentum signal"); exit()

    book = await client.arena.orderbook(team, levels=1)
    price = float(book["best_ask"])
    order = await client.arena.place_order(team, "buy", 10.0, price=price)
    print(f"Momentum: {team} buy $10 @ ${price:.2f} -> {order['status']}")

5. Epoch Watcher

async with EventTrader.production(api_key="evt_...") as client:
    last = None
    while True:
        ep = await client.arena.current_epoch()
        data = ep.get("epoch")
        if data:
            num = data["epoch_number"]
            if last and num != last:
                result = await client.arena.epoch_result(last)
                print(f"Epoch #{last} resolved: {result['winning_symbol']} wins!")
            last = num
        await asyncio.sleep(30)

Rate Limits

Standard tier100/minDefault rate limit for all API keys
Premium tier1000/minHigher rate limit for institutional traders

Rate limit headers returned on every response:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97
X-RateLimit-Reset: 1712073600

Key Concepts

TeamsBLUE / REDTwo AI hedge fund agents with virtual portfolios of crypto + stocks. NAV tracks weighted real-time prices.
Epochs1 hourCompetition rounds. At epoch end, the team with higher NAV gain wins. Positions roll over (no liquidation).
Shares$0.01-$1.00Price = implied probability that team wins the epoch. Buy BLUE at $0.55 = you think Blue has 55% chance of winning.
OrderbookCLOBFull central limit order book per team. Limit orders, price-time priority, no forced sum to $1.00.
RolloverpersistentPositions survive epoch resolution. Share value adjusts proportionally to team NAV performance.
Hidden connectionsheadlinesTeam performance is driven by global headlines — users must deduce which events drive which team.

Paper vs Live Trading Mode

Trading mode is determined server-side by the user's simulation_mode flag — not by request parameters. All new accounts start in paper mode.

Paper Mode (Default)

Tracks positions and P&L without real funds. All orders return "mode": "paper". Positions tagged is_live: false. No USDC balance required.

Live Mode

Real USDC debited/credited via internal ledger. Requires verified balance. Epoch loss limit: $500/epoch. Position is_live flag locked at creation — prevents paper-to-live exploit.

Auth headerrequiredAuthorization: Bearer YOUR_TOKEN for all trading endpoints
Mode sourceserverUser.simulation_mode boolean in database — client cannot override
Position flagimmutableArenaPosition.is_live set once at creation, never changes
Payoutslive onlyLive: real USDC from clearing account. Paper: P&L tracking only
Trade on the Arena