pub enum FillModel {
TakerAtClose,
Resting,
}Expand description
How the replay engine turns orders into fills.
Selected via BacktestConfig::fill_model (builder:
.fill_model(FillModel::…)). Defaults to FillModel::TakerAtClose,
the engine’s historical behaviour — existing backtests are
bit-identical with the default.
Variants§
TakerAtClose
Legacy single-candle fills (the default).
Market / IOC / FOK entries and closes fill as takers at the decision candle’s close. Limit / post-only entries fill only if the decision candle itself crosses the level (marketability judged against the candle open; a marketable limit fills at the open as taker, a marketable post-only is rejected) and are dropped otherwise — nothing rests across candles. Protective brackets require both SL and TP legs and fill at their fixed level even when a candle gaps through it.
Resting
Honest resting-order semantics.
Orders reach the synthetic book at the decision candle’s close (the market price at decision time), so the decision candle can never fill a resting order — its range printed before the order existed (no lookahead).
- Market entries and closes fill at the decision close as takers, same as legacy.
- Limit / post-only entries marketable at the close fill immediately at the close as takers (a marketable post-only is rejected). Non-marketable ones rest (GTC) and fill on the first later candle that crosses the level: at the limit price on a cross, or at that candle’s open when the candle gaps through the level — never at a better price than the market offered. Resting fills are makers: maker fee rate, no slippage.
- IOC / FOK entries that are not marketable at the close are cancelled (the engine has no book depth, so both fill in full or not at all).
- Protective stops trigger on a cross and fill at the stop level or worse (gap through → that candle’s open), as takers with slippage. Take-profits are resting limits: level on a cross, open on a gap (price improvement), maker fee, no slippage. Standalone (stop-only or TP-only) brackets are honoured — legacy mode requires both legs.
- Same-candle ambiguity (multiple levels inside one candle’s range, OHLC path unknown) resolves to the worse outcome for the strategy: the stop leg fires before the take-profit leg; on the candle a resting entry fills, its attached stop may fire on that same candle, but its take-profit only becomes eligible from the next candle.
- At most one resting entry per symbol: any later non-
Holddecision that passes the risk gates cancels it (cancel-and-replace, where the replacement may be nothing).