WebSocket streams
Real-time market data and per-simulation event channels.
A single WebSocket endpoint streams live market data and per-simulation events. It's what keeps the live trading screen and the strategy results progress current in real time.
Endpoint
wss://api.0dtespx.com/__ws
Handshake
After connecting, you have 5 seconds to send an auth message — either anonymous or token-authenticated:
{"auth": "public"}
{"token": "8a4f3e21d6c94b0e9f2a1c5b7d8e4f60"}
A freshly authenticated connection has no subscriptions; you must explicitly subscribe to each channel you want:
{"action": "subscribe", "channels": ["live_aggregate_data", "live_option_chain"]}
{"action": "unsubscribe", "channel": "live_option_chain"}
Wire format
Every server-sent message is a JSON object with a top-level channel field — dispatch on that, never on payload shape. Market-data channels nest their data under payload; event channels put id, type/data as siblings of channel:
{"channel": "live_aggregate_data", "payload": { … }}
{"channel": "live_option_chain", "payload": [{"strike": 5950, "call": {"bid": 4.2, "ask": 4.4, "delta": 0.523}, "put": {"bid": 3.1, "ask": 3.3, "delta": 0.477}}, … ]}
{"channel": "simulation_events", "id": 42, "type": "order_update", "payload": { … }}
{"channel": "end_of_data"}
Channels
| Channel | Cadence | Access |
|---|---|---|
live_aggregate_data |
1-second | Public + authenticated |
live_option_chain |
1-second | Token-authenticated only |
simulation_events |
Event-driven | Token-authenticated, per simulation |
backtest_events |
Event-driven | Token-authenticated, per strategy (source hash) |
end_of_data |
Terminal | — |
live_aggregate_data— the 1-second aggregate market feed (SPX, VIX, expected move).live_option_chain— the latest SPX option-chain snapshot. Each strike'scallandputcarrybid,ask, anddelta— the same fields the REST snapshot endpointGET /market-data/option-chain-snapshots/{timestamp}returns. (Second-order Greeks, IV, and theoretical price are no longer recorded.)simulation_events— discrete state changes for a live simulation:order_update(status transitions),financials_update(cash, buying power, realized P&L),ended, andsettlement_failed. Per-tick continuous values (P&L, delta) aren't pushed here — compute them fromlive_option_chain.backtest_events— strategy results progress for one content-addressed backtest. Subscribe per strategy with itssource_hash:{"action":"subscribe","channel":"backtest_events","source_hash":"<hex>"}(authorized against a saved strategy of yours with that source, or your live builder preview). Each frame carries the full fee-overlaid results snapshot underdata.snapshot(the same shapeGET /strategies/preview/{source_hash}/resultsreturns), folded for you — render straight from it, no per-tick refetch.data.typeis one ofstarted,day_completed,completed,stopped,failed. The HTTP results endpoint stays the source of truth for the initial load and reconnect. A dropped socket never stops a run; reconnect and re-subscribe.
Event ordering and recovery
Event-channel envelopes carry a monotonically increasing id. backtest_events deliberately has no replay — but it needs none: each frame carries the full current snapshot, so a missed frame self-heals on the next one, and the HTTP results endpoint backs the initial load and reconnect. For live-simulation state after a disconnect, refetch positions, orders, and transactions over REST to be safe.
Connection limits
- Anonymous (
{"auth":"public"}) connections stream for at most 5 minutes, after which the server sends{"channel":"end_of_data"}and closes. They may subscribe tolive_aggregate_databut notlive_option_chain. - Token-authenticated accounts have no concurrency limit and no time cap.
Quick test
( echo '{"auth":"public"}'; cat ) | websocat 'wss://api.0dtespx.com/__ws'
Subscribe messages sent before auth completes are ignored, and unknown channel names are silently dropped.