动量和反转听起来是对立的两件事:动量说"涨了还会涨",反转说"涨多了要跌"。Alpha 101 里有 23 个因子属于这一类,它们的精妙之处在于不是无脑选边站,而是用不同条件来判断当前该跟动量还是做反转。
第一篇讲过这类因子的大框架。这篇挑 5 个经典因子,拆解公式里的条件判断逻辑。
Alpha#4:最简短期反转
$$\text{Alpha#4} = -1 \times \text{ts_rank}(\text{rank}(\text{low}), 9)$$整个公式只用了两层嵌套,是 101 个因子里结构最简单的之一。
rank(low) 是截面排名:今天所有股票按最低价排名,归一化到 0~1。最低价高的股票排名靠前(rank 值大)。
ts_rank(..., 9) 是时序排名:这个截面排名值在过去 9 天里处于什么位置。如果今天的 rank(low) 是最近 9 天里最高的,ts_rank 接近 1.0。
取反后:ts_rank 越高,因子值越负(做空信号)。一只股票的最低价在截面排名里连续 9 天走高,说明它连续 9 天都在"相对强势"的位置上,Alpha#4 对这种股票做空,赌短期反转。
为什么用 low 而不是 close?low 反映的是日内的"最弱时刻"。如果连一只股票最弱的时刻都比大多数股票强,说明强势程度很彻底,反转的概率也更高。这比用 close 多了一层信息:close 可能因为尾盘拉升而偏高,但 low 骗不了人。
论文里 Alpha#4 的原始参数是 ts_rank(rank(low), 9.99922),那个 9.99922 就是 10 的优化产物,实操中直接取 9 或 10 没有区别。
Alpha#9 与 Alpha#10:条件反转的两种写法
Alpha#9 在第一篇已经给过公式骨架:
$$\text{Alpha#9} = \begin{cases} \text{ts_rank}(\text{delta}(\text{close},1),\ 5) & \text{if } 0 < \text{ts_min}(\text{delta}(\text{close},1),\ 5) \\ \text{ts_rank}(\text{delta}(\text{close},1),\ 5) & \text{if } \text{ts_max}(\text{delta}(\text{close},1),\ 5) < 0 \\ -1 \times \text{delta}(\text{close},1) & \text{otherwise} \end{cases}$$先判断过去 5 天的走势一致性。ts_min(delta(close,1), 5) > 0 意味着过去 5 天每天都在涨(最小的日变化都是正的)。ts_max(delta(close,1), 5) < 0 意味着过去 5 天每天都在跌。
两种一致趋势的情况下,因子用 ts_rank(delta(close,1), 5),即当前日变化在过去 5 天日变化中的排名。连涨场景下,如果今天的涨幅是 5 天里最大的(ts_rank 高),因子值高,含义是"动量还在加速"。连跌场景下,如果今天的跌幅是 5 天里最小的(ts_rank 高),因子值也高,含义是"下跌在减速"。
“otherwise"分支处理震荡行情:涨跌交替时,直接用 -1 * delta(close, 1) 做反转。今天涨就做空,今天跌就做多。
Alpha#10 的结构和 #9 几乎一样,但条件判断的阈值不同,用 ts_min/ts_max 去比较的表达式更复杂。核心思路一致:先判市场状态,再选策略。这是 Alpha 101 里"条件反转"子类的标准范式,#46、#49、#51 也是这个结构,只是条件的具体写法各有不同。
关键洞察:单一的动量或反转策略在所有市场状态下都不好用。Alpha 101 的做法是用简单的阈值把市场状态分成"趋势"和"震荡"两档,对趋势用动量逻辑,对震荡用反转逻辑。这比机器学习模型里复杂的 regime detection 简单得多,但在日频数据上往往够用了。
Alpha#20:跳空缺口回补
$$\text{Alpha#20} = -1 \times \text{rank}(\text{open} - \text{delay}(\text{high}, 1)) \times \text{rank}(\text{open} - \text{delay}(\text{close}, 1)) \times \text{rank}(\text{open} - \text{delay}(\text{low}, 1))$$三项分别衡量今天开盘价相对于昨天 K 线三个价位的偏离:
open - delay(high, 1):开盘价相对昨日最高价。正值 = 跳空高开(今天直接开在昨天最高价之上)open - delay(close, 1):开盘价相对昨日收盘价。正值 = 高开open - delay(low, 1):开盘价相对昨日最低价。正值几乎一定成立(除非大幅低开)
三项都做截面 rank,乘在一起取反。
什么情况下因子值最大(做多)?三项 rank 都低,即今天开盘相对昨天 K 线明显偏低,大幅低开。取反后变成正值。Alpha#20 赌的是跳空低开会回补。
反过来,大幅高开的股票(三项 rank 都高),因子做空。
跳空缺口回补(gap fill)是交易员常见的经验。大幅高开往往因为隔夜利好被过度定价,开盘后缺乏后续买盘支撑就会回落。大幅低开则因为恐慌性抛售过头,开盘后空头回补和抄底资金推动价格反弹。
三项相乘而不是简单加权的妙处在于:只有三个维度同时给出信号时,乘积才会大。如果只是相对 close 高开了一点,但没超过昨天的 high,那 open - delay(high, 1) 可能为负,rank 偏低,乘积被压下来。必须是"全面跳空”(超过昨天所有价位)才会触发强信号。
Alpha#30:价格动量签名 × 成交量
$$\text{Alpha#30} = \frac{1.0 - \text{rank}((\text{sign}(\text{close} - \text{delay}(\text{close}, 1)) + \text{sign}(\text{delay}(\text{close}, 1) - \text{delay}(\text{close}, 2)) + \text{sign}(\text{delay}(\text{close}, 2) - \text{delay}(\text{close}, 3))) \times \text{sum}(\text{volume}, 5))}{\text{sum}(\text{volume}, 20)}$$公式长,但可以拆成两部分。
分子部分(1.0 - rank(...))里面的核心是:
其中 \(\Delta_1\) = 今天收盘 - 昨天收盘,\(\Delta_2\) = 昨天 - 前天,\(\Delta_3\) = 前天 - 大前天。每一项取 sign(+1 或 -1),加起来的可能取值是 -3, -1, +1, +3。
- +3 = 连涨 3 天
- +1 = 3 天里涨 2 天跌 1 天
- -1 = 3 天里跌 2 天涨 1 天
- -3 = 连跌 3 天
这个值乘以 sum(volume, 5)(5 天总成交量),再做截面 rank。连涨 + 放量的股票 rank 最高,1.0 - rank(...) 就最低。
分母 sum(volume, 20) 是 20 天总成交量,用来做归一化。
整体效果:连续上涨且放量的股票,分子接近 0,因子值低(做空信号)。连续下跌且缩量的股票,分子接近 1,除以 20 天成交量后因子值相对高(做多信号)。
经济直觉和量价背离类因子有交集:放量上涨是过热信号,缩量下跌是超卖信号。Alpha#30 的独特之处在于用了"方向签名"这种离散化的处理方式,不在乎每天涨多少,只在乎方向。这让它对涨跌幅度的噪音更鲁棒。
Alpha#35:三时间尺度交互
$$\text{Alpha#35} = \text{ts_rank}(\text{volume}, 32) \times (1 - \text{ts_rank}(\text{close} + \text{high} - \text{low}, 16)) \times (1 - \text{ts_rank}(\text{returns}, 32))$$三项对应三个不同的时间窗口:
ts_rank(volume, 32):当前成交量在过去 32 天(约 1.5 个月)里的排名。值高 = 近期放量。
1 - ts_rank(close + high - low, 16):close + high - low 可以理解为"日内偏强程度"。close 本身是当天价格水平,加上 high - low(日内振幅),值越大说明收盘价高且日内波动大。ts_rank(..., 16) 衡量这个值在过去 16 天(约 3 周)里的位置。取 1 - ...,所以值高 = 当前"日内偏强程度"处于 16 天低位。
1 - ts_rank(returns, 32):当前收益率在过去 32 天里的位置。取 1 - ...,值高 = 当前收益率处于 32 天低位(近期表现差)。
三项乘起来:什么时候因子值最大?成交量放大 + 日内偏强程度处于低位 + 收益率处于低位。翻译过来就是:一只股票最近一个多月表现很差,价格在底部区域,但成交量在放大。
这是经典的"底部放量"信号。价格处于低位说明已经跌够了,成交量放大说明有新资金进场。三个时间窗口(32、16、32 天)分别衡量了中期成交量趋势、短期价格结构、中期收益走势,不在同一个时间尺度上重复计数。
23 个动量反转因子的设计逻辑
这 23 个因子可以分成三个子类:
条件反转族(#9, #10, #46, #49, #51):先用 if-else 判断市场状态(趋势还是震荡),再分别应用动量或反转逻辑。这组因子的核心贡献不是信号本身,而是"什么时候用什么策略"的状态判断机制。
跳空/缺口族(#20, #23, #24):利用开盘价和前一天收盘价/高低价的偏差做反转。这组因子的时间分辨率最高,本质上捕捉的是隔夜信息的过度反应。
多时间尺度交互族(#30, #35, #52, #53):同时用不同窗口长度的指标,捕捉短期和中期信号的共振或背离。设计上比单时间尺度因子更稳健,但参数空间更大。
和量价背离类的 32 个因子相比,动量反转类的设计更加多样。量价因子几乎都是"计算价格和成交量的相关性"这一个套路的变体,动量反转因子则融合了条件判断、时间尺度嵌套、方向离散化等不同技巧。这也解释了为什么在实际多因子模型中,动量反转类因子往往贡献更多的独立信息。
下一篇讲波动率与日内结构类因子。
系列导航
- Alpha 101 全解读:因子分类与算子速查
- 量价背离类因子详解(32 个因子)
- 本篇:动量与反转类因子详解(23 个因子)
- 波动率与日内结构类因子详解(23 个因子)
- 流动性与复合因子 + 因子组合实战(23 个因子)