Skip to content
GetProfitable
Search

Fill assumptions for limit and stop orders

Lesson 12 · about 10 min

A backtest on bar data has to guess what happened inside each bar. It knows the open, high, low and close and nothing about the order in which prices were visited or how much traded at each level. Every fill in the backtest is therefore an assumption, and the assumption is different for each order type. Getting this wrong is a leading cause of systems that "fill" at prices no one could have traded.

Market orders

A market order fills at the next available price. On bar data, the honest assumption is the open of the bar after the signal, plus slippage. Filling at the close of the signal bar is look-ahead unless you can genuinely act in the last seconds with the close known.

Stop orders

A buy stop at price P fills if the bar's high reaches P. The fill price is not P; it is P plus slippage, and in a gap it is the open of the bar, which can be far above P.

Bar open Bar high Stop level Filled? Fill price (1 tick slippage)
100.0 101.5 101.0 Yes 101.0 + tick
100.0 100.8 101.0 No
102.0 103.0 101.0 Yes, gapped 102.0 + tick (not 101.0)

Rule: fill = max(stop level, bar open) + slippage. The gap case is where naive backtests are most wrong, and it matters a great deal for stop-losses on daily bars: a stock that gaps down through your stop does not fill you at the stop.

Limit orders

A buy limit at price P is the hard case. If the bar's low is below P, the price traded through your limit, and you can be confident you filled (at P, with no slippage, and possibly at a better price if the bar opened below P). If the bar's low is exactly P, the price touched your limit and you may or may not have filled, because other orders were ahead of you in the queue.

Assumption Fill when low == P? Bias
Optimistic Yes Overstates fills at the best prices; these are the trades where price bounced off your level, which are the winners
Conservative No; require low < P (trade-through) Understates fills; some real fills are missed
Partial Fill a fraction Compromise; hard to model without volume at price

The optimistic assumption is the one that most default backtesters use, and it is systematically flattering for mean-reversion strategies. Think about which limit orders fill only at a touch: the ones where the price came down to your level and immediately reversed. Those are exactly the best trades. A backtest that counts all of them has an edge that partly consists of fills you would not have received.

Use the conservative assumption by default. If you have tick data, use the actual traded volume at your price to estimate queue position; if you do not, requiring a trade-through by one tick is the honest choice.

Key idea: A stop fills at the worse of the stop level and the bar open, plus slippage. A limit fills only if price trades through it, not merely touches it. Any backtester that assumes otherwise is giving you fills the market did not.

Same-bar stop and target

A trade opened on bar D has a stop and a target. On some later bar both levels are inside the range. Bar data cannot tell you which came first.

  • Conservative convention: the stop hit first. Use this by default.
  • Open-proximity heuristic: whichever level is closer to the bar's open hit first. Slightly more realistic, still a guess.
  • Lower-timeframe resolution: drop to 1-minute bars for that bar and check the sequence. The only real answer, and worth doing if your platform supports it.

A worked illustration of how much this matters:

Convention Trades Wins Avg R
Stop first 300 132 +0.19
Open proximity 300 141 +0.26
Target first 300 158 +0.41

Same rules, same data, same costs; the average R doubles depending on which guess you make about 26 ambiguous bars. If your platform defaults to "target first" or does not tell you, the reported result is unreliable.

Same-bar entry and stop

A related case: you enter on a stop order at bar D+1's open or intrabar, and the same bar's low is below your stop-loss. Did you get stopped on the entry bar? Conservative: yes. Many backtesters ignore stops on the entry bar entirely, which quietly removes the worst losses from the record.

Entering at the open

If your rule is "buy at the open", note that the printed open of a daily stock bar is the opening auction price, which retail market-on-open orders do receive. For intraday bars, the "open" of a bar is the first trade in that period, which you can only match if you were already in the queue. Model a tick of slippage.

Try it: Find every trade in your backtest where the entry bar's range includes both the stop and the target. Count them and compute the result under stop-first and target-first conventions. If the difference is more than a fifth of your total profit, get lower-timeframe data before trusting the result.

Recap

  • Market orders fill at the next open plus slippage, not at the signal close.
  • Stops fill at max(stop level, bar open) plus slippage; gaps through the stop fill at the open.
  • Limits fill only on a trade-through by default; touch fills flatter mean-reversion systems.
  • When stop and target share a bar, assume the stop hit first unless lower-timeframe data says otherwise.
  • Check whether your backtester honours stops on the entry bar; many do not.

See it drawn

Original diagrams for the ideas on this page. Illustrative, not real market data.

Slippage on a market orderA buy order clears four price levels, so the average price paid is worse than the price first quoted.Buy 1,000 shares at marketpricesell orders resting (bar length = size)20.04300 shares20.03200 shares20.01200 shares20.00300 sharesnothing resting at 20.02order sweeps up the bookaverage fill 20.02SLIPPAGE0.02 a share$20.00 in totalintended 20.00Each level fills at its own price; the average is what you really paid.
Slippage on a market order. You click at 20.00, but only 300 shares are resting there, so the rest of the order fills at 20.01, 20.03 and 20.04. The average price paid is 20.02, and that two-cent gap is slippage.
Risk and reward on one tradeA price scale showing an entry with a stop two points below and a target six points above, so the reward band is three times the risk band.PRICETARGET 106.00ENTRY 100.00STOP 98.00REWARDRISK6.00 pointsthree times the risk2.00 pointsthe most you loserisk : reward = 1 : 3
Risk and reward on one trade. One trade on a price scale: the entry sits 2.00 points above the stop and 6.00 points below the target, so the shaded reward band is three times the risk band. The ratio compares what is lost if the stop is hit with what is gained if the target is reached.
One daily candle broken into four six-hour candlesA tall daily candle on the left and the four six-hour candles that make it up on the right, with dashed lines linking the day's open to the first candle and the day's close to the last.ONE DAILY CANDLEFOUR 6-HOUR CANDLEScloseopenhighlow=00:0006:0012:0018:00one dayThe same trading, summed up in one bar or spelled out in four.
How timeframes stack up. A daily candle is not different data, only coarser data: it opens where the first six-hour candle opened, closes where the last one closed, and its wicks reach the highest and lowest prices any of the four touched.