择时与轮动:动量轮动策略的设计与陷阱
本课目标:搭建一个结构完整的动量轮动框架,并学会识别轮动策略里最常见的几个坑。
先给择时一个清醒的定位
在量化研究的难度谱系里,择时大概是最难的一档。选股是横截面问题,同一时刻你有几千个样本可以比较;择时是时间序列问题,一年只有大约两百多个交易日,真正的大级别拐点一年可能只有几次。样本少、噪声大,意味着任何择时信号都很容易是运气。
轮动策略可以看作择时的一个”折中版”:它不直接判断市场涨跌,而是在一组资产里持续比较相对强弱,把仓位从弱的资产挪到强的资产上。你不需要预测绝对方向,只需要排序——这在统计上比预测点位要求低得多,也更容易验证。
在 A 股语境下,最常见的轮动标的是行业指数和宽基/行业 ETF。ETF 交易门槛低、没有个股停牌和退市的麻烦,很适合作为轮动研究的起点。候选池不宜太大也不宜太小:太小则轮动等于在两三个资产间反复横跳,分散意义有限;太大则排名噪声上升、研究焦点涣散,一般十个以内、彼此逻辑上有差异的资产就够起步了。本文只讨论研究方法,不构成投资建议。
通用框架:排序、持有、再平衡
几乎所有动量轮动策略都可以压缩成三步:
- 排序:在再平衡日,计算候选池内每个资产过去 N 个交易日的动量得分(最朴素的就是区间涨幅),从高到低排序。
- 持有:买入排名前 K 的资产,通常等权持有。
- 再平衡:每隔 H 个交易日重复上述过程,卖出跌出前 K 的资产,买入新进入的资产。
用 pandas 表达核心逻辑大致是这样:
import pandas as pd
# prices: DataFrame, index 为交易日, columns 为各 ETF 代码lookback, hold_n = 60, 2
momentum = prices.pct_change(lookback) # 回看 60 日涨幅rank = momentum.rank(axis=1, ascending=False) # 横截面排名signal = (rank <= hold_n).astype(float) # 前 2 名等权持有weights = signal.div(signal.sum(axis=1), axis=0)# 实际持仓要向后错一天,避免用当日收盘信号成交当日收盘价weights = weights.shift(1)注意最后那行 shift(1):信号在 T 日收盘后才能算出来,最早 T+1 才能执行。漏掉这一步,回测结果会好得离谱。
回看窗口与持有期:两个最敏感的参数
回看窗口 N 决定你捕捉的是哪种级别的趋势。窗口太短,信号被日常噪声主导,换手极高;窗口太长,信号钝化,等你确认趋势时行情往往已走完大半。持有期 H 则决定反应速度和交易成本之间的平衡。
一个实用的检查方法是画参数平原:把 N 和 H 各取一组值,跑出全部组合的回测指标,看结果是否在参数邻域内平滑变化。
| 特征 | 健康的参数平原 | 危险信号 |
|---|---|---|
| 形状 | 大片区域表现相近 | 只有孤立的尖峰 |
| 邻域 | 相邻参数结果接近 | N 从 55 改到 60 结果剧变 |
| 逻辑 | 参数有经济含义 | 纯粹是搜出来的数字 |
如果只有某一组”神奇参数”表现突出,而它旁边的参数全都平庸,那大概率是过拟合,而不是发现了规律。
除了参数平原,还有两个低成本的稳健性检查值得养成习惯:一是把再平衡日整体平移几天(月初改月中),看结果是否大变——对再平衡日期敏感的策略,本质上是在拟合日历噪声;二是把回测期切成前后两半分别评估,两段表现差异悬殊时,要怀疑策略只是抓住了某一段特定行情。这些检查不能证明策略有效,但能廉价地否掉一批伪装成规律的运气。
换手成本:轮动策略的隐形税
轮动天然高换手。假设每次再平衡平均换掉一半持仓,双边成本合计千分之二,每月轮动一次,一年仅摩擦成本就会吃掉相当可观的一块收益。回测时务必把成本显式建进去,并做一个简单的敏感性测试:把单边成本从万五逐步提高到千二,看策略净值何时被”磨平”。如果策略只有在零成本假设下才成立,它在实盘中几乎必然失效。
降低换手的常用手法包括:拉长持有期、引入排名缓冲区(例如跌出前 5 名才卖出,而不是跌出前 2 名就卖)、限制单次调仓的最大权重变化。
空仓与防守资产:轮动的”刹车”
纯相对动量有一个致命弱点:市场普跌时,它仍会持有”跌得最少”的资产。解决办法是叠加绝对动量过滤——当排名靠前的资产自身动量也为负时,转入防守资产(货币 ETF、短债 ETF)或直接空仓。
设计防守腿时要想清楚三件事:触发条件(绝对收益为负,还是低于某个阈值)、防守资产本身的流动性、以及重新入场的条件是否与出场条件对称。很多回测里”防守腿”贡献了大部分回撤控制,这本身值得警惕:它可能只是恰好躲过了样本内的几次大跌,换一段历史未必重现。
另一个容易忽略的细节是频繁进出的”鞭打”损耗:市场在阈值附近来回震荡时,绝对动量过滤会导致反复的”清仓、再买回”,每一个来回都白付两次成本。缓解手段是给出入场设置不同阈值(例如动量跌破 -2% 才离场、回升到 +2% 才进场),用滞回区间换取更少的无效切换。
轮动策略的其他陷阱清单
除了参数过拟合,做轮动研究前还应过一遍这份清单:
- 候选池的幸存者偏差:用今天还存续、规模够大的 ETF 列表去回测十年前,等于提前知道了哪些产品能活下来、能长大。候选池应按 PIT 原则用当时可交易的名单。
- 上市初期数据:ETF 上市初期规模小、折溢价大,回测里的价格未必成交得了,建议剔除上市不满一定时长的品种。
- 拥挤度:动量轮动的逻辑广为人知,信号同质化意味着再平衡日大家挤同一扇门。回测无法完全刻画这一点,但可以通过检查标的成交额与自身资金规模的比例保持清醒。
- 风格归因缺失:行业轮动的超额收益,有时只是变相押注了某种市值或波动风格。跑一次简单归因,确认收益来源与你的设计意图一致。
本课小结
- 轮动是”比较相对强弱”而非”预测绝对方向”,统计上比择时更可行,但仍是时间序列问题,样本天然稀少。
- 通用框架就三步:排序、持有、再平衡;信号必须
shift(1)之后才能用于成交。 - 回看窗口与持有期用参数平原检验,追求平滑的高原而不是孤立的尖峰。
- 换手成本是轮动的隐形税,必须显式建模并做成本敏感性测试。
- 防守腿能控制回撤,但要警惕它只是”记住了”样本内的几次暴跌。
动手练习:选 5 只互相相关性较低的行业 ETF,用上面的框架实现一个”回看 60 日、持有前 2 名、每 20 日再平衡”的轮动回测。然后做两件事:一是画出 N∈{20,40,60,90,120}、H∈{5,10,20,40} 的参数平原热力图;二是加入单边千一的交易成本,对比净值曲线差异,写下你的结论。