Futures Rollover in a Trading Bot: What Can Go Wrong at the Contract Switch
Futures expire. Anyone trading an index future like the E-mini S&P 500 is always trading a specific contract, and it gets replaced by the next one every quarter. For a manual trader, futures rollover is a date in the calendar. For a trading bot, it affects three things at once: the historical data it was tested on, the orders it sends live, and every level calculated across the switch.
What happens at rollover
The major US index futures run on a quarterly cycle - March, June, September, December - and expire on the third Friday of the month. Liquidity doesn't wait for expiration day, though: it usually moves to the next contract a good week earlier. From then on the old contract is thin, and anyone still trading it pays for that through worse fills. There's also a price difference between the two contracts, tied to interest and dividends - and that difference is the root of most data problems.
Three kinds of continuous contracts - and what each distorts
For backtests spanning several quarters, the individual contracts are stitched into one continuous series. How that's done determines which rules can be tested meaningfully at all:
- Unadjusted splice: every price is real, but each switch creates a jump that never happened in any market. Indicators react to it as if it were a genuine move
- Difference-adjusted (back-adjusted): older data is shifted by the price difference and the jump disappears. Distances in points are correct, past absolute prices no longer are
- Ratio-adjusted: older data is scaled by percentage. Percentage changes are preserved, point distances and absolute prices are not
Which rule needs which data series
- Distances and indicators such as moving averages, ATR multiples or stops in points: difference-adjusted data
- Fixed price levels such as round numbers, the prior day's high or volume profile levels: the real prices of the specific contract, not an adjusted series
- Percentage-based rules: ratio-adjusted data
- Result of a position held across a switch: calculated from the actual close and reopen, not from an adjusted price
On top of that comes a point that rarely gets mentioned: an adjusted series changes retroactively with every new switch. Rerun the same backtest a quarter later and it's running on different historical prices. The method, the roll rule and the data as-of date therefore belong with every test result.
Want your bot to handle the contract switch itself?
Describe the instrument and the strategy - the feasibility check and quote are free and non-binding.
Request a projectWhat the bot has to do on roll day
- Switch contracts: orders always go to a specific contract, never to a continuous series. The bot needs a clear rule for when it starts trading the new one
- Handle open positions: hold through the switch, close beforehand, or actively roll into the new contract - a deliberate decision rather than a silent default
- Carry levels over correctly: a prior day's high from the old contract sits offset by the price difference in the new one. Taken over unchecked, it lands in the wrong place
- Restart running calculations: cumulative values such as cumulative delta or session profiles start over in the new contract with its own data
For why cumulative values in particular hinge on their reset point, see the article on cumulative delta (CVD).
For other dates a plain time window doesn't cover, see the article on trading hours and time zones in a bot.
Frequently Asked Questions
When exactly should a bot switch to the new contract?
Not on expiration day, but once liquidity has moved - for the major index futures usually a good week before expiration. The exact date is set by your own roll rule, and that rule should be identical in the backtest and live.
Can I just test on my platform's continuous contract?
Yes, as long as it's clear how it's constructed and which rules it can meaningfully test. Anyone working with fixed price levels should take those from the real prices of the specific contract.
Is the price difference at rollover a loss?
No. Actively rolling means closing the position in the old contract and opening it in the new one - so there are two executions with fees and spread. The price difference between the contracts itself is neither a gain nor a loss.
Does a bot have to handle rollover automatically?
Not necessarily. For strategies that are rarely in the market, a manual switch four times a year can be enough. What matters is that the behaviour is defined and the bot doesn't keep trading the expiring contract unnoticed.
Rollover is as predictable as anything in futures trading gets - the dates are known years in advance. That makes it all the more frustrating when a bot trips over it. Every decision involved can be made at the design stage.
Have an idea for ATAS?
Tell us about your project - you'll get a free, non-binding quote within 24-48 hours.
Request a Free Quote