Quant Memo
Core

Intrabar Path Ambiguity in OHLC Bars

An OHLC bar tells you the open, high, low, and close of a period, but not the order they happened in. Any backtest with a stop and a target inside the same bar is silently guessing which one was hit first.

Prerequisites: Look-Ahead Bias

An OHLC bar compresses an entire minute, hour, or day of trading into four numbers. That's the whole point of the format — but it throws away the one thing a backtest with a stop-loss and a profit target both needs: the order in which prices were touched. If a bar's high would have hit your target and its low would have hit your stop, the bar alone cannot tell you which happened first. A backtest has to guess, and most guess wrong in a consistent direction.

Worked example: the bar that pays out twice

Enter long at 100 with a target at 105 and a stop at 95. The next bar prints Open 101, High 106, Low 94, Close 101 — both the target and the stop were touched somewhere inside that bar.

Assumed pathResultP&L
High reached before LowTarget fills first+5
Low reached before HighStop fills first−5

The true answer is unknowable from the bar alone — it depends on tick-by-tick data the backtest doesn't have. A naive engine that always checks "did we hit the target?" before "did we hit the stop?" will resolve every one of these ambiguous bars in the profitable direction, every single time. Run that over a few hundred trades and the strategy looks like it has a positive expectancy that is actually just a coin flip resolved in its own favor by the code's evaluation order.

Quantify it: suppose ambiguous bars (both levels touched) occur on 15% of the 400 trades a strategy takes per year, i.e. 60 trades. If the true intrabar order is a coin flip, the "always check target first" bug overstates annual P&L by roughly 60 trades × 10-point swing × 0.5 probability = 300 points of pure fiction, on top of whatever the strategy actually earns.

target 105 stop 95 path A: target first path B: stop first
Same bar, two equally consistent interior paths — one a winner, one a loser. The OHLC print cannot distinguish them.

When a bar's high and low both breach active exit levels, treat the outcome as genuinely unresolved rather than defaulting to whichever order your code happens to check first — a consistent default is a hidden, systematic look-ahead bias.

The direction of the bug is rarely random in practice: most backtest frameworks check conditions in the order they're written in the code, and "check the profit target, then the stop" is the natural way to write it. That ordering is exactly backwards from conservative, so unless you've deliberately handled the ambiguous case, assume your framework is currently doing this.

The honest fixes: use intrabar tick or sub-bar data where the strategy's economics depend on exit ordering, or, when only OHLC is available, resolve ambiguous bars pessimistically (stop wins ties) and report the pessimistic and optimistic bounds together so the reader sees how much of the edge depends on a guess.

Related concepts

Practice in interviews

Further reading

  • Pardo, The Evaluation and Optimization of Trading Strategies (ch. 6)
ShareTwitterLinkedIn