rystic

Simulators

Kalshi state UI simulator

Kalshi state UI

Every simulator serves a live monitor at http://localhost:8080/_rystic/ui. It reads the same control plane your tests use — nothing renders that isn't real twin state. The Kalshi twin adds a lens: an order-book workbench for watching a bot trade a recorded market day.

The state UI: Market, per-bot panels, Replay, and the live order book

The cards

Each card collapses independently; collapsed headers keep showing live summaries (spread, P&L, tape position, counts).

CardWhat it does
MarketLast, mid, spread for the market in focus.
Your BotOne panel per connected actor — position, exposure, session P&L, working orders, fills.
ReplayPlay a real captured order-book session through the twin (below).
Order BookLive depth ladder. Click any price row to prefill it into Order Entry. Your resting orders get an amber marker.
SimulatorSynthetic random-walk flow for when you have no tape (below).
Order EntryBid/ask, price, count, GTC/IOC/FOK. Fills, rests, and rejections report inline.
TradesThe tape — every execution, newest first.
Activity, Store, EffectsThe shell's own cards: the event bus, the raw register store, and the WS egress log.

Your Bot

Point a bot at http://localhost:8080 (REST) and /trade-api/ws/v2 (WS) — any API key works, the twin never verifies signatures. It reads the key id as the bot's name, so a signing bot gets its own isolated portfolio and its own panel here without any change on its side; an X-Rystic-Actor header overrides that, and a caller with neither is member.

Two bot panels — position, exposure, session P&L, working orders, fills

Session P&L is measured from the moment the page loaded, so a refresh rebaselines it. A bot that connects mid-tape gets funded and baselined on first sight, so it starts at P&L 0 rather than trading dark. Working orders and fills are scoped to that actor alone, and its resting orders glow amber in the book ladder.

Replay a captured session

If the twin finds a capture archive (KALSHI_CAPTURE_DIR, default ~/data/kalshi-orderbook), the Replay card lists every captured market.

The Replay card: pick a market, set speed, rebase, play/pause/scrub

  1. Filter and pick a market. Tickers render human-readable, grouped by series (Aug 1 00:00 · 00 under KXBTC15M).
  2. Set Speed. Playback is full fidelity: every recorded event, at its recorded spacing, divided by Speed. ×1 is the measurement setting — it replays in true real time, so a bot reacting on the wall clock sees the market it would have seen live. At ×N your bot responds N× slower relative to the tape, which is fine for skimming but not for measuring.
  3. Leave Rebase on. It shifts the tape clock so the session starts now. Against an un-rebased old tape a bot that computes market hours from the wall clock sees an expired market and won't quote.
  4. Load & play. The book streams through every recorded state; the button becomes Pause, and pausing keeps the tape — Resume continues from the same spot. Playing again from the top re-rebases the tape to the new now, so a second session isn't born expired.
  5. Scrub. The slider jumps anywhere in the session, both directions, labeled in session time. Every position is an exact snapshot — but it seeds wholesale, so don't scrub while a bot is trading.

Replayed flow fills your resting orders: a recorded print that exceeds the volume ahead of you in the level FIFO fills you at maker fee 0 and pushes the same fill / user_orders / market_positions frames a live fill would.

Simulator

With no tape — or no capture archive at all — the Simulator card generates synthetic flow instead: a market maker re-quotes around a random-walking fair value while a taker crosses it, with speed, volatility, drift, and order size on live knobs. It's a way to get a moving book from nothing, not a model of the market; a recorded tape is the faithful option whenever you have one. The card disables itself while a tape is playing, since the two would fight over the book.

Activity

The unified event bus: your API requests, the WS effects they emit, and control-plane events, filterable by kind. During a replay each applied frame lands here as a control · replay event alongside the orderbook_delta / trade / ticker effects it produced.

The activity bus during a replay

Headless equivalents

Everything the UI does is a control-plane call, scriptable as-is:

curl -s localhost:8080/_replay/markets                    # list captured markets
curl -X POST localhost:8080/_replay/start -d '{"market":"KXBTC15M-26AUG010000-00","speed":1,"rebase":true}'
curl -X POST localhost:8080/_replay/pause
curl -X POST localhost:8080/_replay/play  -d '{"speed":10}'
curl -X POST localhost:8080/_replay/seek  -d '{"position":80000}'
curl -s localhost:8080/_replay/status
curl -s 'localhost:8080/_rystic/egress?tail=100'          # recent WS frames