Simulators
Settlement
The simulator settles a market when you call POST /_settle, so your test decides when a market resolves.
Differs from Kalshi: Kalshi settles a market on its own clock. The simulator settles one only when POST /_settle is called.
The holding_long scenario starts member with 50 YES contracts on KXDEMO-26-A, so settling it pays out:
export RYSTIC_URL=$(rystic run kalshi-twin -d --port 0 --name settle --scenario holding_long --json | jq -r .data.url)
curl -s "$RYSTIC_URL/trade-api/v2/portfolio/balance" | jq -c '{balance_dollars}'
# -> {"balance_dollars":"10000.0000"}
curl -s -X POST "$RYSTIC_URL/_settle" -H 'Content-Type: application/json' -d '{"ticker":"KXDEMO-26-A","result":"yes"}'
# -> {"accounts_settled":1,"orders_canceled":2,"paid_dollars":"50.0000","result":"yes","ticker":"KXDEMO-26-A"}
curl -s "$RYSTIC_URL/trade-api/v2/portfolio/balance" | jq -c '{balance_dollars}'
# -> {"balance_dollars":"10050.0000"}
curl -s "$RYSTIC_URL/trade-api/v2/portfolio/settlements" | jq -c '.settlements[] | {ticker, market_result, yes_count_fp}'
# -> {"ticker":"KXDEMO-26-A","market_result":"yes","yes_count_fp":"50.00"}
Send the body as JSON, {"ticker", "result"}, with result set to yes or no. The call declares the result, then:
- cancels every resting order on the market
- pays $1.00 per contract to the winning side
- zeroes positions and folds balances
- writes the settlement history that
GET /trade-api/v2/portfolio/settlementsreads
accounts_settled counts the accounts that held a position, and orders_canceled counts every resting order on the market, whoever owns it.
What settling changes
- The market becomes
finalized, Kalshi’s word for a settled market, on an empty book.yes_bid_dollarsreads0.0000,yes_ask_dollarsreads1.0000and the recordedexpiration_valueis published. Creating an order on it then returns404 market_not_found, exactly as for a ticker that doesn’t exist. Canceling still works, because risk-reducing operations are never gated on market status. - The resting orders are canceled for real. Your quotes get
user_orderscancel frames and the book deltas print. - On a replayed tape the later frames leave the settled market alone. On
btc15m_tape, the scenario’s only market stays empty untilPOST /_rystic/scenarioputs the scenario back. market_lifecycle_v2subscribers receive two events. Events, in order:determined→settled.
Repeating a settlement
Settlement is idempotent, so no repeat pays twice:
| You send | The simulator returns |
|---|---|
| the same result again | 200 with "already_settled":true and zero counts |
| the opposite result | 409 with {"error":{"code":"settlement_conflict","message":"market already settled with result yes"}}, and the recorded result never flips |
| an unknown ticker | 404 with market_not_found |
A body not sent as Content-Type: application/json returns 400 with settle requires ticker and result (yes|no).
Last updated on