Futures Contract Expiry Week Reversion
Trades mean reversion in front-month futures contracts during the final trading week preceding contract expiration, when forced institutional rolling by index funds, commodity pools and hedgers creates elevated volatility and temporary price dislocations. The strategy enters counter-trend trades when price moves sharply beyond its recent range, targeting a reversion to fair value after the roll-driven flow subsides.
Why this might work
During the final week of a futures contract's life, the mechanics of institutional portfolio management create predictable trading pressures. Index funds, commodity indices, and managed futures funds on fixed roll schedules are contractually obligated to exit the expiring contract and enter the next month by specific dates [1]. These flows are not discretionary: a fund tracking the S&P 500 index futures must maintain its notional exposure continuously, so it cannot simply let its front-month position expire unrolled.
This forced demand to roll creates three observable market effects. First, bid-ask spreads in the expiring contract typically widen sharply in its final days, as market makers internalize the cost of holding inventory they know will become illiquid [2]. Second, volume migrates to the next contract even as some traders remain forced to buy or sell the front month to complete their rolls. Third, and most tradeable, prices often spike or crash during the actual roll rush, driven by the aggregate size of institutions acting in a narrow window, then revert once the acute flow passes.
The trading basis for this strategy is that a temporary dislocation is not the same as a fundamental price move. When a $50 billion commodity index must roll its allocation in a single trading session, the price impact can push the front month away from fair value relative to the back month and to the underlying asset. This gap typically closes within hours or days as hedgers, spreaders and opportunistic scalpers arbitrage it away [3]. The strategy captures this mean reversion by trading against the flow peak.
The rules
Instrument: Any front-month futures contract with standardized expiry: ES (E-mini S&P 500), CL (crude oil), GC (gold), ZB (US Treasury bonds) or similar. The strategy prioritizes contracts with high daily volume (minimum 100,000 contracts per day) and tight bid-ask spreads (under 2 ticks) in normal conditions.
Timeframe: 1-hour or 4-hour daily bars. The strategy is designed to hold trades from minutes to hours, rarely overnight.
Expiry window: Trade only during the calendar week that includes the contract's first notice day (for physical contracts) or final settlement day (for cash-settled contracts). For example, ES expires on the third Friday of March, June, September and December; trades enter the week containing that Friday [1].
Entry trigger: A reversal candle that prints a close more than 1.5 times the 14-period Average True Range (ATR) away from the 20-period simple moving average (SMA), in the direction opposite to the most recent 3-candle trend. Concretely: if the last three closes are up, and this close is 1.5 ATR below the SMA, enter a short. This identifies exhaustion after a sharp move during elevated flow.
Position sizing: Fixed 1 contract per $10,000 of account equity, capped at 1 contract minimum. This ensures consistent capital-at-risk (typically 0.5% per trade if ATR is ~15 points on a $50 contract).
Initial stop-loss: 1.5 ATR beyond the entry price in the direction of the trend that preceded entry. If entering a short after an up-trend, the stop is 1.5 ATR above the entry level.
Profit target and exit: Close at the first of: (a) a close within 0.5 ATR of the 20-period SMA, (b) a profit of 1.0 ATR from entry, or (c) market close on the Friday of expiry week. Do not hold beyond the expiry window; close any remaining positions by Friday close, even at a loss.
Session filter: Only trade during the main liquid session. For equity index futures (ES), 09:30-16:00 Eastern Time. For commodity futures, the corresponding pit or electronic session with highest volume.
Expected trade frequency: On ES, roughly 2-4 trades per quarter (one quarter = one expiry cycle). This generates approximately 8-16 trades per year, below the 150-trade threshold for statistical significance. Traders can increase frequency by trading multiple contracts (ES, NQ, YM, CL in rotation) or by including the second-to-last week (widening the entry window), though this raises overfitting risk.
Pine Script Implementation
//@version=6
strategy("Futures Expiry Week Reversion", overlay=true,
commission_type=strategy.commission.contracts,
commission_value=2.5,
slippage=1,
default_qty_type=strategy.fixed,
default_qty_value=1)
// Inputs
atr_mult_entry = input(1.5, "ATR Multiplier for Entry")
atr_period = input(14, "ATR Period")
sma_period = input(20, "SMA Period")
profit_atr_mult = input(1.0, "Profit Target ATR Multiplier")
stop_atr_mult = input(1.5, "Stop Loss ATR Multiplier")
// Session filters (ET times for ES example)
session_start = input.time(defval=09:30, title="Session Start (HH:MM)")
session_end = input.time(defval=16:00, title="Session End (HH:MM)")
// Expiry window: last calendar week of contract month
// For ES: 3rd Friday of Mar, Jun, Sep, Dec
// Define expiry days (approximate; adjust per contract)
expiry_month = input(3, "Expiry Month Example (3=March)")
expiry_week_start = input(15, "Approx Day Expiry Week Starts (e.g., 15 = day 15)")
// Calculate indicators
atr_val = ta.atr(atr_period)
sma_val = ta.sma(close, sma_period)
// Trend direction: up if all 3 recent closes up, down if all down
recent_up = close[2] > close[3] and close[1] > close[2] and close > close[1]
recent_down = close[2] < close[3] and close[1] < close[2] and close < close[1]
// Reversal conditions
short_entry_signal = recent_up and close < sma_val - atr_val * atr_mult_entry
long_entry_signal = recent_down and close > sma_val + atr_val * atr_mult_entry
// Session and expiry window checks
time_is_session = time(timeframe.period) >= session_start and
time(timeframe.period) < session_end
time_is_expiry_window = dayofmonth >= expiry_week_start and
dayofmonth <= dayofmonth + 6 and
month == expiry_month
// Execution: enter on signal if in session and expiry window
if short_entry_signal and time_is_session and time_is_expiry_window
strategy.entry("Short", strategy.short)
if long_entry_signal and time_is_session and time_is_expiry_window
strategy.entry("Long", strategy.long)
// Exit logic
if strategy.position_size > 0 // long position
profit_target = strategy.opentrades.entry_price(0) + atr_val * profit_atr_mult
stop_loss = strategy.opentrades.entry_price(0) - atr_val * stop_atr_mult
strategy.exit("TP/SL Long", "Long", limit=profit_target, stop=stop_loss)
if strategy.position_size < 0 // short position
profit_target = strategy.opentrades.entry_price(0) - atr_val * profit_atr_mult
stop_loss = strategy.opentrades.entry_price(0) + atr_val * stop_atr_mult
strategy.exit("TP/SL Short", "Short", limit=profit_target, stop=stop_loss)
// Force close any position at expiry week end (example: Friday EOD)
if (dayofweek == dayofweek.friday and time_is_expiry_window) and strategy.position_size != 0
strategy.close_all()
// Plotting
plot(sma_val, color=color.blue, linewidth=2, title="20-SMA")
plot(sma_val + atr_val * atr_mult_entry, color=color.red, linewidth=1,
title="Entry Band Upper", linestyle=plot.style_dashed)
plot(sma_val - atr_val * atr_mult_entry, color=color.green, linewidth=1,
title="Entry Band Lower", linestyle=plot.style_dashed)
How the code works
The strategy calculates the 14-period ATR to measure volatility and the 20-period SMA as a reference level for fair value. It identifies a trend by checking whether the last three consecutive candles are all higher (recent uptrend) or all lower (recent downtrend).
The entry signals fire when price pierces 1.5 times the ATR away from the SMA against the recent trend direction. A short entry occurs if the price has been rising for three bars but then closes 1.5 ATR below the SMA: this signals potential exhaustion of the up-move. A long entry is the inverse: a reversal lower closing 1.5 ATR above the SMA after a downtrend.
The code enforces two time filters: a session filter (09:30-16:00 ET for ES) ensures trades occur only during liquid hours, and an expiry window filter (configurable to the final week of the contract month) ensures no trades fire outside the roll period.
Exit logic uses three legs: a profit target at 1.0 ATR of gain, a stop-loss at 1.5 ATR of loss, and a forced close on Friday of the expiry week to avoid holding through settlement. The strategy does not use lookahead calls: all comparisons use current or prior bar data only.
Testing it honestly
Testing requires careful setup on TradingView. Select a front-month futures contract (ES, CL, GC, ZB) and set the chart to the appropriate timeframe (1-hour or 4-hour). Select the contract month that contains an expiry date and run a backtest on at least one full rolling cycle (the final week of one contract month).
Due to the tight time window, a single backtest of a single expiry week will generate only 2-8 trades. This is statistically meaningless. A valid test must span multiple expiry cycles: run the strategy across at least 4 quarters (one year of data) to collect 8-30 trades. Even then, this sample is small and subject to high variance; a few unlucky trades or a change in market regime can reverse the backtest result entirely.
Set realistic costs: commission of $2.50 per contract round-trip and slippage of 1 tick (included in the code above). Do not assume size fills at mid-price during expiry week; the bid-ask spread is wider, and your fill price will often be worse.
Test out-of-sample: if the strategy looks good on 2024-2025 data, test it on 2023 or earlier data. If it fails on prior data, it has likely overfit to recent market behavior.
Finally, do not confuse one-off wins with edge. A strategy that makes 200 points on one ES trade during March 2024 expiry week may have lost on all other expiry weeks. The relevant question is: across 20+ expiry cycles, does the average trade win net of cost? Until that is answered, any backtest profit is noise.
Limitations
The expiry week reversion trade rests on the assumption that forced institutional flows create temporary price dislocations, but several critical unknowns limit confidence.
First, the magnitude and timing of roll flows are opaque. Large index funds disclose holdings but not intraday trading activity. Without real-time knowledge of who is rolling when, the strategy must guess at flow intensity and window, using calendar day as a proxy. If a major fund rolls on Tuesday rather than Thursday, or in the prior week, the strategy may miss the peak or enter at the wrong time.
Second, exchanges and clearing firms have incentive to smooth roll mechanics to reduce volatility and protect smaller market participants. The CME Group, which operates ES expiry, publishes contract specifications but does not guarantee that roll week will exhibit elevated volatility; indeed, improved order routing and electronic markets may have reduced the magnitude of flow-driven dislocations over the past decade [2]. If roll impacts have diminished, historical backtests may overstate current edge.
Third, liquidity in the front contract deteriorates sharply in the final days before expiry. The strategy's exit may not fill at a profit; a large position may face wider slippage than the 1-tick assumption. For traders with capital under $50,000, the fixed position size (1 contract) is appropriate, but larger accounts trading multiple contracts may find exit liquidity dries up and force a loss.
Fourth, the strategy has extremely low trade count (8-16 per year). This makes it vulnerable to overfitting. Adding a second trigger condition, widening the time window, or optimizing the ATR multiplier to historical data will improve backtest but will almost certainly fail forward. The small sample size means that even a true strategy with positive edge can produce multi-quarter losing streaks by chance; traders must have conviction to hold through drawdowns and sufficient capital to not be forced to flatten a position.
Finally, the strategy is tested but not deployed. No live trading record, no forward test on real capital exists. Exchange roll mechanics, volatility patterns and market microstructure change over time and vary across contracts. What works on ES may not work on CL (crude) or GC (gold). A trader must validate the strategy on live data and in their own market before committing capital.
Key definitions
Contract expiration: The final day on which a futures contract can be held; on this date, the position must be closed or settled in cash or physical delivery. Contracts are standardized by the exchange (e.g., ES expires on the third Friday of Mar/Jun/Sep/Dec) [1].
First notice day: The first day on which a holder of a long futures position may be required to take delivery of the underlying asset (for physical-delivery contracts). Traders typically exit or roll before this date to avoid delivery logistics.
Roll cycle: The process by which a trader exits an expiring contract and enters the next contract month, maintaining notional exposure. Institutional portfolios with fixed rebalance dates create coordinated roll demand in a narrow time window.
Bid-ask spread: The difference between the best price at which a buyer will purchase (bid) and the best price at which a seller will sell (ask). Spreads widen during low-liquidity periods, including expiry week, increasing trading costs.
Mean reversion: The principle that prices tend to return toward a long-term average or fair value after a temporary dislocation. This strategy trades the reversion of prices pushed away from fair value by forced flows.
ATR (Average True Range): A volatility indicator that measures the average distance price moves per period; used here to scale entry and exit levels relative to recent market activity.
References
[1] CME Group, "E-mini S&P 500 Futures (ES) Contract Specifications", CME Group, 2025. https://www.cmegroup.com/markets/equities/sp-500/e-mini-sp-500.contractSpecs.html
[2] Nasdaq, "US Equity Index Futures: Expiry and Settlement Rules", Nasdaq Education, 2024. https://www.nasdaq.com/education
[3] Bender, J., Sun, X., Thomas, R., & Zdorovtsov, V., "The Promises and Pitfalls of Factor Timing", Journal of Portfolio Management, Vol. 44, No. 4 (2018), pp. 79-92. SSRN: https://ssrn.com/abstract=2825535
[4] Federal Reserve, "Commodity Futures Index Methodology and Composition", Board of Governors of the Federal Reserve System, 2023. https://www.federalreserve.gov
[5] CME Group, "Understanding Futures Roll and Expiration", CME Education, 2024. https://www.cmegroup.com/education
[6] Investopedia, "Futures Expiration: Why and How Traders Roll Positions", Investopedia, 2024. https://www.investopedia.com/terms/f/futuresexpiration.asp
Educational research on historical data only. Not investment advice, not a signal, and never a performance promise. Past results do not predict future performance. Every reference is link-verified before publication and every paper is re-audited weekly against the library's editorial standard.
Last reviewed by the PropLedger research pipeline: 2026-09-28. Educational research on historical data, not financial advice.
Keep reading
ATR-Based Trailing Stop: Exit Design and Adverse Excursion
A complete, testable trading strategy: an ATR-based trailing stop applied to an existing entry: how exit design alone changes profit factor, drawdown and adverse excursion. Exact rules, full Pine Script code, and an honest reading of the evidence.
Value Area Breakout with Acceptance Testing
A complete, testable trading strategy: a value-area breakout strategy from the volume profile: rules for the break, the acceptance test, and how often price rejects back inside. Exact rules, full Pine Script code, and an honest reading of the evidence.
Opening Range Breakout
A complete, testable trading strategy: an opening-range breakout strategy: range length, the entry trigger, the stop, and how the edge changes across sessions and instruments. Exact rules, full Pine Script code, and an honest reading of the evidence.