
“该策略基于票房收益增长交易CRSP或标普500指数,如果日增长超过15%,则做多,否则做空,反映了娱乐驱动的市场情绪。”
资产类别: 差价合约、ETFs、基金、期货 | 地区: 美国 | 周期: 每日 | 市场: 股票 | 关键词: 票房
I. 策略概要
该策略使用CRSP等权重指数或标普500指数,并纳入来自Box Office Mojo的票房收益数据。每日票房收益增长(Changebox)计算为当季平均收益或前一周收益的百分比变化。实际上,Changebox计算为第d天和第d-7天的每日收益之差,除以第d-7天的收益。如果Changebox超过15%,则在第d天结束时做多;否则,做空。这种方法利用娱乐业的表现作为投资者情绪的代理,可能影响股票市场回报。
II. 策略合理性
票房收益是可自由支配消费的有效代理,反映了大量人口的消费习惯,2016年有71%的美国人去过电影院。该数据公开可用,并与GDP增长和可支配收入呈正相关,捕捉的是真实消费变化,而不是借入资金的变化。研究表明,票房收益也与行业投资组合回报呈正相关,排除了行业特定的偏差。然而,票房收益对股票回报的预测能力仅限于4天窗口,因此需要高换手率的投资策略,以利用由可自由支配支出趋势驱动的短期市场波动。
III. 来源论文
Is it Time for Popcorn? Daily Box Office Earnings and Aggregate Stock Returns [点击查看论文]
- Seda Oz 和 Steve Fortin,滑铁卢大学会计与金融学院,滑铁卢大学会计与金融学院
<摘要>
我们定量地衡量了每日消费与股票市场之间的相互作用。我们发现,以剧院票房收益的周期性成分为代表的每日消费,可以在长达五天的时间内显著且积极地预测股票回报。我们还展示了一种使用我们的消费指标的交易策略,该策略以很小的风险产生可观的超额回报。这些发现表明,票房效应是股票市场的一个重要的经济因素。该框架暗示,每日消费携带与价值相关的公共信息,从而导致每日频率的价格反应。


IV. 回测表现
| 年化回报 | 27.13% |
| 波动率 | N/A |
| β值 | -0.363 |
| 夏普比率 | N/A |
| 索提诺比率 | -1.486 |
| 最大回撤 | N/A |
| 胜率 | 31% |
V. 完整的 Python 代码
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()