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

[ PYTHON SDK ]

Official Python SDK for EventTrader prediction markets. Async-first, type-safe, and designed for professional trading bots.

pip install cymetica-eventtrader

[ INSTALLATION ]

Basic Installation

pip install cymetica-eventtrader

With Web3 Support

pip install cymetica-eventtrader[web3]

Requirements

  • Python 3.10+
  • httpx (async HTTP client)
  • pydantic v2 (data validation)
  • websockets (real-time streaming)

[ QUICK START ]

Get started with EventTrader SDK in just a few lines of code:

Python
import asyncio
from event_trader import EventTrader

async def main():
    # Initialize with API key
    async with EventTrader(api_key="evt_...") as client:
        # List active markets
        markets = await client.markets.list(status="active")
        for market in markets:
            print(f"{market.question} - {market.status}")

        # Get order book
        orderbook = await client.markets.orderbook(markets[0].id, "BTC")
        print(f"Best bid: {orderbook.best_bid}, Best ask: {orderbook.best_ask}")

        # Place an order
        order = await client.trading.place_order(
            market_id=markets[0].id,
            asset="BTC",
            side="buy",
            price=0.65,
            quantity=100,
        )
        print(f"Order placed: {order.id}")

asyncio.run(main())

Key Features

Async/Await Type-Safe Auto-Reconnect Rate Limiting JWT Auto-Refresh WebSocket Streaming

[ AUTHENTICATION ]

The SDK supports three authentication methods:

API Key

Simplest method - recommended for server-side applications:

Python
from event_trader import EventTrader

client = EventTrader(api_key="evt_your_api_key_here")
# Or use environment variable
# export EVENT_TRADER_API_KEY=evt_...
client = EventTrader()  # Auto-reads from env

Email/Password (JWT)

User authentication with automatic token refresh:

Python
from event_trader import EventTrader

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

# Tokens refresh automatically before expiration

Wallet (SIWE)

Sign-In With Ethereum for Web3-native authentication:

Python
from event_trader import EventTrader

# Define your signing callback
async def sign_message(message: str) -> str:
    # Use your wallet library to sign
    return wallet.sign_message(message)

# Authenticate with wallet
client = await EventTrader.from_wallet(
    wallet_address="0x742d35Cc6634C0532925a3b844Bc9e7595f3E6d3",
    sign_callback=sign_message,
)

[ SERVICES ]

The SDK is organized into specialized services — the 11 areas documented on this page are below (the client exposes additional services such as CLOB, perpetuals, backtesting, and vaults; see the package reference). Note: Staking is an area, not a separate namespace — its methods live on client.incentives.

📈 Markets

List, search, and get details on prediction markets and orderbooks

list() get() orderbook() featured()

💰 Trading

Place orders, manage positions, and view trade history

place_order() cancel_order() open_orders() history()

Streaming

Real-time WebSocket streams for orderbooks and prices

orderbook() prices() trades()

🏆 Incentives

Bot management, rewards tracking, and leaderboards

register_bot() tier_status() earnings() leaderboard()

🔒 Staking

Stake tokens for rewards, lockup tiers, and voting power (namespace: client.incentives)

stake() unstake() claim_rewards() get_summary()

🎮 Games

Gamification features: streaks, duels, tournaments

record_streak() create_duel() join_tournament() activate_boost()

👛 Wallet

Multi-wallet support, SIWE auth, portfolio tracking

connect() portfolio() gas_recommendations()

🔗 DeFi

DEX aggregation, impermanent loss calculator, MEV protection

swap_quote() calculate_il() assess_mev_risk()

💲 Exchanges

Unified CEX interface for Binance, Coinbase, Kraken

ticker() place_limit_order() compare_tickers()

📊 Aggregator

Cross-platform markets and arbitrage detection

markets() arbitrage_opportunities() route_order()

💵 Prices

Token prices, historical data, and conversions

get() bulk() historical() convert()

[ MARKETS SERVICE ]

Access prediction markets data, orderbooks, and market details.

List Markets

Python
# List all active markets
markets = await client.markets.list(status="active", limit=50)

# Filter by asset type
crypto_markets = await client.markets.list(
    status="active",
    asset_type="crypto",
)

# Search markets
results = await client.markets.search("bitcoin ETF")

for market in markets:
    print(f"{market.id}: {market.question}")
    print(f"  Status: {market.status}")
    print(f"  Volume: ${market.total_volume}")

Get Order Book

Python
# Get orderbook for specific asset
orderbook = await client.markets.orderbook(
    market_id="0x123...",
    asset="BTC",
)

print(f"Best Bid: {orderbook.best_bid}")
print(f"Best Ask: {orderbook.best_ask}")
print(f"Spread: {orderbook.spread}")

# Iterate through price levels
for bid in orderbook.bids[:5]:
    print(f"  BID: {bid.price} x {bid.quantity}")

Featured Market

Python
# Get the featured market
featured = await client.markets.featured()
print(f"Featured: {featured.question}")
print(f"Total Volume: ${featured.total_volume}")

[ TRADING SERVICE ]

Place orders, manage positions, and track trade history.

Place Order

Python
# Place a limit buy order
order = await client.trading.place_order(
    market_id="0x123...",
    asset="BTC",
    side="buy",
    price=0.65,      # 65 cents per share
    quantity=100,    # 100 shares
)

print(f"Order ID: {order.id}")
print(f"Status: {order.status}")
print(f"Filled: {order.filled_quantity}/{order.quantity}")

Cancel Order

Python
# Cancel a specific order
await client.trading.cancel_order(order_id="order_123")

# Cancel all orders for a market
await client.trading.cancel_all(market_id="0x123...")

Open Orders & History

Python
# Get all open orders
open_orders = await client.trading.open_orders()
for order in open_orders:
    print(f"{order.side} {order.quantity} @ {order.price}")

# Get trade history
trades = await client.trading.history(
    market_id="0x123...",
    limit=100,
)

# Get current positions
positions = await client.trading.positions()
for pos in positions:
    print(f"{pos.market_id}: {pos.quantity} shares @ {pos.avg_price}")

[ STREAMING SERVICE ]

Real-time WebSocket streams with automatic reconnection.

Stream Order Book

Python
# Stream orderbook updates in real-time
async for update in client.streaming.orderbook("0x123...", "BTC"):
    print(f"Spread: {update.spread}")
    print(f"Best Bid: {update.best_bid}")
    print(f"Best Ask: {update.best_ask}")

    # Process your trading logic here
    if update.spread > 0.05:
        print("Wide spread detected!")

Stream Prices

Python
# Stream price updates for multiple assets
async for price in client.streaming.prices(["BTC", "ETH", "SOL"]):
    print(f"{price.symbol}: ${price.price} ({price.change_24h}%)")

Stream Trades

Python
# Stream live trades as they happen
async for trade in client.streaming.trades("0x123..."):
    emoji = "🟢" if trade.side == "buy" else "🔴"
    print(f"{emoji} {trade.quantity} @ {trade.price}")

[ INCENTIVES SERVICE ]

Bot management, rewards tracking, and competitive leaderboards.

Register Bot

Python
# Register a new trading bot
bot = await client.incentives.register_bot(
    name="MyArbitrageBot",
    wallet_address="0x742d35Cc6634C0532925a3b844Bc9e7595f3E6d3",
    strategy_type="arbitrage",
    description="Cross-market arbitrage bot",
)

print(f"Bot ID: {bot.id}")
print(f"API Key: {bot.api_key}")  # Save this!

Track Volume & Rewards

Python
# Record trading volume
await client.incentives.record_volume(
    bot_id=bot.id,
    market_id="0x123...",
    volume_usd=5000,
)

# Check tier status
tier = await client.incentives.tier_status(bot.id)
print(f"Current Tier: {tier.current_tier}")
print(f"Reward Multiplier: {tier.reward_multiplier}x")
print(f"Volume to Next Tier: ${tier.volume_to_next_tier}")

# Get earnings breakdown
earnings = await client.incentives.earnings(bot.id)
print(f"Total Earned: ${earnings.total_earned}")
print(f"Pending: ${earnings.pending}")

Leaderboard

Python
# Get weekly leaderboard
leaderboard = await client.incentives.leaderboard(
    period="weekly",
    limit=10,
)

for entry in leaderboard:
    print(f"#{entry.rank} {entry.bot_name}: ${entry.volume}")

[ STAKING SERVICE ]

Lock tokens to earn yield with configurable lockup periods and bonus APY. Staking methods are exposed through the incentives service — every call below is client.incentives.*; there is no separate client.staking namespace.

List Staking Pools

Python
# List available staking pools
pools = await client.incentives.list_staking_pools()

for pool in pools:
    print(f"{pool.name}")
    print(f"  Token: {pool.stake_token.symbol}")
    print(f"  Base APY: {pool.apy.base}%")
    print(f"  Max APY: {pool.apy.max}%")
    print(f"  Total Staked: {pool.pool_stats.total_staked}")
    print(f"  Lockup Tiers: {len(pool.lockup_tiers)}")

Stake Tokens

Python
# Stake tokens with 90-day lockup for bonus APY
stake = await client.incentives.stake(
    pool_id="pool_abc123",
    wallet="0x742d35Cc6634C0532925a3b844Bc9e7595f3E6d3",
    amount=1000,
    lockup_days=90,  # Lock for 90 days to get bonus APY
)

print(f"Stake ID: {stake.stake_id}")
print(f"Amount: {stake.amount}")
print(f"Effective APY: {stake.effective_apy}%")
print(f"Voting Power: {stake.voting_power}")
print(f"Lockup Ends: {stake.timing.lockup_ends_at}")

Check & Claim Rewards

Python
# Calculate pending rewards
rewards = await client.incentives.calculate_staking_rewards(stake.stake_id)
print(f"Pending Rewards: {rewards.pending_rewards}")
print(f"Days Elapsed: {rewards.days_elapsed}")

# Claim rewards
claim = await client.incentives.claim_staking_rewards(
    stake_id=stake.stake_id,
    wallet="0x...",
)
print(f"Claimed: {claim.amount} {claim.reward_token.symbol}")

Unstaking

Python
# Request unstake (starts cooldown period)
stake = await client.incentives.request_unstake(
    stake_id="stake_123",
    wallet="0x...",
)
print(f"Cooldown ends: {stake.timing.cooldown_ends_at}")

# Complete unstake after cooldown
stake = await client.incentives.complete_unstake(
    stake_id="stake_123",
    wallet="0x...",
)
print(f"Unstaked! Status: {stake.status}")

# Emergency unstake (with penalty)
stake = await client.incentives.emergency_unstake(
    stake_id="stake_456",
    wallet="0x...",
)
print(f"Penalty applied: {stake.penalty_applied}")

User Staking Summary

Python
# Get full staking summary for a user
summary = await client.incentives.get_staking_summary("0x...")

print(f"Total Staked: {summary.total_staked}")
print(f"Active Stakes: {summary.active_stakes}")
print(f"Pending Rewards: {summary.pending_rewards}")
print(f"Total Claimed: {summary.total_claimed}")
print(f"Voting Power: {summary.total_voting_power}")

# List individual stakes
for stake in summary.stakes:
    print(f"  {stake.stake_id}: {stake.amount} @ {stake.effective_apy}% APY")

Lockup Tiers

Longer lockup periods earn higher APY:

Lockup Bonus APY Voting Power
Flexible (0 days) +0% 1.0x
30 days +5% 1.25x
90 days +15% 1.5x
180 days +25% 2.0x
365 days +40% 3.0x

[ GAMES SERVICE ]

Gamification features to increase engagement and rewards.

Win Streaks

Python
# Record a winning trade
streak = await client.games.record_streak(
    user_id="user_123",
    result="win",
    market_id="0x123...",
)

print(f"Current Streak: {streak.current_count} wins")
print(f"Bonus Multiplier: {streak.bonus_multiplier}x")

# Get streak bonus
bonus = await client.games.streak_bonus("user_123")
print(f"Your Bonus: {bonus.bonus_percent}%")

Duels

Python
# Create a trading duel
duel = await client.games.create_duel(
    market_id="0x123...",
    stake_amount=100,
    duration_hours=24,
)

print(f"Duel ID: {duel.id}")
print(f"Prize Pool: ${duel.prize_pool}")

# Accept a duel challenge
await client.games.accept_duel(duel_id=duel.id, user_id="user_456")

Tournaments

Python
# List active tournaments
tournaments = await client.games.list_tournaments(status="active")

for t in tournaments:
    print(f"{t.name}: ${t.prize_pool} prize pool")
    print(f"  {t.current_participants}/{t.max_participants} joined")

# Join a tournament
entry = await client.games.join_tournament(
    tournament_id=tournaments[0].id,
    user_id="user_123",
)

# Check tournament leaderboard
leaderboard = await client.games.tournament_leaderboard(
    tournament_id=tournaments[0].id,
    limit=10,
)

Boosts

Python
# Get available boosts
boosts = await client.games.available_boosts("user_123")

# Activate XP boost
activation = await client.games.activate_boost("user_123", "xp_boost")
print(f"Boost: {activation.multiplier}x for {activation.duration}")

[ WALLET SERVICE ]

Multi-wallet support, portfolio tracking, and gas estimation.

Portfolio

Python
# Get wallet portfolio
portfolio = await client.wallet.portfolio(
    address="0x742d35Cc6634C0532925a3b844Bc9e7595f3E6d3",
    chain="polygon",
)

print(f"Native Balance: {portfolio.native_balance} MATIC")
print(f"Tokens: {len(portfolio.tokens)}")

for token in portfolio.tokens:
    print(f"  {token.symbol}: {token.balance} (${token.value_usd})")

Gas Recommendations

Python
# Get gas price recommendations
gas = await client.wallet.gas_recommendations(chain="ethereum")

print(f"Slow: {gas.slow.gwei} gwei (~{gas.slow.estimated_time})")
print(f"Standard: {gas.standard.gwei} gwei (~{gas.standard.estimated_time})")
print(f"Fast: {gas.fast.gwei} gwei (~{gas.fast.estimated_time})")

SIWE Authentication

Python
# Full SIWE authentication flow
session = await client.wallet.siwe_authenticate(
    address="0x742d35Cc6634C0532925a3b844Bc9e7595f3E6d3",
    sign_callback=your_sign_function,
    chain_id=137,  # Polygon
)

print(f"Session: {session.session_id}")
print(f"Expires: {session.expires_at}")

[ DEFI SERVICE ]

DEX aggregation, impermanent loss calculator, and MEV protection.

Swap Quote

Python
# Get best swap quote across DEXs
quote = await client.defi.swap_quote(
    token_in="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",  # WETH
    token_out="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", # USDC
    amount_in="1000000000000000000",  # 1 ETH in wei
    chain="ethereum",
    slippage_bps=50,
)

print(f"Output: {quote.amount_out} USDC")
print(f"Price Impact: {quote.price_impact_pct}%")
print(f"Route: {' -> '.join(quote.route)}")

Impermanent Loss Calculator

Python
# Calculate IL for LP position
il = await client.defi.calculate_il(
    pool_address="0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8",
    token_a="WETH",
    token_b="USDC",
    initial_price="2000",
    current_price="2500",
    initial_value_usd="10000",
    fees_earned_usd="150",
)

print(f"Impermanent Loss: {il.impermanent_loss_pct}%")
print(f"Hold Value: ${il.hold_value_usd}")
print(f"LP Value: ${il.lp_value_usd}")
print(f"Net vs Hold: ${il.net_pnl_vs_hold_usd}")

MEV Risk Assessment

Python
# Assess MEV risk for large swap
mev = await client.defi.assess_mev_risk(
    token_in="0xWETH...",
    token_out="0xUSDC...",
    amount_in="10000000000000000000",  # 10 ETH
    amount_in_usd="25000",
    slippage_bps=100,
)

print(f"Risk Score: {mev.risk_score}/100")
print(f"Risk Level: {mev.risk_level}")
print(f"Estimated MEV: ${mev.estimated_mev_usd}")
print(f"Attack Vectors: {mev.attack_vectors}")
print(f"Recommended: {mev.recommended_protection}")

[ EXCHANGES SERVICE ]

Unified interface for centralized exchanges (Binance, Coinbase, Kraken, etc.).

Market Data

Python
# Get ticker from Binance
ticker = await client.exchanges.ticker("binance", "BTC/USDT")

print(f"Last: ${ticker.last}")
print(f"Bid: ${ticker.bid} / Ask: ${ticker.ask}")
print(f"24h Volume: {ticker.volume_24h} BTC")
print(f"24h Change: {ticker.change_pct_24h}%")

Cross-Exchange Comparison

Python
# Compare prices across exchanges
comparison = await client.exchanges.compare_tickers(
    "BTC/USDT",
    exchanges=["binance", "coinbase", "kraken"],
)

for exchange, data in comparison.exchanges.items():
    print(f"{exchange}: Bid ${data.bid} / Ask ${data.ask}")

print(f"Best Bid: {comparison.best_bid['exchange']} @ ${comparison.best_bid['price']}")
print(f"Best Ask: {comparison.best_ask['exchange']} @ ${comparison.best_ask['price']}")

if comparison.arbitrage_opportunity:
    print("⚠️ Arbitrage opportunity detected!")

Trading

Python
# Place limit order on Binance
order = await client.exchanges.place_limit_order(
    exchange="binance",
    symbol="BTC/USDT",
    side="buy",
    amount=0.001,
    price=50000,
)

print(f"Order ID: {order.order_id}")
print(f"Status: {order.status}")

# Get account balance
balance = await client.exchanges.balance("binance", assets=["BTC", "USDT"])
for asset, bal in balance.balances.items():
    print(f"{asset}: {bal.free} free, {bal.used} in orders")

[ AGGREGATOR SERVICE ]

Cross-platform prediction markets aggregation and arbitrage detection.

Cross-Platform Markets

Python
# Get markets across platforms
markets = await client.aggregator.markets(
    platforms=["polymarket", "kalshi"],
    category="politics",
)

for market in markets:
    print(f"{market.question}")
    print(f"  Platform: {market.platform}")
    print(f"  Volume: ${market.volume}")

Arbitrage Detection

Python
# Find arbitrage opportunities
arbs = await client.aggregator.arbitrage_opportunities(
    min_spread_bps=20,
    min_profit=1.0,
)

for arb in arbs:
    print(f"Opportunity: {arb.market_question}")
    print(f"  Buy on: {arb.buy_platform} @ {arb.buy_price}")
    print(f"  Sell on: {arb.sell_platform} @ {arb.sell_price}")
    print(f"  Profit: ${arb.expected_profit}")

Smart Order Routing

Python
# Get optimal execution plan
plan = await client.aggregator.route_order(
    market_id="0x123...",
    outcome_id="Yes",
    side="buy",
    size=1000,
    strategy="best_price",
)

print(f"Total Cost: ${plan.total_cost}")
print(f"Avg Price: {plan.average_price}")
for leg in plan.legs:
    print(f"  {leg.platform}: {leg.quantity} @ {leg.price}")

[ ERROR HANDLING ]

The SDK provides a comprehensive error hierarchy for granular exception handling:

EventTraderError - Base exception
APIError - General API errors
AuthenticationError - Auth failures
RateLimitError - Rate limit exceeded
ValidationError - Invalid parameters
NotFoundError - Resource not found
ConnectionError - Network issues
TimeoutError - Request timeout
WebSocketError - WS issues
InsufficientFundsError - Low balance
OrderError - Order failures
MarketClosedError - Market closed

Example

Python
from event_trader import (
    EventTrader,
    EventTraderError,
    AuthenticationError,
    RateLimitError,
    NotFoundError,
    InsufficientFundsError,
    OrderError,
)

try:
    order = await client.trading.place_order(
        market_id="0x123...",
        asset="BTC",
        side="buy",
        price=0.65,
        quantity=100,
    )
except InsufficientFundsError:
    print("Not enough balance to place order")
except RateLimitError as e:
    print(f"Rate limited, retry after {e.retry_after}s")
except NotFoundError:
    print("Market not found")
except OrderError as e:
    print(f"Order failed: {e.message}")
except EventTraderError as e:
    print(f"SDK error: {e}")

[ API KEY BOOTSTRAP ]

Register an account and obtain API credentials programmatically. Two paths are available: standard registration or instant MCP registration for AI agents.

Standard Registration + API Key

Python
import requests

# Option 1: Register new account + get API key (two calls)
resp = requests.post("https://cymetica.com/auth/register", json={
    "email": "bot@example.com",
    "username": "my_trading_bot",
    "password": "secure_password_here"
})
print(f"Registered: {resp.json()}")

# Get API key for the new account
resp = requests.post("https://cymetica.com/auth/api-key", json={
    "email": "bot@example.com",
    "password": "secure_password_here",
    "key_name": "my-trading-bot"
})
data = resp.json()
api_key = data["api_key"]
api_secret = data["api_secret"]
print(f"API Key: {api_key}")
print(f"Secret: {api_secret}")
# Store these securely — they will not be shown again!

MCP Registration (AI Agents)

Python
import requests

# Option 2: For AI agents — instant registration via MCP
resp = requests.post("https://cymetica.com/mcp/v1/register", json={
    "name": "MyTradingBot",
    "description": "Automated market maker for SBIO/USDC pair",
    "contact_email": "bot@example.com",
    "capabilities": ["trading", "market_making"],
    "intended_use": "Provide liquidity on SBIO/USDC pair",
    "role": "market_maker"
})
data = resp.json()
api_key = data["api_key"]
print(f"MCP API Key: {api_key}")

[ EXCHANGE TRADING ]

Place orders on the CLOB exchange, check the order book, query balances, and cancel orders via the REST API. Use preflight() for sub-100ms round-trip order placement.

Python
import requests

API_KEY = "evt_YOUR_KEY_HERE"  # or mcp_YOUR_KEY_HERE
BASE_URL = "https://cymetica.com"

# Use a Session for HTTP keep-alive (saves ~300ms per request)
session = requests.Session()
session.headers.update({
    "X-API-Key": API_KEY,
    "Content-Type": "application/json"
})

# ── Low-latency preflight: balance + BBO in one call (~5ms server) ──
resp = session.get(f"{BASE_URL}/api/v1/clob/preflight/sbio")
pf = resp.json()
print(f"Balance: {pf['base_balance']} SBIO, {pf['quote_balance']} USDC")
print(f"BBO: {pf['best_bid']}/{pf['best_ask']} ({pf['server_ms']}ms server)")

# ── Place a limit buy order (server-side ~50ms) ──
resp = session.post(f"{BASE_URL}/api/v1/exchange/sbio/orders",
    json={
        "side": "buy",
        "order_type": "limit",
        "quantity": "100",
        "price": "0.005"
    }
)
order = resp.json()
print(f"Order placed: {order['order_id']}")

# Server-side timing breakdown
timing = order.get("server_timing", {})
print(f"Server: pre_match={timing.get('pre_match_ms')}ms "
      f"match={timing.get('match_ms')}ms total={timing.get('total_ms')}ms")

# ── Cancel an order ──
resp = session.delete(
    f"{BASE_URL}/api/v1/exchange/sbio/orders/{order['order_id']}"
)
print(f"Cancelled: {resp.json()}")

[ MARKET MAKER BOT ]

A complete, runnable market maker skeleton that provides two-sided liquidity by placing limit orders on both sides of the spread. Earns 0% maker fees + 2 bps rebate.

Python
"""Simple Market Maker Bot for EventTrader CLOB Exchange.

Provides two-sided liquidity by placing limit orders on both
sides of the spread. Earns 0% maker fees + 2 bps rebate.

Usage:
    python market_maker_bot.py --api-key evt_YOUR_KEY --symbol sbio
"""

import argparse
import time
import requests
import logging

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s")
log = logging.getLogger("mm-bot")

BASE_URL = "https://cymetica.com"


def get_headers(api_key: str) -> dict:
    return {"X-API-Key": api_key, "Content-Type": "application/json"}


def get_mid_price(session: requests.Session, symbol: str) -> tuple[float | None, dict]:
    """Fetch BBO + balance via preflight (~5ms server-side).

    Uses the preflight endpoint instead of separate book + balance calls
    to reduce latency from ~4s to ~50ms per quote cycle.
    """
    resp = session.get(f"{BASE_URL}/api/v1/clob/preflight/{symbol}")
    if resp.status_code != 200:
        return None, {}
    pf = resp.json()
    bid = pf.get("best_bid")
    ask = pf.get("best_ask")
    if not bid or not ask:
        return None, pf
    return (float(bid) + float(ask)) / 2, pf


def cancel_all_orders(session: requests.Session, symbol: str):
    """Cancel all open orders."""
    resp = session.get(f"{BASE_URL}/api/v1/exchange/{symbol}/orders")
    if resp.status_code != 200:
        return
    orders = resp.json()
    for order in orders:
        if order.get("status") in ("open", "partially_filled"):
            session.delete(
                f"{BASE_URL}/api/v1/exchange/{symbol}/orders/{order['order_id']}"
            )


def place_quotes(session: requests.Session, symbol: str, mid: float,
                 spread_pct: float, size: float):
    """Place buy and sell limit orders around mid price using batch."""
    half_spread = mid * spread_pct / 2
    buy_price = round(mid - half_spread, 6)
    sell_price = round(mid + half_spread, 6)

    # Batch place both sides (single HTTP call — lower latency)
    resp = session.post(
        f"{BASE_URL}/api/v1/clob/orders/batch",
        json={
            "pair": f"{symbol.upper()}/USDC",
            "orders": [
                {"side": "buy", "order_type": "post_only", "quantity": str(size), "price": str(buy_price)},
                {"side": "sell", "order_type": "post_only", "quantity": str(size), "price": str(sell_price)},
            ]
        }
    )
    result = resp.json()
    log.info(f"Quoted {symbol}: bid={buy_price} ask={sell_price} spread={spread_pct*100:.1f}%")
    return result


def run_market_maker(api_key: str, symbol: str, spread_pct: float = 0.05,
                     order_size: float = 100, refresh_seconds: int = 30):
    """Main market maker loop."""
    # Use a persistent Session for HTTP keep-alive (saves ~300ms/request)
    session = requests.Session()
    session.headers.update(get_headers(api_key))
    log.info(f"Starting market maker on {symbol.upper()}/USDC")
    log.info(f"Spread: {spread_pct*100:.1f}% | Size: {order_size} | Refresh: {refresh_seconds}s")

    while True:
        try:
            t0 = time.monotonic()
            mid, pf = get_mid_price(session, symbol)
            if mid is None:
                log.warning("No mid price available, waiting...")
                time.sleep(refresh_seconds)
                continue

            cancel_all_orders(session, symbol)
            place_quotes(session, symbol, mid, spread_pct, order_size)
            cycle_ms = (time.monotonic() - t0) * 1000
            log.info(f"Cycle: {cycle_ms:.0f}ms (preflight: {pf.get('server_ms', '?')}ms)")
            time.sleep(refresh_seconds)

        except KeyboardInterrupt:
            log.info("Shutting down — cancelling all orders")
            cancel_all_orders(session, symbol)
            break
        except Exception as e:
            log.error(f"Error in MM loop: {e}")
            time.sleep(refresh_seconds)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="EventTrader Market Maker Bot")
    parser.add_argument("--api-key", required=True, help="API key (evt_ or mcp_)")
    parser.add_argument("--symbol", default="sbio", help="Trading pair symbol")
    parser.add_argument("--spread", type=float, default=0.05, help="Spread percentage (default 5%%)")
    parser.add_argument("--size", type=float, default=100, help="Order size per side")
    parser.add_argument("--refresh", type=int, default=30, help="Refresh interval in seconds")
    args = parser.parse_args()

    run_market_maker(args.api_key, args.symbol, args.spread, args.size, args.refresh)

[ WEBSOCKET STREAMING ]

Stream real-time order book updates over WebSocket for low-latency market data.

Python
import asyncio
import websockets
import json

async def stream_orderbook(symbol: str = "sbio"):
    """Stream real-time order book updates."""
    uri = f"wss://cymetica.com/ws/exchange/{symbol}/book"
    async with websockets.connect(uri) as ws:
        # Subscribe to order book channel
        await ws.send(json.dumps({
            "action": "subscribe",
            "channel": "orderbook",
            "symbol": symbol
        }))

        async for message in ws:
            data = json.loads(message)
            if data.get("type") == "orderbook_update":
                print(f"Book update: {data}")

asyncio.run(stream_orderbook())

[ EXAMPLES ]

Complete working examples are available in the SDK repository:

Example Description
basic_trading.py Basic trading workflow - list markets, place orders
streaming_orderbook.py Real-time orderbook streaming with WebSocket
market_maker_bot.py Simple market maker with spread management
bot_incentives.py Bot registration, rewards, and leaderboards
gamification.py Streaks, duels, tournaments, and boosts
defi_integration.py DEX quotes, IL calculation, MEV protection
exchange_trading.py CEX trading with Binance, Coinbase, Kraken

Market Maker Bot Example

Python
import asyncio
from event_trader import EventTrader

async def market_maker():
    async with EventTrader(api_key="evt_...") as client:
        market_id = "0x123..."
        asset = "BTC"
        spread = 0.02  # 2% spread
        size = 100

        while True:
            # Get current orderbook
            ob = await client.markets.orderbook(market_id, asset)
            mid_price = (ob.best_bid + ob.best_ask) / 2

            # Cancel existing orders
            await client.trading.cancel_all(market_id=market_id)

            # Place new orders around mid price
            bid_price = mid_price * (1 - spread / 2)
            ask_price = mid_price * (1 + spread / 2)

            await client.trading.place_order(
                market_id=market_id,
                asset=asset,
                side="buy",
                price=bid_price,
                quantity=size,
            )

            await client.trading.place_order(
                market_id=market_id,
                asset=asset,
                side="sell",
                price=ask_price,
                quantity=size,
            )

            print(f"Quotes: {bid_price:.4f} / {ask_price:.4f}")
            await asyncio.sleep(5)

asyncio.run(market_maker())