# Original paper

**Abstract**

Economists have traditionally viewed futures prices as fully informative about future economic activity and asset prices. We argue that open interest could be more informative than futures prices in the presence of hedging demand and limited risk absorption capacity in futures markets. We find that movements in open interest are highly pro-cyclical, correlated with both macroeconomic activity and movements in asset prices. Movements in commodity market interest predict commodity returns, bond returns, and movements in the short rate even after controlling for other known predictors. To a lesser degree, movements in open interest predict returns in currency, bond, and stock markets.

**Keywords:**Â Bonds, Business cycle, Commodities, Currencies, Futures market, Inflation

# Trading rules

- Create an equal-weighted commodity commodity portfolio covering four categories: agriculture, energy, livestock, and metals.
- Assess the dollar open interest of every commodity: spot price multiplied by the number of futures contracts outstanding.
- Aggregate total dollar open interest within each sector and compute its monthly growth rate.
- Compute the aggregate average growth rate of open interest: equal-weighted average of growth rates for each sector over the last 12 months.
- Identify the mean and standard deviation of commodity futures market interest for all available history.
- Go long on the basket of futures for one month if the current average 12-month growth rate in open interest exceeds a predefined threshold (e.g., 1.5 times the historical standard deviation).
- Conduct these computations on a monthly basis, constructing and holding the portfolio in accordance with market timing strategy indications.
- Consider incorporating additional prediction variables for a more complex model (e.g., short rate, yield spread).

# Python code

## Backtrader

```
import backtrader as bt
class CommodityMarketTiming(bt.Strategy):
params = (
('threshold', 1.5),
)
def __init__(self):
self.sector_weights = {'agriculture': 0.25, 'energy': 0.25, 'livestock': 0.25, 'metals': 0.25}
self.monthly_growth_rates = []
self.historical_sd = None
self.mean_market_interest = None
def next(self):
if len(self.data) % 20 != 0: # Perform calculations only once per month
return
current_month_dollar_open_interests = {}
for sector in self.sector_weights:
current_month_dollar_open_interests[sector] = self.data[sector].close[0] * self.data[sector].volume[0]
if len(self.monthly_growth_rates) >= 12:
self.monthly_growth_rates.pop(0)
if len(self.monthly_growth_rates) > 0:
last_month_dollar_open_interests = sum(self.monthly_growth_rates[-1].values())
current_month_dollar_open_interests_sum = sum(current_month_dollar_open_interests.values())
growth_rate = (current_month_dollar_open_interests_sum - last_month_dollar_open_interests) / last_month_dollar_open_interests
self.monthly_growth_rates.append(growth_rate)
if len(self.monthly_growth_rates) == 12:
avg_growth_rate = sum(self.monthly_growth_rates) / 12
self.mean_market_interest = avg_growth_rate
self.historical_sd = (sum([(x - self.mean_market_interest) ** 2 for x in self.monthly_growth_rates]) / 12) ** 0.5
if self.mean_market_interest is not None and self.historical_sd is not None:
threshold = self.mean_market_interest + self.params.threshold * self.historical_sd
if self.monthly_growth_rates[-1] > threshold:
for sector in self.sector_weights:
target_weight = self.sector_weights[sector]
current_value = self.data[sector].close[0] * self.getposition(self.data[sector]).size
target_value = target_weight * self.broker.getvalue()
size_diff = (target_value - current_value) / self.data[sector].close[0]
self.order_target_size(data=self.data[sector], target=size_diff)
else:
for sector in self.sector_weights:
self.close(data=self.data[sector])
cerebro = bt.Cerebro()
# Add data feeds for the four commodity sectors
# cerebro.adddata(...)
# ...cerebro.addstrategy(CommodityMarketTiming)
cerebro.run()
```

Please note that this code assumes you have added the required data feeds for each commodity sector to the `cerebro`

instance. You will need to replace the lines commented with `# cerebro.adddata(...)`

with the actual data feeds.