Introduction

 

Contango in Futures occurs when the spot prices of further-term contracts are higher than that of the expected spot price adjusted for continuous-compounded interest rate. This phenomenon can occur in a variety of markets, including commodities like oil and natural gas, as well as financial instruments like stock indices and currencies. It is commonly referred to as the Futures yield curve. Contango is generally considered to be a normal market condition, as it reflects the cost of carrying the underlying asset over time. When a commodity is in contango, it means that buyers are willing to pay a premium to ensure that they can take delivery of the commodity at a future date, rather than having to buy it at the spot price in the present.

Source: CME Group. (n.d.) What is Contango and Backwardation.  

 

What Contributes to Contango?

Contango can occur for a variety of reasons, including:

  1. Storage costs: If a commodity has storage costs associated with it, such as oil or natural gas, then the futures price may reflect these costs, as buyers are willing to pay a premium to ensure that the commodity is available for delivery at a future date.
  2. Interest rates: Contango can also be influenced by interest rates, as buyers may be willing to pay a premium to lock in a future price, rather than having to pay the higher spot price in the present. This is especially true if interest rates are low, as the opportunity cost of carrying the commodity over time is lower.
  3. Supply and demand: Contango can also be influenced by supply and demand factors, as buyers may be willing to pay a premium to ensure that they can take delivery of a commodity at a future date if they believe that supply will be constrained in the future.

The degree of contango increases due to rising costs in holding physical assets, such as storage, insurance, and financing. When investors believe these costs will increase, the demand for using a forward contract to secure the trading price increases. Since there is a price difference between the future price and the spot price, arbitrage opportunities exist for traders using various future pricing models.

 

Method

In this strategy, we try to profit from predicting the development of this horizontal spread and monetary inflation. We set our universe to be all gold Futures contracts expiring within 90 days to avoid holding a single position for too long.

# Subscribe and set our expiry filter for the futures chain
self.future_g_o_l_d = self.add_future(
    Futures.metals.GOLD, 
    resolution = Resolution.MINUTE,
    data_normalization_mode = DataNormalizationMode.BACKWARDS_RATIO,
    data_mapping_mode = DataMappingMode.OPEN_INTEREST,
    contract_depth_offset = 0)
# Expiry between 0 and 90 days to avoid naked position stays for too long to tying up funds
self.future_g_o_l_d.set_filter(0, 90)

Note that physical product storage expenses depend on the demand and value of the physical product; for example, expensive gems may require higher security costs, and oil needs physical tanks. Since contango is most likely to happen when projected costs are higher, we can bet on the Future going more contango when projected costs rise. To predict the acceleration in price (or increase in return), we set up an SMA of ROC indicator to predict short-term return mean-reversion.

# 20-day SMA on return as the basis mean-reversion predictor
self.roc = self.ROC(self.future_g_o_l_d.symbol, 1, Resolution.DAILY)
self.sma = IndicatorExtensions.of(SimpleMovingAverage(20), self.roc)

We predict a price acceleration when the last return is lower than the trailing mean return. We then measure the horizontal spread between each pair of contracts in the universe, select the pair of contracts that has the lowest horizontal spread, buy the contract in the pair with the furthest expiry, and sell the contract in the pair with the nearest expiry to maximize the possibility of price divergence upwards (contango).

# We only trade during last-day return is lower than average return
if not self.roc.is_ready or not self.sma.is_ready or self.sma.current.value < self.roc.current.value:
    return

spreads = {}

for chain in slice.future_chains:
    contracts = list(chain.value)

    # if there is less than or equal 1 contracts, we cannot compare the spot price
    if len(contracts) < 2: continue

    # sort the contracts by expiry
    sorted_contracts = sorted(contracts, key=lambda x: x.expiry)
    # compare the spot price
    for i, contract in enumerate(sorted_contracts):
        if i == 0: continue

        # compare the ask price for each contract having nearer term
        for j in range(i):
            near_contract = sorted_contracts[j]

            # get the spread and total cost (price of contracts and commission fee $1 x 2)
            horizontal_spread = contract.bid_price - near_contract.ask_price
            total_price = contract.bid_price + near_contract.ask_price + 2
            spreads[(contract.symbol, near_contract.symbol)] = (horizontal_spread, total_price)

# Select the pair with the lowest spread to trade for maximum potential contango
if spreads:
    min_spread_pair = sorted(spreads.items(), key=lambda x: x[1][0])[0]
    far_contract, near_contract = min_spread_pair[0]

    num_of_contract = max((self.portfolio.total_portfolio_value / min_spread_pair[1][1]) // self.future_g_o_l_d.symbol_properties.contract_multiplier, 1)
    self.market_order(far_contract, num_of_contract)
    self.market_order(near_contract, -num_of_contract)

 

Results

Since it is a long-short strategy, we used buy-and-hold 10y US bond ETF - IEF as the benchmark. Result metrics over three years are as shown below:

Future Contango Prediction IEF Benchmark
Total Return 6.875% 3.941%
Compounded Annual Return 0.843% 0.489%
Sharpe Ratio 0.178 0.090
Information Ratio 0.028 -0.092
Maximum Drawdown 14.200% 22.800%
Annual Standard Deviation 0.036 0.054

 

Discussion

The strategy successfully yielded a higher return with a better Sharpe Ratio compared with the IEF benchmark. This suggests that there are arbitrage opportunities and the market is not utilizing all its information on pricing future contracts with collateral charges. The current implementation doesn't evaluate the potential contango chance and size. To improve the strategy, we could set up a calculator for that and an early exit handler to free up invested capital for more opportunities. We might also improve future contango prediction. Another suggestion would be to construct an efficient portfolio by treating the price difference between a pair of contracts as a single series to obtain a covariance matrix for all pairs. We can thus include more assets and contracts to scale up the investment.

 

References

  1. CME Group. (n.d.) What is Contango and Backwardation. Available at https://www.cmegroup.com/education/courses/introduction-to-ferrous-metals/what-is-contango-and-backwardation.html