Original paper
Abstract
This study shows how the investor sentiment in the stock market affects prices of commodity exchange-traded funds (ETFs). The study provides quantitative evidence that the tracking errors of commodity ETFs differ in the bullish versus the bearish stock market, and the aggregate tracking error of commodity ETFs is sensitive to the well-known sentiment measures. The study exploits a profitable trading strategy based on investor sentiment in the stock market and commodity market. The sentiment-driven demand for commodity ETFs could exist even after consideration of trading costs, and it is a short-term phenomenon. This unique evidence indicates investor sentiment affects asset valuation across markets.
Keywords:Â Investor Sentiment; Tracking Errors; Commodity ETFs
Trading rules
- Investment universe: SPY and one broad commodity market ETF.
- If the previous day witnessed a bullish stock market, take a long position on the commodity ETF and a short position on SPY. Do this at the beginning of each day.
- Hold the portfolio for one day before closing positions.
Python code
Backtrader
import backtrader as bt
class MyStrategy(bt.Strategy):
def __init__(self):
self.spy = self.datas[0] # SPY
self.etf = self.datas[1] # commodity ETF
self.spy_price = self.spy.close
self.etf_price = self.etf.close
self.bullish_market = False
# Define the trading logic
def next(self):
if self.spy_price[-2] < self.spy_price[-1]:
self.bullish_market = True
else:
self.bullish_market = False
# Long the commodity ETF and short SPY
if self.bullish_market:
self.buy(self.etf)
self.sell(self.spy)
# Liquidate at the end of the day
self.closeall()
# Add data
data0 = bt.feeds.YahooFinanceData(dataname="SPY", fromdate=start_date, todate=end_date)
data1 = bt.feeds.YahooFinanceData(dataname="COMMOD", fromdate=start_date, todate=end_date)
# Create an instance of cerebro
cerebro = bt.Cerebro()
# Add our strategy
cerebro.addstrategy(MyStrategy)
# Add data to cerebro
cerebro.adddata(data0)
cerebro.adddata(data1)
# Set initial cash
cerebro.broker.setcash(100000)
# Run the backtest
cerebro.run()