Commodity Spread Trading: Calendars, Cracks and Crush

Commodity spread trading isolates relative prices within the energy, ag, and metals complexes instead of betting on outright direction. A calendar spread trades two expiries of the same commodity; a crack spread trades crude vs refined products; a crush spread trades soybeans vs meal and oil. These are among the oldest systematic relative-value trades in futures — and they still work when the economics of storage, refining, and processing create temporary dislocations. This article covers the main structures and how to risk-manage them.

Why spreads instead of outright

Outright commodity futures embed:

Spreads cancel much of the common factor and leave structural economics:

SpreadLegsEconomic story
CalendarM1 vs M6 same commodityStorage, seasonality, inventory
CrackCrude vs gasoline / heating oilRefining margin
CrushSoybeans vs meal + oilProcessing margin
SparkNatural gas vs powerGeneration margin
LocationalSame product, different deliveryTransport / bottleneck

Calendar spreads

calendar = F_near - F_far

In contango, far > near; in backwardation, near > far. Calendar P&L comes from curve reshaping, not from spot level (approximately).

Drivers:

  • Inventory builds → curve toward contango
  • Seasonal demand (heating oil winter, gasoline summer)
  • Delivery constraints into expiry
def calendar_pnl(near_entry, far_entry, near_exit, far_exit,
                 qty_near=1.0, qty_far=1.0) -> float:
    """Long near / short far calendar P&L."""
    return qty_near * (near_exit - near_entry) - qty_far * (far_exit - far_entry)

Crack spreads

Refineries buy crude and sell gasoline and distillates. The 3:2:1 crack is the standard paper proxy:

crack_321 = 2 × gasoline + 1 × heating_oil - 3 × crude   (per barrel units)

When the crack is historically wide, the market is pricing rich refining margins — possible mean-reversion if capacity can respond. When crushed, refineries cut runs and products can tighten.

Caveats for quants:

  • Paper crack ≠ physical refining (location, quality, operational costs)
  • Seasonal patterns are strong but crowded
  • Margin and contract specs differ across legs — normalize to barrel-equivalent carefully
def crack_321(gasoline: float, heat: float, crude: float) -> float:
    """Gasoline and heat in $/gal; crude in $/bbl. Convert gal→bbl (*42)."""
    return 2 * gasoline * 42 + heat * 42 - 3 * crude

Crush spreads

Soybean processors buy beans, sell meal and oil:

crush = meal_value + oil_value - bean_cost

Use exchange-standard conversion factors (bushels, tons, pounds) — wrong units are the #1 bug in ag spread backtests. Crush embeds:

  • Processing capacity utilization
  • Export demand for meal/oil
  • Weather / crop reports (seasonality)

Risk that looks small until it is not

Spreads reduce beta to spot but concentrate idiosyncratic risk:

  1. Contract specs — wrong multiplier → fake P&L
  2. Expiry — near-leg squeezes into delivery
  3. Correlation breakdown — crack can move with crude in a crisis
  4. Liquidity — back months and products have wider markets
  5. Margin — exchange spread margin helps, but stress can spike requirements

Size by historical spread volatility and worst move, not by outright commodity vol. Use stress testing with "curve inversion" and "refinery outage" scenarios.

Systematic approaches

Mean-reversion on z-scored spreads:

import pandas as pd

def spread_z(spread: pd.Series, window: int = 60) -> pd.Series:
    mu = spread.rolling(window).mean()
    sd = spread.rolling(window).std()
    return (spread - mu) / sd

# Enter when |z| > 2, exit toward 0; filter with inventory / crack seasonality

Carry overlay: prefer calendars that also earn positive roll on the held structure (futures curve).

Inventory conditionals: EIA / USDA prints change the fair value of calendars overnight — event risk, not continuous alpha.

Backtest hygiene

  • Continuous contracts with explicit roll on each leg
  • Same timezone for energy inventory releases
  • Unit conversion tests (gal ↔ bbl, bu ↔ ton)
  • Bid-ask on thin product months
  • No lookahead on USDA/EIA (timestamp the print, not the day)

Event-driven engines handle multi-leg rolls more honestly than vectorized spliced series.

Key takeaways

  • Commodity spreads trade structural economics, not just price direction
  • Calendars, cracks, and crush are the core toolkit — get units right
  • Spot beta falls; idiosyncratic and event risk rise
  • Size on spread vol and stress scenarios, not outright vol
  • Inventory and seasonal calendars are features — and sources of crowding
#commodity spreads #crack spread #crush spread #calendar spread #futures