Tick Replay reconstructs the historical tick sequence inside each bar so that OnEachTick logic runs on historical data the same way it runs live. Some indicators and strategies genuinely need it for accurate historical intrabar calculation; others do not, and enabling it can encourage exactly the intrabar patterns that repaint. This article explains what Tick Replay does, when it is required, and how it interacts with OnEachTick repaint. It is educational only and is not trading advice; nothing here implies any result or profitability.
Tick Replay is a per-data-series option that feeds your script the historical intrabar ticks that built each bar, instead of only the bar's OHLC summary. Normally, historical bars carry no tick history — NinjaTrader knows the open, high, low, and close, but not the order the ticks arrived in. So under Calculate.OnEachTick, OnBarUpdate on historical data effectively fires once per bar as if only the closing tick occurred, while live it fires on every real tick. Tick Replay closes that gap by replaying the stored ticks, so historical OnBarUpdate fires tick by tick just as it will live.
You enable it in the data series properties of the chart or strategy (Tick Replay must also be turned on in Tools > Options > Market Data). It requires that tick data actually be stored for the instrument and period; without downloaded tick data there is nothing to replay. The cost is real: replaying every historical tick is far heavier than reading bar summaries, so load times and memory use rise sharply.
You need Tick Replay when a historical calculation depends on the path the price took inside a bar, not just its final OHLC. The clearest case is anything reading bid/ask or volume-at-price intrabar: order-flow tools, volume-delta and cumulative-delta indicators, bid/ask volume profiles, and footprint-style calculations. These read OnMarketData or per-tick bid/ask state that simply does not exist in bar-summary historical data. Without Tick Replay, they either produce nothing historically or produce a flat, wrong approximation.
You also need it when your OnEachTick logic makes intrabar decisions you want reflected historically — for example, a strategy that reacts to a threshold being crossed within a bar rather than at its close, and you want the backtest to model that intrabar reaction honestly.
You do not need it if your logic only reads completed bars under Calculate.OnBarClose. A close-only moving-average cross, a bar-close breakout, an ATR read on closed bars — none of these touch intrabar path, so Tick Replay adds cost and nothing else. Turning it on for a close-only strategy is a common way to slow a backtest to a crawl for zero benefit.
This is the part people get backwards. Tick Replay does not cause repaint and does not cure it — it changes what your historical backtest sees, which can either expose repaint or hide it depending on your code. Repaint is a property of your logic: reading a value that is not yet final and acting on it. If your strategy reads the current forming bar's Close[0] and enters on it, that is repaint whether or not Tick Replay is on:
// WRONG: acts on the still-forming current bar
protected override void OnBarUpdate()
{
if (Close[0] > High[1]) // Close[0] is not final intrabar
EnterLong();
}With Tick Replay off, that line historically evaluates once with the finished close, so the backtest looks clean and live diverges. With Tick Replay on, the same line historically fires on every replayed tick with a moving Close[0], so the backtest now reveals the intrabar instability — which is more honest, but the underlying logic is still repainting. Tick Replay made the flaw visible; it did not fix it. See [repainting](/learn/repainting) for the full treatment, and [look-ahead bias](/learn/look-ahead-bias) for why reading a not-yet-final value is a look-ahead problem.
The correct pattern under Tick Replay is to consume intrabar data for observation and state accumulation while making decisions on completed bars or on genuinely-final events. If you legitimately need per-tick processing, isolate the once-per-bar decision with IsFirstTickOfBar and guard CurrentBar so early bars do not throw:
// CORRECT: accumulate intrabar, decide on the closed bar
protected override void OnBarUpdate()
{
if (CurrentBar < 1) return;
if (IsFirstTickOfBar)
{
// a new bar just started; the prior bar is now final
if (Close[1] > High[2])
EnterLong();
}
// intrabar work that only observes, never acts on unfinished data
intrabarHigh = Math.Max(intrabarHigh, High[0]);
}For order-flow calculations that must read every tick, do the reading in OnMarketData or per tick, but store results and only commit a signal when the bar completes. The rule is invariant: never act on a value that can still change. Tick Replay gives you an accurate intrabar history to observe; it does not license you to trade off unfinished bars. This is the same divergence-source discussed in [why most backtests fail](/learn/why-most-backtests-fail) — a backtest that trades off intrabar values it treats as final will not reproduce live.
Decide with three questions. First, does any calculation depend on intrabar price path, bid/ask, or volume-at-price? If yes, you likely need Tick Replay and must have tick data stored for the instrument. If no, leave it off and save the load time. Second, are you running Calculate.OnEachTick or OnPriceChange? Tick Replay only changes historical behavior for per-tick calculation; under OnBarClose it has no effect on your logic and only adds cost. Third — and this is the one that protects your results — does your logic ever act on the current forming bar? If so, Tick Replay will surface the instability historically, but the real fix is to move the decision to a completed bar, not to toggle Tick Replay.
Before trusting any per-tick strategy, run it through the free [NinjaScript validator](/ninjascript), which flags intrabar acts-on-forming-bar patterns and unguarded barsAgo access regardless of whether Tick Replay is enabled. Tick Replay is a fidelity tool for historical intrabar accuracy — valuable when your calculation needs the tick path, wasteful when it does not, and never a substitute for writing logic that only acts on final data. This article is educational only, describes NinjaScript and NinjaTrader behavior, and makes no claim about profitability, win rate, or returns.
Educational only — not financial advice. Trading involves substantial risk of loss.