Backtesting & replay
Backtesting & replay
Replay a market’s real recorded history through a WebSocket with a test key, trade into it with simulated orders, and get a P&L summary — with zero real-money surface.
Replay streams a market’s actual recorded history — the trade tape, the quote at each trade, and the price ticks — over a dedicated WebSocket, paced at a speed you choose. You can place simulated orders into the stream and they fill against subsequent recorded prints, so a strategy can be validated against real markets before it ever touches money.
Replay and the sandbox scenario injector are
sandbox products. They accept a drzl_test_ key only — a live key is refused
by design. Start at Get an API key and mint one with
environment: "test".
What replay contains — and what it does not
This is the honest boundary, and every session opens with a coverage frame
that restates it for your requested window:
Two things are deliberately not offered rather than approximated:
- No order-book (L2) ladder replay. No book-ladder history is recorded anywhere on the platform, so replaying one would mean fabricating book states.
- No deep-history market-by-order (MBO) replay. The trading event log is archived and then deleted, so an MBO stream over old history would have gaps it could not honestly declare.
Every frame carries replay: true, and the replay envelope deliberately omits
the live stream’s sequence and channel keys — replayed history can never be
mistaken for the live feed.
Connect
wss://staging.drazill.com/api/v1/ws/replay
The first frame authenticates. A live key is refused before a socket is worth opening, so the client checks the prefix itself:
Three gates apply, each with its own close reason so you know which one failed:
Ask for a window
start is inclusive and end is exclusive, so two adjacent windows tile the
tape exactly once with no duplicated print. Speeds are 1, 10, 60, or
"max"; max streams as fast as backpressure allows, bounded by a per-session
frame budget rather than a clock.
Then {"type": "pause"}, {"type": "resume"},
{"type": "seek", "to": "<ISO-8601 instant inside the window>"} and
{"type": "stop"} control playback. replay_progress heartbeats report how far
along a long window is.
Trade into the replay
An order control frame places a simulated order into the session.
The fill model, stated plainly
- A resting BUY fills when a recorded print occurs at or below its limit; a SELL mirrors that.
- Fill size is capped by the recorded print’s own size. That is deliberately conservative: the tape is history, and a simulated order cannot change what actually printed.
- Partial fills accumulate across subsequent prints until the order is complete or the session ends.
- There is no queue-position modelling and no market impact. The same assumptions are returned inside the session’s own P&L summary, not just here.
tifisIOC(one look at the next print, then expire) orGTC(rests for the remainder of the session).
Fills arrive as replay_fill frames carrying synthetic: true and
livemode: false. Nothing is persisted — a replay session is ephemeral by
design, so no paper or real balance moves and no webhook fires. On stop (or
when the window is exhausted) a replay_complete frame carries the session P&L.
Run the whole thing
The tested quickstart lives at
sdks/python/examples/replay_quickstart.py,
with a matching notebook (replay_quickstart.ipynb) whose cells import from it.
Requires pip install drazill[websocket].
Where it is turned on
So the flow on this page works on staging today. A live key is refused in both environments regardless — that is the design, not a limitation of the rollout.
Next
- Stage a lifecycle event — make a fill, a resolution or a halt happen on demand against your own sandbox.
- Live realtime feeds — the separate, forward-only stream.

