Stops that fill at the perfect price
A backtest that books every stop-loss exit exactly at the stop level, or assumes the target came before the stop, is quietly giving itself prices it could not have got.
The trap
Your strategy has a stop-loss at 100 points below entry. In the backtest, whenever price crosses that level, the trade is closed at exactly 100 points. It feels like the natural assumption. It is almost always too generous.
How it fools you
Most systems check their stop on a completed bar. By the time a 5-min bar closes below the stop, price has usually travelled further. The live system sells at that later price, not at the stop level. The time between price crossing the stop and the system acting on it is detection lag, and the extra distance is the overshoot.
On any single trade the overshoot is small. A system that stops out hundreds of times a year pays it hundreds of times.
There is a quieter cousin. If a backtest only knows a bar’s high and low, it cannot tell whether price hit your target or your stop first. “Did price ever reach the target today?” is not the same question as “did it reach the target before the stop?”
A real example
Detection lag. Our published opening-range breakout on NIFTY with its exact rules (30-minute range, trade only in the direction of the opening-range candle, stop and target both at R, exit by 15:00), run three times with one change: how a stop exit is filled. Data: back-adjusted NIFTY futures, 5-min bars, 1 October 2022 to 31 July 2026, 785 trades. Cost: 2 points per round trip. The target is a resting order filled at its level in every run.
- Naive: the stop fills exactly at the stop level whenever a bar’s low (or high) crosses it.
- Bar close: the system checks completed 5-min bars, so the stop fires only when a bar closes beyond it, at that close.
- Touch + 3: the stop fires the moment price touches it, filled 3 points worse than the level (or at the open, if the bar opens through it).
| Stop-fill model | Wider stop (R = ½ ATR): total | Per trade | Stops | Tighter stop (R = ¼ ATR): total | Per trade | Stops |
|---|---|---|---|---|---|---|
| Naive | +369 pts | +0.5 | 187 | +146 pts | +0.2 | 333 |
| Bar close | −642 pts | −0.8 | 170 | +130 pts | +0.2 | 294 |
| Touch + 3 | −201 pts | −0.3 | 187 | −857 pts | −1.1 | 333 |
On the bar-close model the average stop filled about 12 points beyond the level (median about 7) for both stop distances. The wider stop, our headline setting, goes from a small profit to a loss of 642 points. A 3-point slippage on 187 stops costs it 570 points, more than its whole naive profit.
The fill model also changed which stop looked best. Naive fills prefer the wider stop (+369 against +146). On bar-close fills the tighter stop comes out ahead (+130 against −642): it pays the same overshoot but avoids the stop-outs on bars that dip through the level and close back above it. With touch fills and slippage the order reverts, and both lose. A parameter choice made on naive fills was made on prices you could not have got.
Path order. NIFTY futures, 1-min bars, every trading day from 2 January 2023 to 31 July 2026 (882 days). Buy at the 09:20 open with a target and a stop at the same distance, T points away; exit at the close if neither is hit. Two ways to score the same trades:
| Target = stop = T | P(target ever reached) | P(target reached before stop) | Neither by close | Per trade, “ever reached” | Per trade, time order |
|---|---|---|---|---|---|
| 50 pts | 66% | 49% | 4% | +18.0 pts | +0.3 pts |
| 100 pts | 37% | 33% | 33% | +9.0 pts | +1.6 pts |
(Per-trade figures before costs.)
“Did price reach +50 today?” says yes on two days in three. “Did it reach +50 before −50?” is a coin flip: 49% target first, 48% stop first. Scored the first way, the ±50 bracket makes 18 points a trade and 14,084 points over the period after 2 points of cost. Scored in time order it makes 0.3 points a trade before costs, a loss of 1,516 after. The short side gives the same picture.
How to spot it
- Stop exits in your trade log are exactly the stop distance, every time.
- The tightest stop wins your parameter sweep.
- Win rates or “probability of reaching X” are calculated from daily or bar highs and lows.
- The backtest has no rule for a bar that touches both the target and the stop.
How we guard against it
Every result states its stop-fill model next to the numbers: bar-close exit, or intrabar touch with explicit slippage. When a bar touches both stop and target, we assume the stop came first. See Methodology: costs and parameter sensitivity.
Was this useful?
More to say, or spotted a mistake? Write to [email protected]. We read everything.