该策略基于10年期国债波动率指数期货,但也可用于VIX期货或罗素2000波动率指数期货。策略在美国劳工统计局每月第一个星期五公布失业率前一天的美国东部时间下午4:15卖出期货,并在公布日当天的下午4:15关闭仓位。

策略概述

投资范围包括10年期国债波动率指数期货,但为了创建类似的策略,也可以使用不同的期货合约(如VIX期货或罗素2000波动率指数期货)。美国劳工统计局在每个月的第一个星期五公布失业率。前一天美国东部时间下午4:15卖出期货,并在公布日当天美国东部时间下午4:15关闭仓位。

策略合理性

隐含波动率指数,有时也被称为恐慌指数,与市场不确定性相关。当失业率公布时,关于就业市场和经济状况的最新信息会被公布,吸引众多投资者关注。研究表明,公告发布后,不确定性下降,波动率指数随之降低。因此,在失业率公布前一天隐含波动率较高时开立波动率指数期货头寸,并在市场不确定性消除后(即公告发布后)关闭头寸,可形成一个盈利的交易策略。

论文来源

Resolution of Financial Market Uncertainty Around the Release of Unemployment Rate Announcements [点击浏览原文]

<摘要>

我们提供证据表明,失业率公告的发布无条件地导致股票、国债、大宗商品和外汇市场的不确定性解决。该发现具有经济价值。一个简单的每日策略是在失业率公告发布前卖出10年期国债波动率指数期货,并在公告发布后平仓,年化夏普比率达到3.79,而类似的VIX期货日内策略则产生3.98的年化夏普比率。尽管这种不确定性消除与失业率意外值的大小无关,我们也发现,高于(低于)预期的失业率会削弱(加强)不确定性解决过程。

回测表现

年化收益率2.85%
波动率0.75%
Beta-0.191
夏普比率3.79
索提诺比率N/A
最大回撤N/A
胜率31%

完整python代码

from AlgorithmImports import *
#endregion
class MarketUncertaintyResolutionFollowingTheUnemploymentAnnouncements(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2011, 1, 1) # VIX starts from 2011
        self.SetCash(100000)
        self.unemployment_rate_dates:list[datetime.datetime] = []
        csv:str = self.Download('data.quantpedia.com/backtesting_data/economic/UNEMPLOYMENT_RATE.csv')
        lines:list[str] = csv.split('\r\n')
        for line in lines[1:]: # skip header
            if line == '':
                continue
            split:list[str] = line.split(';')
            date_str:str = split[0]
            date:datetime.date = datetime.strptime(date_str, '%d.%m.%Y').date()
            self.unemployment_rate_dates.append(date)
        
        # subscribe vix
        self.continuous_contract:Future = self.AddFuture(Futures.Indices.VIX, resolution = Resolution.Minute,
                                                  dataNormalizationMode = DataNormalizationMode.BackwardsRatio,
                                                  dataMappingMode = DataMappingMode.FirstDayMonth,
                                                  contractDepthOffset = 0)
    def OnData(self, data: Slice):
        curr_time:datetime.datetime = self.Time
        curr_date:datetime.date = curr_time.date()
        next_day:datetime.date = curr_date + timedelta(days=1)
        # NOTE The futures listed in CME or CBOT have their data set in Chicago Time
        # EST -> Chicago time conversion
        if next_day in self.unemployment_rate_dates and curr_time.hour == 15 and curr_time.minute == 15:
            # buy VIX contract
            mapped_contract_symbol:Symbol = self.Securities[self.continuous_contract.Mapped].Symbol
            self.SetHoldings(mapped_contract_symbol, 1)
        elif curr_date in self.unemployment_rate_dates and curr_time.hour == 15 and curr_time.minute == 15:
            # sell VIX contract
            self.Liquidate()

Leave a Reply

Discover more from Quant Buffet

Subscribe now to keep reading and get access to the full archive.

Continue reading