该策略交易七个欧盟股指期货,根据近期回报对表现较差的标的做多,对表现较好的标的做空,权重与其偏离基准的程度成正比。每周进行一次再平衡。

I. 策略概述

该策略针对欧洲七个国家的股指期货,包括德国、法国、意大利、西班牙、荷兰、比利时和奥地利,仅交易即将到期的最近月合约。根据过去五天的收益表现,将国家分为赢家(收益高于欧洲等权基准)和输家(收益低于基准)。策略内容为做多表现较差的输家并做空表现优异的赢家,仓位权重与其偏离基准的幅度成正比(偏离幅度越大,权重越高)。投资组合每周根据更新的表现进行再平衡,旨在利用欧盟股指期货市场中的均值回归趋势。

II. 策略合理性

短期逆向投资组合利用了过去赢家表现不佳、过去输家表现优异的趋势,从而产生超越基准的超额收益。这种行为符合过度反应假说,即交易者对新闻的调整超出基本面支持的合理范围。这些短期反转模式具有持续性,即使在高效市场中也为基于回报的策略提供了机会。通过利用这些规律,投资者可以从短期价格波动的可预测性中获利,抓住由过度反应及其后续修正驱动的市场低效性带来的机会。

III. 论文来源

Contrarian Long-Short Futures Arbitrages and Market Efficiency: Evidence in the Index Futures Markets around the Globe [点击浏览原文]

Chen, Kang, Lien

<摘要>

本文分析了在过去E天中卖出赢家并买入输家后持有H天的逆向多空期货套利,在1992-2002年期间的全球39个指数期货市场中展开研究。结果表明,{5,5}多空期货套利的标准化超额利润在除美国指数期货市场外的所有市场中均具有统计显著性。这些套利在9月现货月的周四/周五尤为显著,主要由回报反转和熊市条件驱动。因此,我们的研究表明,多空期货套利在大多数指数期货市场中可能仍然具有盈利能力。

IV. 回测表现

年化收益率29.6%
波动率N/A
Beta0.03
夏普比率N/A
索提诺比率-0.001
最大回撤N/A
胜率49%

V. 完整python代码

import numpy as np
from AlgorithmImports import *
class ShortTermReversal(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2000, 1, 1)
        self.SetCash(100000)
        
        self.symbols = ['EWG', 'EWQ', 'EWI', 'EWP', 'EWN', 'EWK', 'EWO']
        
        # Daily price data.
        self.data = {}
        self.period = 5
        self.SetWarmUp(self.period)
        
        for symbol in self.symbols:
            data = self.AddEquity(symbol, Resolution.Daily)
            data.SetFeeModel(CustomFeeModel())
            data.SetLeverage(5)
            
            self.data[symbol] = RollingWindow[float](self.period)
        
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Thursday), self.TimeRules.AfterMarketOpen(self.symbols[0]), self.Rebalance)
    def OnData(self, data):
        for symbol in self.data:
            symbol_obj = self.Symbol(symbol)
            if symbol_obj in data.Keys:
                if data[symbol_obj]:
                    price = data[symbol_obj].Value
                    if price != 0:
                        self.data[symbol].Add(price)
    def Rebalance(self):
        self.Liquidate()
        
        symbol_return = {}
        for symbol in self.symbols:
            if self.data[symbol].IsReady: 
                if self.Securities[symbol].GetLastData() and (self.Time.date() - self.Securities[symbol].GetLastData().Time.date()).days < 5:
                    closes = [x for x in self.data[symbol]]
                    symbol_return[symbol] = closes[0] / closes[-1] - 1
        
        if len(symbol_return) != 0:
            avg_ret = np.average([x[1] for x in symbol_return.items()])
            
            # Average return weighting.
            return_diff = {x[0] : abs(x[1] - avg_ret) for x in symbol_return.items()}
    
            total_diff = sum(x[1] for x in return_diff.items())
            weight_ratio = float(1 / total_diff)
    
            # Trade execution.
            winners = [x[0] for x in return_diff.items() if symbol_return[x[0]] > avg_ret]
            losers = [x[0] for x in return_diff.items() if symbol_return[x[0]] < avg_ret]
            
            for symbol in winners + losers:
                weight = return_diff[symbol] * weight_ratio
                if symbol in winners:
                    self.SetHoldings(symbol, -weight)
                elif symbol in losers:
                    self.SetHoldings(symbol, weight)
    
# Custom fee model
class CustomFeeModel(FeeModel):
    def GetOrderFee(self, parameters):
        fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005
        return OrderFee(CashAmount(fee, "USD"))




发表评论

了解 Quant Buffet 的更多信息

立即订阅以继续阅读并访问完整档案。

继续阅读