Strategy API
The Python Strategy base class, the agent runtime, risk rails and backtests.
langbot run strategy.py --mode demo|live runs a user-authored strategy on your machine against the feed and your Kalshi account.
The base class
from langbot import Strategy, Event, Book class Mention(Strategy): markets = ["KXEARNINGSMENTIONNVDA-*"] # glob over tickers; drives subscriptions + book feeds phrases = ["blackwell"] # what to listen for async def on_event(self, evt: Event): ... # phrase_detected, speaker_change, event_started… async def on_book(self, book: Book): ... # orderbook_delta from the venue WS async def on_fill(self, fill): ... # your fills # helpers# self.buy_yes(ticker, price, count) self.sell_yes(...)# self.cancel_all(ticker) self.position(ticker)# self.book(ticker) self.ladder(ticker, prices, count)Modes
| mode | venue | notes |
|---|---|---|
demo | demo.kalshi.co | paper fills; default; start here |
live | api.elections.kalshi.com | your prod key; risk rails required |
Kalshi adapter env: KALSHI_KEY_ID, KALSHI_PRIVATE_KEY_PATH (Ed25519 or RSA-PSS), KALSHI_ENV=demo|prod. Polymarket is read-only.
Risk rails (enforced in-process)
LANGBOT_MAX_POSITION_USD=50 # per-market max exposureLANGBOT_MAX_DAILY_LOSS_USD=100 # daily loss stop → kill switchLANGBOT_MARKET_ALLOWLIST=KXEARNINGSMENTION*,KXFEDMENTION*The runtime refuses to start in live mode without all three set.
Backtests
langbot backtest strategy.py --events ev_nvda_q2_2026,ev_nvda_q1_2026Replays archived transcript_words and orderbook_snaps at their original timestamps, so your on_event sees the phrase at the same instant relative to the book as it would have live. Fills are simulated against the recorded book with the venue's taker delay applied.
Reference strategies
Three reference strategies ship with the Python SDK (langbot.strategies):
- mention sniper — buy YES on the first detection if the ask is under a threshold
- pre-event resting orders — ladder resting YES bids on likely phrases before the call, cancel on
event_ended - cross-venue hedge — Kalshi execution with Polymarket (read) as a price reference
Local agent API
langbot run also serves 127.0.0.1:8787: GET /status, GET /strategies, POST /strategies/{id}/start|stop, GET /positions, GET /fills. The MCP run_paper tool and the dashboard's agent status card use it. Heartbeats go to POST /v1/agent/heartbeat with your token (optional).
LLM drafting
draft_strategy(thesis) produces a file like the one above from a sentence. It never runs live on its own: you read it, run it in demo, then decide.