
“该策略将50%分配给基于纳斯达克EMA的趋势跟踪策略,50%分配给使用标准普尔500指数ETF的逆趋势策略,并为每个策略设定特定的买入/卖出条件。”
资产类别: 差价合约(CFDs)、交易所交易基金(ETFs)、期货 | 地区: 美国 | 周期:
每日 | 市场: 股票 | 关键词: 动量、反趋势
I. 策略概要
投资范围包括跟踪纳斯达克综合指数和标准普尔500指数的两只ETF/期货。趋势跟踪策略使用纳斯达克价格的指数移动平均线(EMA),当收盘价高于50日和150日EMA时买入。如果价格低于50日EMA但高于150日EMA,则该策略转为现金,当价格低于两个EMA时卖空。逆趋势策略在今日低点为过去20天最低点时买入标准普尔500指数ETF,否则卖出。投资者将50%分配给每个策略。
II. 策略合理性
这种组合策略的本质在于实施一种机制,以减少短期反转的影响——即逆趋势策略。该策略仅在市场大幅下跌后才买入选定的ETF。结果是显著提高了回报/风险比率。
III. 来源论文
Opposites Attract: Improvements to Trend Following for Absolute Returns [点击查看论文]
- 利克(Leake),Anchor Capital Management Group, Inc.
<摘要>
最近的市场事件提醒了市场参与者多空趋势跟踪策略的长期盈利能力。虽然长期来看趋势跟踪可以盈利,但波动或无趋势的市场会使趋势跟踪充满挑战。在强趋势市场中,大幅的短期逆趋势波动很常见,如果不加以考虑,通常会在原本成功的趋势跟踪系统中产生大幅回撤。本文的目的是展示动量投资和逆趋势方法的简单量化混合,它提供了多空趋势跟踪策略的优势,并减少了回撤。结果是一种易于应用的投资方法,在35年的时间里,与基准指数相比,年回报率显著提高,风险降低。


IV. 回测表现
| 年化回报 | 12.2% |
| 波动率 | N/A |
| β值 | -0.313 |
| 夏普比率 | N/A |
| 索提诺比率 | 0.004 |
| 最大回撤 | -11.5% |
| 胜率 | 47% |
V. 完整的 Python 代码
from AlgorithmImports import *
class MomentumandCountertrend(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2000, 1, 1)
self.SetCash(100000)
self.SetWarmUp(150)
self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
self.qqq = self.AddEquity("QQQ", Resolution.Daily).Symbol
self.qqq_short_ema = self.EMA("QQQ", 50, Resolution.Daily)
self.qqq_long_ema = self.EMA("QQQ", 150, Resolution.Daily)
self.low_history_period = 20
self.spy_low_history = RollingWindow[float](self.low_history_period)
def OnData(self, data):
if self.IsWarmingUp: return
# QQQ trend-following strategy
if self.qqq_short_ema.IsReady and self.qqq_long_ema.IsReady:
if self.qqq in data.Bars:
qqq_close = data.Bars[self.qqq].Close
short_ema = self.qqq_short_ema.Current.Value
long_ema = self.qqq_long_ema.Current.Value
if (short_ema > long_ema) and (qqq_close > short_ema) and (qqq_close > long_ema):
self.SetHoldings(self.qqq, 1/2)
elif (short_ema < long_ema) and (qqq_close < short_ema) and (qqq_close < long_ema):
self.SetHoldings(self.qqq, -1/2)
# SPY counter-trend strategy
if self.spy in data.Bars:
spy_low = data.Bars[self.spy].Low
self.spy_low_history.Add(spy_low)
if self.spy_low_history.IsReady:
history_low = min([x for x in self.spy_low_history]) # low of the 20 most recent days
if history_low == spy_low:
self.SetHoldings(self.spy, 1/2)
else:
self.SetHoldings(self.spy, -1/2)