The ES chart running back ten years in your backtest platform is not a record of ES prices. No ES contract has ever lived ten years. Every one expired, and the chart was assembled from dozens of them by a stitching rule you probably never chose and cannot name. Depending on that rule, the prices on your screen are either interrupted by gaps that were never tradeable or shifted to numbers that never printed on any exchange. Both defects break specific categories of strategy logic and leave others perfectly intact. Knowing which is which decides whether a backtest transfers to live trading.
A continuous futures contract is a synthetic series built by stitching successive contract months together, so its historical prices are either discontinuous at every roll (raw splice) or shifted away from what actually traded (back-adjusted). Back-adjusted data preserves point differences exactly, which makes it correct for moving averages, ATR multiples and point-distance stops, and actively misleading for any rule keyed to a fixed price level. Because each new roll re-shifts the entire history, a backtest is not reproducible unless the adjustment method, the roll rule and the as-of date are recorded with the results.
Why is every long futures chart a construction?
Because contracts expire. The E-mini S&P 500 trades a quarterly cycle (March, June, September, December), so any single ES contract's useful life is measured in months. A multi-year chart has to be assembled from a sequence of separate instruments, and that assembly forces two decisions: when to switch contracts, and what to do about the price difference between them.
TradingView's support documentation is blunt about it. It defines a continuous futures contract as "an artificial financial instrument derived by linking multiple individual futures contracts with different expiration dates," and warns that because they are synthetic, "they may not accurately represent the actual traded prices of individual futures contracts." That is the data vendor, in its own help pages, telling you the chart prices are not the prices that traded.
Confirmation takes ten seconds: try to route an order to a continuous symbol. You cannot. Exchange order entry requires a specific contract with a specific expiry, so no broker accepts an order against a synthetic series.
What are the three stitching methods?
Three, and they differ in what they protect. Raw splicing protects the printed prices. Difference back-adjustment protects continuity of price changes. Ratio adjustment protects continuity of percentage returns. Only one of the three can hold in a given series.
| Method | Operation at each roll | Preserved exactly | Broken | Example implementation |
|---|---|---|---|---|
| Raw splice (unadjusted) | Concatenate, change nothing | Every printed price is real | A phantom gap at every join, equal to the roll spread | NinjaTrader MergeNonBackAdjusted |
| Difference back-adjust | Add (new close minus old close) to all prior bars | Point differences, and the P&L of a rolled position | Absolute price levels; can go negative | NinjaTrader MergeBackAdjusted |
| Ratio (proportional) adjust | Multiply all prior bars by (new close / old close) | Percentage returns | Point differences and absolute levels | Interactive Brokers TWS |
NinjaTrader's merge policy help guide defines MergeNonBackAdjusted as a mode where "Offset values are NOT used and leaves historical data as raw data," and MergeBackAdjusted as its mirror: "Offset values will be used to back adjust the historical price data to match the next front month." CSI Data describes the same arithmetic: "the new contract price minus the past contract price on roll-from day represents the delta price difference that is added to the past contract prices."
Ratio adjustment is different arithmetic, not a variant spelling. Interactive Brokers' Trader Workstation guide spells out the steps: "Calculate the ratio of closingPrice(Contract A)/closingPrice(Contract B)," then "Multiply all Contract B data for [the roll date] and all prior dates by this ratio." CSI describes its own ratio option as an enhancement of back and forward adjustment in which contracts are "joined by increasing or decreasing successively further distant contracts by a percentage." Sierra Chart offers back-adjusted and non-back-adjusted variants of both a date rule and a volume rule, and states that "the original prices are also preserved and never modified in the chart data file."
Every roll spread in the worked examples below is an illustrative number chosen so the arithmetic is clean and checkable, not an observed market quote.
How far off are back-adjusted prices?
By exactly the accumulated roll spread, with the sign set by term structure. For any given historical bar, define the cumulative adjustment C as the sum, over every roll that occurred after that bar, of (new contract price minus expiring contract price). Then back-adjusted price of that bar = actual traded price + C. In contango, where the deferred contract prices above the expiring one, C is positive and the adjusted history reads higher than what traded. In backwardation the deferred contract prices below, C is negative, and the adjusted history reads lower.
Equity index futures have generally sat in contango in recent rate regimes, because the roll spread on an index future is cost of carry, and financing rates have exceeded the S&P dividend yield. That relationship is not permanent, and the only authority on today's sign is today's calendar-spread quote. Take a bar sitting before eight consecutive rolls of +4.25, +5.50, +3.75, +6.00, +5.25, +4.50, +5.75 and +5.00, summing to C = +40.00. If it reads 4,240.00 on the back-adjusted chart, the actual traded price was 4,240.00 - 40.00 = 4,200.00. At the ES multiplier of $50 per index point, that 40.00-point distortion is worth 40.00 x $50 = $2,000 per contract. Flip all eight signs for the backwardation mirror: C = -40.00, and a chart reading 4,200.00 was a contract that actually traded 4,240.00.
The magnitude is not a fixed property of ES. Roll spread is approximately index level x (financing rate minus dividend yield) x fraction of a year between contracts. With round illustrative inputs: 6,000 x 3.00% = 180, and 180 x 0.25 = 45.00 points per quarterly roll, so eight rolls accumulate 8 x 45.00 = 360.00 points, or $18,000 per contract. That is the formula's output on made-up inputs. The real figure moves with the index level, the rate regime and the dividend calendar, and the only way to know it is the live calendar-spread quote.
Picture three real contract segments drawn end to end at their true traded prices: March, then June, then September. June ended 5.00 points below where September began, and March ended 4.25 points below where June began, so the raw series has two visible vertical gaps. Back-adjustment anchors on September and lifts the June segment by 5.00 and the March segment by 5.00 + 4.25 = 9.25, which makes both joins flush. Now draw one horizontal line at 4,200.00 across both versions. It touches completely different bars in each.
Which strategy rules survive back-adjustment?
Every rule that measures a distance, and no rule that names a price. Inside any one contract segment, back-adjustment adds a single constant to every bar, and adding a constant leaves every difference untouched.
Back-adjusted data is safe for every rule that measures a distance and dangerous for every rule that names a price.
Watch an absolute rule fail in both directions. Take C = +40.00 and the rule "buy a touch of 4,200.00." On the day the contract genuinely traded 4,200.00, the adjusted chart shows 4,200.00 + 40.00 = 4,240.00, so the backtest never sees the trigger. Meanwhile a bar printing 4,200.00 on the adjusted chart was a session where the contract actually traded 4,200.00 - 40.00 = 4,160.00, so the backtest fills a trade the market never offered. The rule misses real opportunities and manufactures fake ones at the same time, and the error is 40.00 points, or $2,000 per contract, in both directions.
Now watch a relative rule survive. An adjusted move from 4,240.00 to 4,265.00 is +25.00 points. The actual traded move underneath it, 4,200.00 to 4,225.00, is also +25.00 points. Both are worth 25.00 x $50 = $1,250. A 20-period simple moving average of adjusted prices equals the SMA of actual prices plus that same constant 40.00, provided the 20-bar window sits inside one contract segment, so price-minus-SMA is identical, ATR is identical, every crossover fires on the same bar, and every point-distance stop sits the same distance away. Windows that straddle a roll are the interesting case: there the adjusted series is the internally consistent one and the raw prices are the discontinuous ones. Percentage rules are slightly off under difference adjustment because the denominator moved, and that error grows the further back from the anchor you go, which is exactly what ratio adjustment exists to remove.
Back-adjustment is a per-chart or per-instrument setting on most retail platforms, not a universal default, so a continuous chart may well contain raw roll gaps. TradingView warns that "Rollover periods can cause sudden price jumps or gaps, which may impact technical analysis and trading strategies." Check the current setting in your own platform rather than trusting any article's description of a vendor default.
Why does back-adjustment get P&L right and the raw splice not?
The back-adjusted series is the correct record of what a continuously held and rolled position actually earned.
Take a trader long 1 ES bought in the September contract at 4,240.00. At the roll, September closes at 4,250.00 and December closes at 4,255.00, a roll spread of +5.00. The trader sells September at 4,250.00, buys December at 4,255.00, then later sells December at 4,275.00. Real P&L: the September leg made 4,250.00 - 4,240.00 = +10.00 points, the December leg made 4,275.00 - 4,255.00 = +20.00 points, total +30.00 points, or 30.00 x $50 = $1,500, before commissions and exchange fees.
The back-adjusted series lifts the September entry bar by 5.00 to 4,245.00 and leaves the exit at 4,275.00, showing 4,275.00 - 4,245.00 = +30.00 points. Exactly right. The raw spliced series shows 4,275.00 - 4,240.00 = +35.00 points, or $1,750, overstating by 5.00 points and $250 per contract. That error is precisely the roll spread, and it recurs at every roll a position spans. Raw splicing keeps every price honest and gets every multi-contract P&L wrong.
Difference versus ratio: how far apart do they drift?
They agree at the roll and diverge the further back you look, in proportion to how much the price level has changed. Take the same roll: expiring closes 4,250.00, new closes 4,255.00. The difference method adds 5.00 to every prior bar. The ratio method multiplies every prior bar by 4,255 / 4,250 = 1.0011764705882353.
On a historical bar of 4,000.00, the difference method gives 4,005.00 and the ratio method gives 4,004.71, a disagreement of 0.29 points or about $14.71 per contract. On a deeper bar of 2,000.00, the difference method gives 2,005.00 and the ratio method gives 2,002.35, a disagreement of 2.65 points or about $132.35 per contract. Both series are internally consistent. A percentage-return study belongs on the ratio series, a point-distance study belongs on the difference series, and running one on the other is a silent error that grows with lookback.
Why does the same backtest give a different answer next quarter?
Because back-adjustment is retroactive. Every new roll adds another offset to the entire history, so every historical bar changes value on roll day, including bars from years ago that you already tested against.
Concretely: you run a backtest today, a bar on a given historical date reads 4,200.00, and your rule "buy a touch of 4,200.00" fires there. Next quarter one more roll occurs with a spread of +5.25. Every bar before that roll shifts by another +5.25. The same bar on the same date now reads 4,200.00 + 5.25 = 4,205.25 and the rule no longer fires. Same code, same date range, same vendor, different trade list. A 50-bar moving-average crossover on that identical date produces the identical signal in both runs, because every price in the 50-bar window moved by the same 5.25 and the crossover only reads the gap between them.
Picture the pipeline drawn twice, side by side. Contract months feed a roll-rule box, which feeds an adjustment box, which produces a price series, which feeds a strategy-rule box, which emits a signal. The left run is labelled Q3: its adjustment box receives eight roll offsets, and the signal fires. The right run is labelled Q4 and is identical in every component except that one additional roll-offset arrow now feeds the adjustment box, the same date's price reads 4,205.25 instead of 4,200.00, and the signal does not fire. Exactly one edge differs between the two flows, and that one edge changes the answer.
So an absolute-price result is only meaningful when stamped with the adjustment method, the roll rule and the as-of date the series was built. Without those three it cannot be reproduced or compared against a later run. This is a cousin of the problems covered in how futures backtests get overfit, except the instability lives in the data rather than the parameter search.
Do two vendors' continuous ES series match?
No, and they can differ before adjustment is even considered, because they roll on different triggers. The mechanics of rolling a live position are covered in futures contract rollover explained. What matters here is that the trigger a data vendor uses to switch contracts in the historical series is a separate choice, and the menu is wide. Settings below are what each vendor's own documentation described at the time of writing; treat them as a prompt to check your own configuration, not as a current spec sheet.
| Vendor | Roll trigger | Adjustment |
|---|---|---|
| TradingView (1! symbol) | Front-month contract expiration | Back-adjustment offered as a chart setting; confirm the current method in TradingView's own help pages |
| NinjaTrader | User-set merge policy per instrument | Offset-based difference (MergeBackAdjusted), raw (MergeNonBackAdjusted), or single expiry only (DoNotMerge) |
| Interactive Brokers | A sequence of successively expiring "lead" contracts; the TWS guide does not state how lead status is assigned | Ratio multiplication |
| CSI Unfair Advantage | Open interest, volume, a specific date of the month, or strictly by days before expiration | Back or forward adjusted by difference, plus a ratio (proportional) option |
| Sierra Chart | Date rule or volume-based rollover | Back-adjusted or non-back-adjusted variant of each; original prices kept unmodified in the data file |
| Norgate | Business day prior to last trading day (cash settled), or business day prior to First Notice Day (deliverable) | Unadjusted, or arithmetic back-adjustment |
The TradingView row deserves a specific note. Its documentation states that the 1! contract "rolls over to the next contract when the current front-month contract expires." Volume in an equity index future typically migrates to the deferred contract around a week ahead of expiry, and exact timing varies by product and quarter, so an expiry-triggered series can keep tracking the dying contract through sessions where most of the volume has already left. Those bars are thin, wide and unrepresentative, which compounds the fill assumptions discussed in tick data versus bar data for backtesting. Compare the two contracts' volume yourself around a roll rather than assuming either behaviour.
How does a back-adjusted chart go negative?
By accumulating enough backwardation that the cumulative subtraction exceeds the historical price level. This is documented behaviour, not a bug. CSI Data states that "Back- and forward-adjusted contracts can include negative numbers, which Unfair Advantage is able to display in charts," and warns that "negative values may cause problems if files are exported for use with other software."
Take an illustrative market in persistent backwardation with monthly rolls averaging -$0.80. Over 60 rolls, five years, C = 60 x -0.80 = -$48.00. A price of $30.00 that genuinely traded appears on the back-adjusted chart as 30.00 - 48.00 = -$18.00. Nothing has broken. The series is correctly recording that a continuously rolled long collected enough roll yield that its total-return path, anchored to today's real price, has to start below zero. Platforms handle this differently: some display it, some clamp it, some refuse the export.
This is not an execution problem
No trade copier, execution stack or latency improvement fixes any of this, and it would be dishonest to suggest otherwise. Live execution runs on the real front-month contract at real prices, because that is the only thing a broker will accept. The defect lives entirely upstream, in how the research data was assembled.
What it causes is misdiagnosis. A trader whose strategy was built on absolute price levels in a back-adjusted series will watch live results diverge from the backtest, and the first suspects are always slippage, fill quality and copier latency. Those are the wrong suspects. The signals are firing on different bars live than they did in the test, because the test read a shifted series. Checking the data construction costs an afternoon. Chasing phantom latency costs months.
What should you actually do?
Four things, in order of payoff.
Find out what your data source does before you trust a long backtest. Two facts: the adjustment method and the roll trigger. Both are usually documented and often user-configurable. If you cannot find them, the results are uninterpretable no matter how good they look.
For short-horizon strategies, skip continuous data entirely. If the whole test window fits inside a single contract month, test on that individual contract. No stitching, no adjustment, no roll rule, and every price on the chart is a price that traded. Most platforms expose this as a specific-expiry load, NinjaTrader's DoNotMerge policy being one example, and it removes the entire class of problem.
Express rules in relative terms wherever the logic permits. Distances, multiples, crossovers and percentages are stable under back-adjustment and stable across reruns. Fixed price levels are not. If a rule genuinely needs an absolute level (a prior swing high, a session open, a settlement price), source that level from the individual contract's real prices and run the signal logic on the adjusted series. Sierra Chart preserving the original unmodified prices in the data file is exactly what makes that split practical.
Stamp every result set with method, roll rule and as-of date. Three fields in a header row. Without them, next quarter's rerun is a different experiment wearing the same name.
The honest limit: no adjustment method is correct for every purpose, and none ever will be. Preserving absolute price levels and preserving continuity across rolls are mutually exclusive by construction, because the roll spread is a real number and something has to absorb it. Raw splicing puts it in the price path. Difference adjustment puts it in the price levels. Ratio adjustment puts it in the point differences. Hunting for a "true" continuous series is a category error. Choosing the method that matches what your strategy actually reads, and writing down which one you chose, is the whole job.
Frequently asked questions
What is a continuous futures contract?
A continuous futures contract is a synthetic price series built by joining successive individual contract months into one long chart, because no single futures contract lives long enough to cover multiple years. TradingView's documentation calls it "an artificial financial instrument derived by linking multiple individual futures contracts with different expiration dates." It cannot be traded, because exchange order entry requires a specific contract with a specific expiry.
Is back-adjusted data bad for backtesting?
Back-adjusted data is correct for relative logic and misleading for absolute logic, so the answer depends entirely on how your rules are written. Moving averages, ATR multiples, crossovers, point-distance stops and rolled-position P&L all come out exactly right, because difference back-adjustment adds a single constant to a segment and constants cancel in every subtraction. Any rule that names a fixed price level is being evaluated against a number that never printed on an exchange.
What is the difference between back-adjusted and unadjusted futures data?
Unadjusted data concatenates each contract's real prices unchanged, so every printed price is genuine but every roll boundary contains a gap equal to the roll spread that was never tradeable. Back-adjusted data shifts all prior prices by that spread so the joins are flush, which fixes the gap and the P&L arithmetic but moves the historical price levels away from what actually traded. NinjaTrader exposes both as MergeNonBackAdjusted and MergeBackAdjusted.
Why do my backtest results change when I rerun the same code months later?
Because back-adjustment is retroactive and every new roll shifts the entire history again. If a bar read 4,200.00 last quarter and a new roll carried a spread of +5.25, that same bar on that same date now reads 4,205.25, so a rule keyed to 4,200.00 stops firing. Relative-logic results stay stable across reruns; absolute-price results do not, which is why the method and as-of date must be recorded with the results.
Can a back-adjusted futures chart show a negative price?
Yes, and it is expected arithmetic rather than a bug. In persistent backwardation each deferred contract prices below the one it replaces, so the cumulative subtraction can exceed the historical price level: 60 monthly rolls averaging an illustrative -$0.80 give a cumulative -$48.00, turning a real $30.00 print into -$18.00 on the chart. CSI Data documents displaying these negative values and warns they can cause problems when files are exported for use with other software.
Do TradingView and Interactive Brokers show the same continuous ES chart?
No, because each vendor picks its own roll trigger and its own adjustment arithmetic, and both choices change the printed history. Interactive Brokers' Trader Workstation guide describes ratio adjustment, multiplying all prior contract data by the ratio of the two closing prices, while TradingView exposes back-adjustment as a chart setting so two traders on the same platform can also see different histories. Difference adjustment preserves point moves and ratio adjustment preserves percentage moves, and the two diverge more the further back you look.
Is back-adjustment turned on by default?
Assume it is not, and check, because on most retail platforms back-adjustment is a per-chart or per-instrument setting rather than a universal default. A continuous chart with adjustment off contains raw roll gaps, which will silently corrupt any gap-sensitive or level-sensitive test. Vendor defaults are product settings and change over time, so verify the current state in your own platform instead of trusting a written description.
How do I avoid continuous contract problems entirely?
Test on an individual contract month whenever the entire test window fits inside one contract's active life. There is no stitching, no adjustment and no roll rule, so every price on the chart is a price that genuinely traded and every absolute-level rule is evaluated honestly. This works for most intraday and short-swing strategies and is the cleanest fix available.
Does a trade copier fix back-adjusted data problems?
No, and no execution tool can, because the defect lives upstream in the research data rather than in order routing. Live execution runs on the real front-month contract at real prices, since that is the only instrument a broker will accept. The practical risk is misdiagnosis: a backtest-to-live divergence caused by absolute-price rules on a shifted series gets blamed on slippage or copier latency instead of on the data construction.
Which adjustment method is the correct one?
None of them is correct for every purpose, because preserving absolute price levels and preserving continuity across rolls are mutually exclusive by construction. The roll spread is a real number and one of the three properties (printed prices, point differences, percentage returns) has to absorb it. Choose the method that matches what your strategy actually reads, then document the method, the roll rule and the as-of date alongside the results.