
The strategy trades CRSP or S&P 500 based on box office earnings growth, going long if daily growth exceeds 15% and short otherwise, reflecting entertainment-driven market sentiment.
ASSET CLASS: CFDs, ETFs, funds, futures | REGION: United States | FREQUENCY:
Daily | MARKET: equities | KEYWORD: Box Office, Earnings
I. STRATEGY IN A NUTSHELL
Uses box office earnings growth to trade stocks. If weekly earnings rise >15%, go long; otherwise, go short. Leverages consumer sentiment as a short-term market signal.
II. ECONOMIC RATIONALE
Box office reflects discretionary spending and GDP-linked consumption. Strong earnings indicate positive investor sentiment; weak earnings signal caution. Predictive effect lasts about 4 days, requiring high-turnover trading.
III. SOURCE PAPER
Is it Time for Popcorn? Daily Box Office Earnings and Aggregate Stock Returns [Click to Open PDF]
Seda Oz, University of Waterloo – School of Accounting and Finance; Steve Fortin, University of Waterloo – School of Accounting and Finance
<Abstract>
We quantitatively measure the interactions between daily consumption and the stock market. We find that daily consumption, proxied by the cyclical component of theatrical box office earnings, can significantly and positively predict stock returns for up to five days. We also demonstrate a trading strategy using our consumption measures that yield non-trivial excess returns with little risk. These findings suggest that the box office effect is an economically important factor for equities. The framework implies that daily consumption carries value-relevant public information, which leads to price reaction at a daily frequency.


IV. BACKTEST PERFORMANCE
| Annualised Return | 27.13% |
| Volatility | N/A |
| Beta | -0.363 |
| Sharpe Ratio | N/A |
| Sortino Ratio | -1.486 |
| Maximum Drawdown | N/A |
| Win Rate | 31% |
V. FULL PYTHON CODE
from AlgorithmImports import *
#endregion
class DailyBoxOfficeEarningsandAggregateStockReturns(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2010, 1, 1)
self.SetCash(100000)
self.symbol = self.AddEquity("SPY", Resolution.Daily).Symbol
# Daily box data indexed by date.
self.daily_box_data = {}
# Import daily box data.
# Data source: https://www.boxofficemojo.com/daily/2020/?view=year
daily_box_string_data = self.Download('data.quantpedia.com/backtesting_data/economic/daily_box_earnings.csv')
lines = daily_box_string_data.split('\r\n')
for line in lines[1:]:
split_line = line.split(';')
date = datetime.strptime(split_line[0], "%Y-%m-%d").date()
if split_line[5] == '-':
weekly_change = None
else:
weekly_change = float(split_line[5])
self.daily_box_data[date] = weekly_change
def OnData(self, data):
date_to_lookup = (self.Time - timedelta(days = 1)).date()
if date_to_lookup in self.daily_box_data:
weekly_change = self.daily_box_data[date_to_lookup]
if weekly_change:
if weekly_change > 15:
self.SetHoldings(self.symbol, 1)
else:
self.SetHoldings(self.symbol, -1)
else:
self.Liquidate()
VI. BACKTEST PERFORMANCE