Concept
Session model: warp vs live, t_logical, speed_x
The venue has two execution modes and one clock abstraction. Live is wall-clock; warp is t_logical advanced at speed_x. Every order, fill, and candle row carries a (mode, speed_x, t_logical) triple so a consumer can always tell what frame of reference they're in.
Two modes, one matcher
- mode: "wall" — live matcher, wall-clock
t_logical = unix_seconds(),speed_x = 1.0. - mode: "warp" — partitioned book,
t_logicaladvances on everystepcall,speed_xis whatever you requested at session mint (0.1×–1000×).
How the clock ticks
In live mode the matcher is event-driven by HTTP arrivals and the wall clock. In warp mode, it's event-driven by the client's step calls. A step advances t_logical by1 / speed_x wall-seconds worth of historical tape; if you call step in a tight loop, the matcher will saturate one CPU and warp will throttle. The speed_x you mint with is thecap, not a guarantee.
curl -s https://api.taifoon.dev/tape/v1/clock | jq
# { "now": 1779047542, "speed_x": 1.0, "mode": "wall", "session": null }
curl -s 'https://api.taifoon.dev/tape/v1/clock?session=<sid>' | jq
# { "now": 1747353600, "speed_x": 100.0, "mode": "warp", "session": "<sid>" }Why everything is stamped
A candle from a warp session has the same JSON shape as a live candle. The mode,speed_x, and t_logical fields are how you tell them apart. If you persist warp candles into the same store as live candles without preserving the triple, you will eventually back-test against your own back-tests.
Equivalence: the matcher exposes a CI-gated test that runs the same input deck through wall-mode and warp-mode at speed=100× and diffs the fill stream byte-for-byte. Every merge to master must pass it.
Sessions are bounded
- Max wall-clock lifetime: 6h (matcher cancels-all and finalises on timeout).
- Max
to - fromhistorical window: 30 days (Phase A); 365 days (Phase B). - Max concurrent sessions per attribution: 1 (Phase A); 8 (Phase A.2).
