Same-Bar Fills: The Lookahead Bug Developers Keep Rebuilding
CuteMarkets Team
Research
Same-Bar Fills: The Lookahead Bug Developers Keep Rebuilding
A signal generated from completed bar t should normally enter no earlier than the next observable bar or quote after t. Same-bar fills often introduce lookahead.

Same-Bar Fills: The Lookahead Bug Developers Keep Rebuilding
Abstract
Same-bar fills are one of the easiest ways to make an intraday strategy look better than it is. The bug is subtle: a completed bar creates a signal, but the simulator lets the strategy enter inside that same bar. The code appears realistic because the bar exists in the dataset. The decision is not realistic because the strategy did not know the full bar until it closed.
For options backtesting, this problem becomes larger because the entry then selects and prices an option using a timestamp that may already include information from the move that triggered the signal.
The Causal Rule
If a signal is generated from bar t, the earliest conservative default is entry on the next observable bar or quote after t. This rule feels strict, but it is the correct baseline for a developer who wants the simulation to survive contact with a live loop.
There are strategies that place stop or limit orders before a bar completes. Those need explicit order-state modeling. They should not be represented as "observe full bar, then fill inside it." That is not a minor implementation detail. It changes the information set.
Write The Event Timeline Down
The safest way to find same-bar leakage is to write the event timeline as data. A completed bar has an open time, close time, and publication time. A signal has an evaluation time. A contract selector has a discovery time. A quote has an exchange timestamp or feed timestamp. A simulated order has a route time and a fill policy. If those fields are missing, the simulator will eventually invent an ordering.
For a simple next-bar model, the timeline should be boring. Bar t closes, the signal evaluates after that close, contract selection runs at or after the signal time, and entry pricing uses the next quote or bar that would have been observable. If an implementation cannot express those timestamps, it cannot reliably prove that it is causal.
This is not only a theoretical problem. Intraday bars often compress many market states into one row. The high, low, close, and volume of that row are only known after the row completes. Using the high to detect a breakout and the same row's low to fill a favorable option entry is a classic hindsight path.
Why It Matters More In Options
In stock-only replay, a same-bar fill can flatter the entry price. In options replay, it can also flatter the contract choice. The selected strike, DTE, spread, and quote may all reflect the completed move rather than the earlier state.
That creates a double leak: the signal sees too much, and the instrument selection sees too much. A strategy can survive the stock chart and fail once contract selection is forced back to the timestamp it actually had.
Standing Orders Are A Different Model
Some strategies really do have orders resting before the bar completes. A breakout stop, a bracket order, or a marketable limit order can be modeled before the event if the strategy defines the order state in advance. That is a valid model, but it is not the same as next-bar replay.
The difference is that a standing-order model must know the order before the outcome. It should record when the order was placed, the trigger condition, the eligible instrument, the limit rule, and the cancellation rule. It also has to model whether the selected option was known at the placement time. If the contract is chosen only after the completed bar, the model has not solved the leakage problem.
Developers should therefore avoid a vague setting such as allow_same_bar_fill=true unless the simulator also records the order-state assumptions. A boolean flag hides too much. The right question is whether the entry was a reaction after the bar closed or an order that already existed before the bar evolved.
How To Test For It
Add regression tests around signal time and entry time. A test should prove that a touch or breakout on bar t enters no earlier than bar t+1 unless the strategy explicitly modeled a standing order before the touch.
Also inspect rejected trades. If a same-bar fix suddenly creates more quote misses or spread rejects, that is useful evidence. It means the old run was using a tradable surface that did not exist at the decision time.
A Useful Regression Test Shape
A minimal regression test can use a synthetic three-bar session. Bar one creates context. Bar two crosses the threshold and closes beyond it. Bar three is the first bar eligible for a reactive entry. The test should assert that the selected entry timestamp is on bar three or later. Then add a second test for a standing order, where the order is placed before bar two and can trigger inside bar two under explicit rules.
For options, add a contract-selection assertion. The selected contract must come from the universe visible at the eligible entry time, not from a universe built after the full move. If the test only checks the underlying bar, it can miss a leak in the option layer.
The best tests also assert rejection behavior. If no quote exists after the signal, the trade should reject. It should not fall back to a prior quote or the completed bar's convenient price unless that fallback is part of a documented policy.
What Usually Changes After The Fix
Fixing same-bar fills often reduces trade count, worsens average entry, and increases rejects. That does not mean the fix harmed the strategy. It means the previous result included information the live system would not have had. The corrected result is less flattering but more useful.
Sometimes a strategy still works after the fix. That is meaningful evidence. It means the edge did not depend entirely on catching an impossible intrabar price. More often, the fix moves a branch from "promising" to "needs redesign." That is also progress, because it closes a false path before paper trading spends time on it.
Takeaway
Same-bar fill bugs are not academic. They decide whether an intraday backtest is measuring a strategy or a hindsight rule. Developers should make next-bar semantics the default, then only loosen that rule when order state is modeled explicitly.
FAQ
Related questions
Why are same-bar fills risky?
They let the strategy react to a completed bar and still fill inside that same bar, using information that was not available at entry time.
Product links
Build the workflow with CuteMarkets
This article is part of the broader CuteMarkets product and research stack. Use the landing pages below to move from the blog into the specific API workflow you want to evaluate.
Learn Options From Zero
Send newcomers to the beginner path for calls, puts, chains, Greeks, IV, and risk.
Options Data API
See the canonical product page for real-time and historical options data.
Historical Options Data API
Inspect the historical contracts, quotes, trades, and aggregates workflow.
Options Chain API
Go straight to chain snapshots, expirations, and strike discovery.
Pricing
Review plans before you move from free evaluation into production usage.