halo 的技术博客

返回

多因子投资有个隐藏前提:你决定持有哪几个因子(价值、动量、质量……),永远等权持有它们。这个前提把”该配哪些因子”当成一次性的静态决策。但因子不是静止的——价值会沉寂三年、动量会接力领涨、低波会在泡沫里失效。如果”因子”和”股票”一样是一种资产,那它也应该有自己的择时信号

这就是因子动量(Factor Momentum):把因子当成可交易的资产,用因子自身过去一段时间的收益去配置它们——哪类因子过去走强,就超配以它;走弱就减配甚至剔除。它和”在因子内部做股票截面动量”是完全不同的两层:后者选股、前者配置因子,是架在因子选择之上的二阶择时

在 25 年(300 个月)合成的 5 个风格因子上,静态等权持有全部因子的 Sharpe 是 0.94;而用过去 12 个月收益做信号的因子动量组合,Sharpe 冲到 2.27、回撤 −17.3%(比静态 −21.2% 还小)。更关键的是,它和共同市场的相关只有 0.18——它赚的是”因子之间轮动”的钱,不是市场方向的钱。

五个风格因子的累计净值:轮动明显,有的领涨、有的沉寂

一、为什么因子会有动量:因子是”状态时变”的#

因子动量成立的前提只有一个:因子的收益是可预测的、且有持续性。这和我们做股票截面动量是一个道理,只是把对象从”股票”换成了”因子”。

我们构造 5 个风格因子的月度收益,每个因子的收益由三部分组成:

  • μ_i:因子的长期漂移(价值、动量各自有不同的正溢价);
  • s_{i,t}:一个 AR(1) 慢变状态(持续性 φ=0.85)——这是因子”时好时坏”的来源,也是动量能捕捉的对象;
  • β_i·M_t + 特异噪声:共同市场暴露与特异冲击。

φ=0.85 意味着因子的”好状态”会持续好几个月——过去 12 个月走强的因子,未来一两个月往往还行。这就是因子动量的燃料。注意它和**时间序列动量(TSMOM)**的同构性:TSMOM 是对资产自身收益做时序动量,因子动量则是对”因子收益”这一层做时序动量——所以是”二阶”,因为它是套在底层因子之上的再一层趋势判断。

二、把因子当资产:因子动量组合怎么建#

逻辑和”用过去收益排序选股票”完全对称,只是排序对象是因子自身。每月:

  1. 算每个因子过去 12 个月累计收益,作为信号;
  2. 信号为正的因子纳入多头、等权持有,信号为负的剔除;
  3. 持有 1 个月,下月重算。
LOOK, REB = 12, 1
fm_w = np.zeros((NF, T))
fm_ret = np.zeros(T)
for t in range(LOOK, T):
    sig12 = ret[:, t - LOOK:t].sum(axis=1)        # 过去 12 月累计 = 信号
    longs = sig12 > 0
    w = longs.astype(float) / longs.sum() if longs.sum() else np.ones(NF) / NF
    fm_w[:, t] = w
    fm_ret[t] = float(np.dot(w, ret[:, t]))
fm_ret = fm_ret[LOOK:]
ew_ret = ret.mean(axis=0)[LOOK:]                  # 对照: 静态等权全部因子
python

这里没有任何未来函数:信号只用 t 之前的数据,持仓在 t 月内不变。阈值用”>0”而非”排行前几”,避免人为挑断点——本质是”顺因子的势”,而不是押注某个具体风格。

三、结果:因子动量把 Sharpe 翻了一倍多#

把单因子、静态等权组合、因子动量组合摆在一起:

标的年化波动Sharpe最大回撤
价值 / 动量 / 规模 / 质量 / 低波(单因子)3.7~9.2%13~21%0.22~0.61−55~−87%
静态等权全部因子7.0%7.4%0.94−21.2%
因子动量组合22.0%9.7%2.27−17.3%
50% 动量 + 50% 静态14.3%8.0%1.79−15.5%

因子动量组合 Sharpe 2.27,几乎是无脑等权的 2.4 倍,且回撤更小。这说明”在哪个因子上多下注”这件事,本身就藏着大量未被静态配置利用的 alpha。

Sharpe 对比:因子动量组合高于任一单因子与静态等权

四、它赚的是什么钱:相关结构#

因子动量最妙的地方,是它和市场的低相关。在我们的样本里:

  • 因子动量 vs 静态等权因子组合:0.72(不是 1,说明它不是简单复制底层因子,而是加了”择时”这一层);
  • 因子动量 vs 共同市场:0.18(几乎中性——它赚的是因子之间的轮动,不是市场方向)。

信号本身也站得住脚:12 个月累计收益与下月因子收益的截面相关(IC)均值 0.327,且约 59.7% 的月份信号为正——也就是说,“因子过去强、未来还强一阵”是一个稳定存在的现象,不是噪声。

因子动量组合 vs 静态等权因子组合的净值与滚动相关

权重热力图更直观地展示了”轮动”:每个月被做多的因子在变,没有哪个因子被永久超配——因子动量做的是动态再平衡,而非押注单一风格。它是二阶的:第一阶决定”持有这些因子”,第二阶(本文)决定”这个月该给谁加注”。

因子动量权重热力图:每月只做多过去 12 月收益为正的因子

五、二阶择时的边界#

因子动量不是银弹。它是”因子择时”这一层新的自由度,好处是能抓住轮动、坏处是会再次过拟合,必须清醒看待边界:

  • 它是市场状态的影子:在”因子轮动清晰”的 regime 里赚钱,在”所有因子一起失效”的危机里会同时亏(价值沉、动量破、质量也破)。它不是市场中性,只是低相关。
  • 与截面动量不可混淆:因子动量(对因子收益做时序动量)和”在因子内做截面动量”是两件事。前者配置因子、后者选股,别混为一谈;混了容易把同一份溢价重复计数。
  • 因子数量太少会过机动:只用 5 个因子,任何一个月”信号为正的因子”可能只有 1~2 个,集中度高、路径依赖强。真实应用应在几十个因子上做,分散单一因子的 regime 风险。

一个稳妥的落地起点:先在大类因子(价值/动量/质量/低波/规模)层面跑通因子动量,确认 IC 稳定为正后,再逐步下沉到更细的子因子,而不是一上来就对着几十个相关性混乱的因子做月度再平衡。

六、真实陷阱(诚实版)#

1. 数据是合成的、且校准偏乐观:单因子 Sharpe 0.22~0.61、因子动量 2.27,都是为演示机制选的友好参数。真实因子动量(Ehsani-Linnainmaa-Reibstein 等文献)效应存在,但净 Sharpe 通常更温和,且高度依赖样本期。

2. 过拟合信号窗:本文用 12 个月回望,是”已知答案后选的”。实盘必须样本外确定回望窗,或用多个窗平均,否则会挑出看起来最漂亮、其实过拟合的那个。

3. 因子数量太少会过机动:只用 5 个因子,任何一个月”信号为正的因子”可能只有 1~2 个,集中度高、路径依赖强。真实应用应在几十个因子上做,分散单一因子的 regime 风险。

4. 它是市场状态的影子:因子动量在”因子轮动清晰”的 regime 里赚钱,在”所有因子一起失效”的危机里会同时亏(价值沉、动量破、质量也破)。它不是市场中性,只是低相关。

5. 交易成本与换手:每月调仓、且权重在 0/正之间跳变,换手不低。上面的数字没有扣交易费——实盘要把 bid-ask、冲击成本、短期资本利得税算进去,Sharpe 会打折。

6. 与截面动量的混淆:因子动量(对因子收益做时序动量)和”在因子内做截面动量”是两件事。前者配置因子、后者选股,别混为一谈;混了容易把同一份溢价重复计数。

结语#

“因子本身也有趋势”这句话,听着只是视角的转换,但落地后收益结构完全不同:静态持有因子,是把因子当常量;因子动量,是把因子当有时好有时坏、且好坏会持续的状态变量。本文用 5 个合成因子证明,仅仅是”顺因子的势”这一层二阶择时,就能把组合 Sharpe 从 0.94 拉到 2.27,且与市场几乎脱钩。真正的功课不在模型,而在样本外验证信号窗、控制换手、并在多因子维度上分散——否则你只是把”因子择时”这层新的自由度,又过拟合了一遍。

本文图表与全部数字均由 generate_factor_momentum_images.py 用 numpy 从零计算生成(AR(1) 因子状态 + 因子动量组合 + 相关/IC 统计),非占位图。把 ret 换成你真实的因子收益序列,整套代码可直接复用。

因子动量:当因子本身也有趋势,用因子收益做二阶择时
https://blog.halo26812.eu.org/blog/factor-momentum-signal
Author halo
Published at 2026年7月17日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨