Indicators··7 min read

Spread Tracker: Two Futures Contracts

0 references, link-verifiedEditor of record: Shane CantyStandards review editorial standard · audit log

Monitors the price differential between two related futures contracts, useful for mean-reversion traders, arbitrage scouts, and market structure analysts who track co-movement of linked instruments like crude oil and heating oil, or equity index futures. The indicator displays the raw spread, a moving average to identify the typical range, and optional Bollinger Bands to flag extremes.

//@version=6
indicator("Spread Tracker: Two Futures", overlay=false)

// Inputs
contract1Input = input.symbol("ES1!", "First Contract")
contract2Input = input.symbol("NQ1!", "Second Contract")
spreadType = input.string("Absolute", "Spread Type", options=["Absolute", "Ratio", "Percentage"])
maLength = input.int(20, "Moving Average Period", minval=1)
showBands = input.bool(true, "Show Bollinger Bands")
stdDevMultiplier = input.float(2.0, "Band Standard Deviations", minval=0.1)

// Fetch prices from both contracts
price1 = request.security(contract1Input, timeframe.period, close)
price2 = request.security(contract2Input, timeframe.period, close)

// Calculate spread based on selected type
spread = switch spreadType
    "Absolute" => price1 - price2
    "Ratio" => price2 != 0 ? price1 / price2 : na
    "Percentage" => price2 != 0 ? ((price1 - price2) / price2) * 100 : na

// Moving average and standard deviation of spread
spreadMA = ta.sma(spread, maLength)
spreadStd = ta.stdev(spread, maLength)

// Bollinger Bands for the spread
upperBand = spreadMA + (stdDevMultiplier * spreadStd)
lowerBand = spreadMA - (stdDevMultiplier * spreadStd)

// Plot spread
plot(spread, "Spread", color=color.blue, linewidth=1)
plot(spreadMA, "Spread MA", color=color.orange, linewidth=2)

// Plot bands if enabled
if showBands
    plot(upperBand, "Upper Band", color=color.new(color.red, 50), linewidth=1, style=plot.style_dashed)
    plot(lowerBand, "Lower Band", color=color.new(color.green, 50), linewidth=1, style=plot.style_dashed)

// Zero line for reference
hline(0, "Zero Line", color=color.gray, linestyle=hline.style_dotted)

How the code works

The indicator pulls the latest close price from two user-specified contracts via request.security(), which retrieves data for symbols other than the active chart. The spread is calculated three ways: an absolute difference (contract1 minus contract2), a ratio (contract1 divided by contract2), or a percentage change ((contract1 minus contract2) divided by contract2 times 100). The user selects which representation best matches the trading setup.

A simple moving average (SMA) of the spread smooths short-term noise and reveals the typical mid-level around which the spread oscillates. Standard deviation measures how far the spread typically strays from that moving average; the Bollinger Bands multiply this standard deviation by a configurable number (default 2.0, matching the statistical 95 percent confidence interval) to draw upper and lower boundaries. When the spread breaches these bands, it signals an unusual divergence relative to recent history.

The zero line serves as a visual anchor: on the "Absolute" view, zero marks the point where both contracts have identical price; on "Ratio" view, 1.0 would be shown by setting the hline value manually; on "Percentage" view, zero marks zero difference as a fraction of the second contract.

Reading it on a chart

Traders use this display to identify three market states. A normal range occurs when the spread oscillates between the moving average and the bands, typical of stable market structure. A tight spread suggests the two contracts are moving in near-perfect lockstep, often indicating strong hedging demand or arbitrage activity keeping them paired. A wide spread or band breach shows the contracts have decoupled, which may signal a supply shock affecting one more than the other (e.g., a refinery outage widening crude–heating oil spread) or a change in carry cost.

Traders monitoring mean reversion look for spreads that push to the upper or lower band, expecting them to snap back toward the moving average. Arbitrage watchers flag extremes as potential opportunities to leg into or out of long-duration positions. Market structure analysts track whether the band width (volatility of the spread) is expanding or contracting, which hints at uncertainty or conviction in the relationship.

Switching between "Absolute," "Ratio," and "Percentage" matters for interpretation: absolute differences suit contracts with similar price levels (e.g., nearby crude oil contracts), ratios highlight relative price swings (useful for gold versus silver, where absolute point differences are misleading), and percentages normalize to the second contract's magnitude for cross-market comparisons.

Limitations

Symbol availability and data continuity: Pine Script cannot verify whether the entered symbols are valid or actively traded; entering a symbol that does not exist on the user's broker returns NaN. Front month futures contracts (e.g., "ES1!") roll on set dates; the indicator does not automatically jump to the next contract, so the spread will show a discontinuity or be invalid on roll day unless the user manually updates the symbol.

No intra-bar repainting: The indicator closes out calculations at bar end and does not recalculate mid-bar, but request.security() does introduce a one-bar lag when fetching data from a different symbol on the same timeframe. The moving average and bands are computed only from closed bars, delaying signals by at least one period.

Bollinger Bands assume normal distribution: The bands assume spread returns follow a normal distribution, which fails during market gaps, supply shocks, or regime changes. The 2.0 standard deviation heuristic is arbitrary and does not account for changing market regimes; in low-volatility periods, the bands may provide false confidence that extreme spreads are impossible, while in crises they may be too wide to signal anything useful.

Spread does not imply causation: A widening spread does not explain why the contracts decoupled. Cost-of-carry, volatility term structure, liquidity cascades, or news affecting one commodity more than the other all show up as a widening spread, but the indicator cannot distinguish them.

No adjustment for contract specifications: Futures contracts may differ in contract size, tick value, or trading hours. A spread of 100 points between two contracts may be enormous or negligible depending on their multipliers. Users must manually interpret the absolute spread in the context of each contract's specifications and account for any trading halts or liquidity gaps.

Key definitions

Spread: The price difference (or ratio or percentage change) between two related instruments, calculated as the first contract's price minus (or divided by) the second contract's price.

Moving Average (SMA): A simple average of the spread over the lookback period, smoothing short-term noise to reveal the typical level of the spread.

Standard Deviation: A measure of how far the spread typically deviates from its moving average; used to construct the Bollinger Bands.

Bollinger Bands: Upper and lower boundaries placed at the moving average plus/minus a multiple of standard deviation, marking the range within which the spread normally trades.

Mean reversion: The principle that prices that deviate sharply from their average tend to return toward that average over time.

Basis: The difference between the spot price (or one contract's price) and the futures price (or another contract's price); similar in concept to spread but often used specifically for spot-futures pairs.

References


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-10-18. Educational research on historical data, not financial advice.

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. Found an error? Email support@prop-ledger.org and the paper is corrected or withdrawn.