The bot operates on a simple but effective two-phase cycle: discover markets that might be profitable, then monitor them in real time so we can act the instant conditions are right. Here's how each piece works.
Phase 1 β Market Discovery (REST API Scan)
Every ~2 minutes, the bot calls Kalshi's REST API to fetch the full catalog of open events and their markets. This is the only way to discover new markets β you can't subscribe to something you don't know exists yet.
For each event, the scanner pulls every market's current ask prices, volume, and open interest. It then runs through your profile filters β checking category (e.g., sports, weather, economics), minimum liquidity, number of outcomes, and the coverage probability threshold.
Markets that pass all filters become candidates. Markets that are close but don't quite qualify get logged as near misses so you can see what's just outside the threshold.
Phase 2 β Real-Time Price Updates (WebSocket)
While REST scans happen every couple of minutes, prices change every second. That's where the WebSocket comes in. The bot maintains a persistent connection to Kalshi's WebSocket API (wss://api.elections.kalshi.com), which pushes live price and volume updates for every market on the platform.
These updates stream in sub-second and are stored in an in-memory cache. Between REST scans, the strategy engine reads from this cache instead of making API calls β which means zero additional rate-limit usage and prices that are always fresh.
The WebSocket also delivers market lifecycle events (new markets opening, markets settling) and fill confirmations when our orders execute β so the bot knows immediately when a trade goes through.
Phase 3 β Continuous Evaluation (Strategy Engine)
Every bot cycle (typically every few seconds), the strategy engine re-evaluates all candidate markets using the latest WS-cached prices. For dutching, it calculates:
- Coverage probability β what percentage of outcomes can we cover?
- Total cost β how much does it cost to buy all legs (including Kalshi's taker fee)?
- Guaranteed payout β the minimum we receive no matter which outcome wins
- Net profit margin β payout minus cost, accounting for fees
When the numbers cross your profile's threshold β meaning the cost to cover all outcomes is low enough to guarantee a profit β the engine issues a trade decision.
Phase 4 β Execution & Position Management
Once a trade decision is made, the executor places limit orders for each leg of the dutch bet. Each order is sized proportionally so the payout is balanced regardless of which outcome wins.
After entry, the triage agent monitors open positions. It can check external data sources (like weather forecasts for weather markets) to detect if conditions have changed and recommend early exits before resolution.
Positions are tracked per-profile, with independent risk limits, capital allocation, and trade modes (sim vs. live) for each.
Data Flow Diagram
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MARKET DISCOVERY (REST) β
β Every ~2 minutes β
β ββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ β
β β Kalshi REST ββββββΆβ Profile Filters ββββββΆβ Candidates β β
β β Full Catalog β β Category, Liq, β β + Near Misses β β
β β /events β β Coverage, Rules β β β β
β ββββββββββββββββ ββββββββββββββββββββ ββββββββββ¬ββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββ
β
Γ’βΒΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β REAL-TIME MONITORING (WebSocket) β
β Continuous, sub-second updates β
β ββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ β
β β Kalshi WS ββββββΆβ In-Memory Cache ββββββΆβ Fresh Prices β β
β β Ticker Feed β β tickers[market] β β No Rate Limits β β
β β Lifecycle β β Orderbooks β β Sub-second β β
β β Fills β β Fill Status β β β β
β ββββββββββββββββ ββββββββββββββββββββ ββββββββββ¬ββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββ
β
Γ’βΒΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β STRATEGY EVALUATION (Every Cycle) β
β Uses WS-cached prices, not REST β
β ββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ β
β β Candidates + ββββββΆβ Dutch Math ββββββΆβ Trade Decision β β
β β Live Prices β β Coverage, Cost, β β or Skip/Wait β β
β β β β Margin, Fees β β β β
β ββββββββββββββββ ββββββββββββββββββββ ββββββββββ¬ββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ¬βββββββββββββββ
β
Γ’βΒΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β EXECUTION & MONITORING β
β ββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ β
β β Place Orders ββββββΆβ Track Positions ββββββΆβ Triage Agent β β
β β Per Leg β β Per Profile β β Early Exit? β β
β β Limit Orders β β Sim or Live β β External Data β β
β ββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π‘ Key Design Choices
- REST for discovery, WS for speed β You need the full catalog to find new opportunities, but you need real-time prices to act on them. Using both gives you the best of each.
- Cycle-based evaluation, event-driven data β The bot evaluates on a regular cadence, but the data feeding those evaluations is always current thanks to the WebSocket stream.
- Near misses matter β Markets just outside the profitability threshold today might cross it tomorrow. Tracking them means you're ready when they do.
- Fees are first-class citizens β Every calculation includes Kalshi's taker fee model (7% Γ price Γ (1βprice), clamped). A market that looks profitable before fees might not be after them.
- Profile isolation β Each profile has its own filters, risk limits, and capital. One conservative profile can run alongside an aggressive one without interference.