Execution Assumptions
Daily-bar execution boundaries, fill priority, gap-through behavior and explicit model limits.
This page describes the order-mode model boundary. It should be read before trusting stops, limits, brackets, OCO or trailing-stop results on daily bars.
backtester/execution/fill_engine.pyFillEngine.process_bar(...)Daily-Bar Execution Boundary
Daily OHLC bars contain open, high, low and close. They do not contain the intraday sequence.
bar.open = 100
bar.high = 112
bar.low = 94
bar.close = 105
take_profit = 110
stop_loss = 95This bar proves that both levels were touched. It does not prove whether price hit 110 before 95, or 95 before 110. A daily-bar backtest must therefore apply a documented same-bar convention.
Same-Bar Convention
The fill engine processes active orders by priority:
STOP -> STOP_LIMIT -> STOP_TRAIL -> STOP_TRAIL_LIMIT -> LIMIT -> MARKET -> BRACKET -> OCOFor a long position with separate protective stop and take-profit, this makes same-bar ambiguity conservative: stop-like orders are evaluated before limit exits. This is acceptable for EOD research when the assumption is explicit. It is not tick-accurate execution.
Gap-Through Rules
A stop price is a trigger level, not a guaranteed fill price.
| Order | Trigger | Open-aware theoretical fill |
|---|---|---|
| Sell stop | bar.low <= stop_price | min(stop_price, bar.open) |
| Buy stop | bar.high >= stop_price | max(stop_price, bar.open) |
| Buy limit | bar.low <= limit_price | min(limit_price, bar.open) |
| Sell limit | bar.high >= limit_price | max(limit_price, bar.open) |
Slippage and commission are applied after the theoretical price is selected.
Stop-Limit Boundary
A stop-limit has two phases:
- The stop activates when the stop level is crossed.
- The activated limit order only fills at-or-better than its limit.
If price gaps through the limit, the order can remain pending instead of filling. That is different from a plain stop-loss.
Partial Fill Boundary
Volume participation can create partial fills. This models a maximum share of bar volume, not queue priority, hidden liquidity or exchange matching behavior.
Explicit Non-Goals
- Tick-level event reconstruction from daily bars.
- Exchange queue priority.
- Broker rejects and venue routing.
- Low-latency live execution.
- Guaranteed fill ordering when OHLC does not contain the path.
Audit Checklist
- What bar frequency was used?
- Did any candle touch both TP and SL?
- Which fill priority applies to same-bar ambiguity?
- Did a stop gap through the trigger level?
- Did a stop-limit activate but remain unfilled?
- Were partial fills enabled by
max_volume_participation? - Are slippage and commission documented in the report packet?