Simulators
Exchange shards
Kalshi runs its exchange as shards numbered 0 to 3, and the simulator does the same. Every market lives on one shard, named by its exchange_index. An account holds cash per shard (balance_breakdown), and trades a market only on a shard where it’s provisioned (exchange_presence). An order routes to its market’s shard by the body’s exchange_index, or by ticker when that’s omitted or -1. Its fill debits that shard’s cash.
The shard2_world scenario holds a market on shard 2 and a member funded there:
export RYSTIC_URL=$(rystic run kalshi-twin -d --port 0 --name shards --scenario shard2_world --json | jq -r .data.url)
curl -s "$RYSTIC_URL/trade-api/v2/markets" | jq -c '.markets[] | {ticker, exchange_index}'
# -> {"ticker":"KXBTCSHD-26-W","exchange_index":2}
curl -s "$RYSTIC_URL/trade-api/v2/portfolio/balance?exchange_index=2" | jq -c '{balance_dollars}'
# -> {"balance_dollars":"5000.0000"}
curl -s "$RYSTIC_URL/trade-api/v2/portfolio/balance" | jq -c '.balance_breakdown | map({exchange_index, balance})'
# -> [{"exchange_index":0,"balance":"5000.0000"},{"exchange_index":1,"balance":"0.0000"},{"exchange_index":2,"balance":"5000.0000"},{"exchange_index":3,"balance":"0.0000"}]
- A balance seeded without
balance_breakdownis a one-shard account on shard 0. An order on a market on another shard returns404 user_not_found, as on the exchange. - A replayed or live-fed market keeps its real shard, read from its market record. With no record (the metadata fetch turned off or unreachable, and no
meta/) it sits on shard 0.GET /trade-api/v2/markets/{ticker}shows it, andGET /trade-api/v2/portfolio/balance?exchange_index=2shows that shard’s cash. - Fund the shard in the seed. This balance holds cash on shards 0 and 2 and provisions both:
{"state_balance": {"member": {
"balance": 1000000, "balance_dollars": "10000.0000",
"portfolio_value": 0, "updated_ts": 1784989800,
"balance_breakdown": [{"exchange_index": 0, "balance": "0.0000"},
{"exchange_index": 2, "balance": "10000.0000"}],
"exchange_presence": [0, 2]
}}}
One cash pool
Start the simulator with KALSHI_REPLAY_SHARD=0, and every market a tape or the live feed creates is placed on shard 0, whatever its record says. So a plain balance seed funds them all. Any other non-negative index works the same way, and a value that isn’t one is ignored and logged. A market you seed yourself keeps the exchange_index you give it.
Differs from Kalshi: with KALSHI_REPLAY_SHARD set, routing, per-shard cash and transfers no longer reflect where the markets really live.