Execution contract is the promise between a strategy signal and the backtest engine. It says when the signal is known, when an order may be submitted, which price can fill, and which accounting rules are certified.
This matters because a single pos_weight column can mean very different
things:
- target exposure at the current close;
- signal observed at close and filled next open;
- entry plus stop-loss/take-profit/trailing behavior inside the next bar;
- explicit fills already generated by an external alpha;
- multi-order package lifecycle such as DCA/grid/basket/arbitrage.
QuantBT now makes those contracts explicit. Old endpoints remain compatible, but execution-sensitive alphas should use the narrowest contract that matches their domain.
| Contract | Endpoint | Signal phase | Fill phase | Intrabar semantics | Certification target |
|---|---|---|---|---|---|
close_target_v2 |
signal_notional, pct_equity, native vectorized |
bar close | bar close target accounting | none | Level 2 for close-target signals |
next_open_v1 |
reserved / event routes | bar close | next bar open | entry/exit only | future specialized route |
intrabar_bracket_v1 |
intrabar_bracket, intrabar_bracket_reference |
bar close | next bar open, then high/low path | SL/TP/trailing/reversal | Level 2 now, Level 3+ with parity bundle |
fill_replay_v1 |
fill_replay |
explicit fills supplied | explicit fill tape | alpha-owned | Level 1 accounting replay |
event_lifecycle_v2_next_bar_close |
native-event compatibility routes | command/event driven | market at effective-bar close; legacy OHLC triggers | order-owned, legacy frozen | reproducibility contract |
event_lifecycle_v3_next_open |
event_driven, explicit lifecycle, reactive strategy |
prior close observation or explicit tape | actual effective-bar open plus versioned gap rules | order-owned, ambiguity flagged | Level 2 with Python/Rust parity |
nautilus |
nautilus_validation, order/package validation |
event driven | Nautilus simulation | external engine | Level 4 route when configured |
Use close-target routes when the strategy already produced a target exposure series and does not claim stop-loss, take-profit, trailing-stop, or custom intrabar exit prices.
The model is intentionally simple:
signal[t] -> target exposure at close[t]
PnL[t+1] -> position[t] * (close[t+1] - close[t])
This is correct for research signals that do not depend on the inside of the
bar. It is not a certified route for alphas that generate exit_price,
exit_type, slpercent, tppercent, or high/low-based exits. If such columns
are present on a close-target run, QuantBT records an uncertified status in
metadata instead of silently claiming intrabar correctness.
Use intrabar_bracket_v1 when a strategy emits compact entry intent and the
engine must own:
- next-open entry;
- gap-aware stop-loss;
- limit-style take-profit;
- same-bar SL/TP conflict policy;
- trailing-stop update timing;
- technical exits;
- reversals as two fee-paying legs;
- optional final close;
- simple single-symbol liquidation checks.
The canonical timing is:
strategy observes bar t close
entry/reversal/technical exit may fill at open[t + 1]
stop/take-profit may fill within bar t + 1 using high/low
trailing stop updates after bar t + 1 close
The Python reference oracle is readable and should be used when debugging a new alpha migration. The Numba kernel is the production research path once parity is verified.
Use fill_replay_v1 when an alpha already emitted exact fills. QuantBT then
replays the fill tape for accounting only:
bar_index, sequence, side, qty, price
This certifies PnL/fee/funding/margin accounting from the supplied fills. It does not certify how those fills were generated. The right label is Level 1 unless paired with a separate causal fill-generation proof.
Use native event or Nautilus routes when the strategy has explicit order lifecycle requirements:
- market/limit/stop orders;
- order activation/cancel/replace;
- bracket/OCO packages;
- basket all-or-none packages;
- arbitrage multi-leg execution;
- DCA/grid state machines.
These routes are broader but slower than the narrow intrabar kernel. They are the right place for order/package semantics that cannot be reduced to a compact single-symbol bracket tape.
V2 is retained under its honest next-bar-close name for historical replay. V3 is the causal close-to-next-open contract and requires real open prices. The two IDs never alias to each other. Exact clock, gap, stop-limit ambiguity, bar-zero, final-bar, and typed lifecycle semantics are maintained in the native-event contract registry.
| Level | Label | Meaning |
|---|---|---|
| 0 | Legacy / unspecified | Backtest ran, but execution-sensitive claims are not certified |
| 1 | Accounting replay | Explicit fills were replayed correctly; fill generation remains alpha-owned |
| 2 | Engine causal | QuantBT owns causal execution semantics with oracle/kernel parity |
| 3 | Cross-backend | Native route matches another QuantBT route on known scenarios |
| 4 | External validation | Nautilus/lower-timeframe/external bundle is available |
Production-style claims should be at least Level 2. Execution-sensitive stakeholder reports should prefer Level 3 or Level 4 when feasible.
- Pure signal target: use close target.
- Entry at next bar and SL/TP/trailing inside the bar: use intrabar bracket.
- Old alpha emits fills: use fill replay first, then migrate to causal engine.
- Multi-leg package or grid state: use event lifecycle or Nautilus validation.
- If unsure, scan the alpha and treat the result as a migration hint, not proof.