跳转到内容

多因子入门

上一篇截面动量的整套动作——打分、排序、分组、看哪组未来涨得多——其实不依赖「过去收益」这个具体变量。把打分依据换成市盈率、换手率、ROE、分析师评级变化,流程一个字都不用改。任何一个能给股票排队打分的变量,都叫因子(factor)。这一篇把上一篇的框架推广成一般意义上的因子方法论,并引入衡量因子质量的标准尺子:IC。

先建立直觉。学校体检时老师让全班按身高排队:身高是一个可排序的特征,排完队,站在队首的和站在队尾的一眼可辨。因子就是股票的「身高」——一个每只股票都能算出一个数值、因此可以拿来给整个股票池排队的特征。因子投资的全部赌注是一句话:排队的顺序里携带了关于未来收益的信息。按身高排队能预测谁够得着书架顶层;按因子排队,我们希望队尾的股票未来平均跑赢队首(或者反过来——方向不重要,重要的是顺序里有信息)。怎么量化「顺序里有没有信息」?上一篇看了分组柱状图,那是一目了然的快照;这一篇的 IC 是把同样的问题压缩成一个数字,并且可以在时间轴上逐日滚动地算。

方法论:因子 → 排序 → 分层 → 看层间分化

Section titled “方法论:因子 → 排序 → 分层 → 看层间分化”
  • R1(标的池):全市场股票,池子必须用当时的成分(第 1 章的幸存者偏差)。本章演示用 30 只合成股票。
  • R2(因子计算):每日收盘后,为池中每只股票计算因子值 fi,tf_{i,t}。因子可以是任何可排序的数值:估值、动量、质量、情绪……唯一的纪律是只用当时可得的数据(常见坑一节会看到这有多容易违反)。
  • R3(排序分层):把 N 只股票按因子值从小到大排序,均分 5 层:因子值最低的 20% 是第 1 层,最高的是第 5 层。30 只股票每层恰好 6 只。
  • R4(跟踪收益):记录每只股票次日(或下一持有期)的收益 ri,t+1r_{i,t+1},按层求等权平均。分层的关键在时间错开:分层依据是 tt 日收盘后的因子值,收益是 t+1t+1 日的——因子在收益之前,无前视。
  • R5(质量度量与迭代):对每一天,算因子排名与次日收益排名的相关性,得到 IC 序列;同时把各层的日收益累乘成分层净值。IC 均值为正且稳定、分层净值单调分化,是因子有效的两条证据;两者都不理想,就换因子或改定义,回到第 2 章的假设检验流程重新来。
  • 成功标准:假设在碰数据前写死——「该因子的日度 IC 均值显著大于 0,且五分位层净值按因子值高低单调排列」。「显著」沿用第 2 章的判据。

本章演示数据是 120 个交易日 × 30 只合成股票(多因子入门演示:120 个交易日 × 30 只合成股票的截面。每日因子值是真实信号 s 的带噪代理(corr(f, s) ≈ 0.707),次日收益以 0.07 的载荷依赖 s(理论截面秩相关 ≈ 0.05)。ic 为每日因子排名与次日收益排名的 Spearman 秩相关;layers 为按因子值升序五分位分组(第 1 层因子最低、第 5 层最高,每组 6 只)的组内等权日收益累乘净值。分组只用当日收盘后已知信息,无前视)。生成剧本沿用了上一篇的思路:每只股票每天暗藏一个真实信号 si,ts_{i,t}(不写入数据,实盘不可观测),因子值是 ss 的带噪代理(相关约 0.7),次日收益以一个小的载荷依赖 ss,使得因子的真实截面相关约为 0.05。0.05 这个数不是随手选的:真实世界里日度 IC 能有 0.05 上下、且稳定为正,已经是可用的好因子——单日的 IC 噪声极大(标准差约 0.1792),靠单日什么也看不出来,必须看序列的平均形态。

第 tt 日的 IC 定义为因子值排名与次日收益排名的相关系数:

ICt=corr(rank(fi,t), rank(ri,t+1))=1−6∑i=1ndi2n(n2−1),di=rank(fi,t)−rank(ri,t+1)\text{IC}_t = \text{corr}\Big(\text{rank}(f_{i,t}),\ \text{rank}(r_{i,t+1})\Big) = 1 - \frac{6\sum_{i=1}^{n} d_i^2}{n\left(n^2 - 1\right)}, \qquad d_i = \text{rank}(f_{i,t}) - \text{rank}(r_{i,t+1})

等号右边是 Spearman 秩相关的闭式(要求没有并列名次)。nn 是股票数;ICt\text{IC}_t 取值在 −1-1 到 +1+1 之间。顺带一提它的姊妹指标 ICIR:

ICIR=IC‾σ(IC)\text{ICIR} = \frac{\overline{\text{IC}}}{\sigma(\text{IC})}

即 IC 序列的均值除以标准差(也常年化,乘上 T\sqrt{T},TT 是一年的调仓期数)——IC 告诉你因子「灵不灵」,ICIR 告诉你「灵得稳不稳」。

人话解释:为什么用排名而不是原始数值?因为排名把「因子值差多少」翻译成「谁排谁前面」,量纲和分布形状全部洗掉——市盈率 5 倍和 50 倍,只差排名,不管差几倍;收益里一天 ±10% 的涨跌停和 ±0.1% 的织布机,也只差排名。这让 IC 对极端值不敏感,是截面因子检验的行业默认。公式本身更好读:did_i 是第 ii 只股票「因子名次」和「收益名次」的落差。如果因子的排队顺序和次日收益的排队顺序完全一致,所有落差都是零,公式第二项为零,IC 等于 1——满分。排队越不一致,落差平方越大,IC 越低;完全反过来排,IC 接近 −1(那也是信息,反向用就行)。真正没信息的因子,IC 在 0 附近随机晃。

手算一遍:5 只股票的玩具截面。某日因子值与次日收益如下表(因子值越小名次越靠前,排名从 1 开始):

股票因子值因子排名次日收益收益排名落差 did_idi2d_i^2
A2.12+0.2%3−11
B3.54−1.0%139
C1.81−0.3%2−11
D4.05+1.5%500
E2.93+0.8%4−11

先看排名这步怎么来的:因子值从小到大是 C(1.8)、A(2.1)、E(2.9)、B(3.5)、D(4.0),所以因子排名依次是 C=1、A=2、E=3、B=4、D=5;次日收益从低到高是 B(−1.0%)、C(−0.3%)、A(+0.2%)、E(+0.8%)、D(+1.5%),收益排名 B=1、C=2、A=3、E=4、D=5。落差 did_i = 因子排名 − 收益排名,逐只相减得上表倒数第二列,平方后求和:1 + 9 + 1 + 0 + 1 = 12。代入公式,nn = 5:IC = 1 − (6 × 12) ÷ (5 × (25 − 1)) = 1 − 72 ÷ 120 = 1 − 0.6 = 0.40。读法:这个因子的排队顺序与次日收益的顺序明显同向(D 因子最高、收益也最高;B 因子第四、收益却垫底,是最刺眼的一个错位,贡献了 12 里的 9)。注意 5 只股票的 IC 只能取少数几个档位,0.40 这么整齐的数字是玩具例子特有的;真实截面有几百上千只股票,IC 是连续值,且单日大多在 −0.3 到 +0.3 之间晃——看点不在单日,而在几百天平均下来是不是稳稳站在 0 上方。

伪代码:计算一个因子的 IC 序列

Section titled “伪代码:计算一个因子的 IC 序列”
输入:股票池 pool(N 只)、因子函数 factor(i, t)(只用 t 日收盘前可得的数据)、
日收益 ret[i][t](t−1 收盘到 t 收盘)、层数 Q = 5
icSeries ← 空列表;layerNav ← Q 个元素全为 1
对 t 从 1 到 n−1:
# ① t 日收盘后算因子并排名(排名从 1 开始,升序:值最小名次 1)
对 pool 中每只股票 i:f[i] ← factor(i, t)
rankF ← rank(f)
# ② 取次日收益并排名(t+1 日的收益,相对因子晚一天:无前视的关键)
对每只股票 i:r[i] ← ret[i][t+1]
rankR ← rank(r)
# ③ Spearman 闭式(无并列名次时与秩相关完全等价)
d2 ← Σᵢ (rankF[i] − rankR[i])²
icSeries[t] ← 1 − 6·d2 / (N·(N² − 1))
# ④ 按因子值升序分 Q 层,层内等权,日收益累乘净值
idx ← 按 f 从小到大排序的股票下标
对 q 从 1 到 Q:
成员 ← idx 的第 q 段(每段 N/Q 只)
layerNav[q] ← layerNav[q] × (1 + 成员次日收益的等权平均)
输出:icSeries(再算均值、标准差、ICIR、滚动均值)、layerNav(Q 条分层净值)

三处容易写错的地方:① 和 ② 的时间错开是整条管线的灵魂——因子用 tt 日数据,收益用 t+1t+1 日,写成同一天就是隐性的未来函数(IC 会好看到失真,常见坑第 2 条);② 的排名和 ① 的排名是两套独立的排名,分别排,不能混用;③ 的闭式只在无并列名次时严格成立,实盘里因子值经常出现大量并列(比如停牌股因子值全为 0),有并列时要退回通用的秩相关定义(先排名、再对排名算 Pearson 相关),并对并列名次取平均秩。

把演示数据 120 天的 IC 逐日画成柱子,叠加 20 日滚动均值:

读图三要点:

  1. 别看单根柱子,看滚动均值。单日 IC 的噪声极大(本例标准差 0.1792),59% 的日子为正、其余为负,单拎任何一天都说明不了问题。蓝线(20 日滚动均值)才是因子的「真实水平」:全期 IC 均值 0.0512,大部分时间滚动均值站在 0 轴上方——均值为正且稳定,这就是好因子的长相。本例滚动均值也短暂跌破过 0,这很正常:真实因子总有失灵的小段,判据是长期均值和 ICIR(本例 0.286),不是要求天天为正。
  2. IC 的正负号只是方向。如果某因子 IC 稳定为负,不是因子没用,是方向拿反了——把因子值取负号,IC 就变正。真正没用的因子是 IC 在 0 附近无规律晃、滚动均值压线的那种。
  3. 这是合成数据。剧本里真实信号 ss 是存在的,IC 为正且稳定是安排好的——它演示的是「好因子的 IC 序列长什么样」,供你日后拿真实因子的图来对照。

再看同一批数据的分层净值——每天按因子值分五层,层内等权、逐日累乘:

读图三要点:

  1. 看终点是否单调。120 天后,第 1 层(因子最低)净值 0.8089,第 5 层(因子最高)净值 1.15,中间三层依次排开(0.8685、1.0604、1.0937)——五层终点严格单调排列,层间单调分化是因子有效最直观的证据:因子的排队顺序确实翻译成了收益的排队顺序。
  2. 看分化是否持续拉开,而不是某一天跳出来的。本例五层从共同的起点 1.0 出发逐渐散开,第 5 层与第 1 层的差距随时间越拉越大——这是「信息每天都在兑现」的形态。如果分化主要由少数几天贡献,因子可能只是在赌某次事件。
  3. 中途允许交叉。120 天里五层净值只有约 19 天严格单调排列,中间层经常互相穿越——噪声主导短期,信息主导长期。判断形态看终点和整体趋势,不苛求每一天都整齐。

两图对照着看是本章最想留下的习惯:IC 序列回答「顺序里有没有信息、稳不稳」,分层净值回答「这个信息换成钱是什么形态」。一个是诊断指标,一个是结果展示;研报里只给分层净值不给 IC 序列的,要警惕它是不是挑了一段好看的历史。

多因子的「多」:从单因子到复合打分

Section titled “多因子的「多」:从单因子到复合打分”

前面的流程只针对单一因子。但任何单一因子都是「偏科生」:价值因子在熊市抗跌、在牛市滞涨;动量因子在牛市领跑、在震荡市频繁被套。

多因子模型的精髓,在于用多个低相关的因子互相取长补短。把它们合成一个最终打分,标准流程分三步:

  1. 去量纲与标准化(Z-score):市盈率是倍数(5~100),换手率是百分比(1%~20%),两者无法直接相加。必须先用第 2 章的方法把每个因子转成标准分:z=(f−μ)/σz = (f - \mu) / \sigma,变换后所有因子均值为 0、标准差为 1,站上了同一把起跑线;
  2. 加权求和:设定各因子的权重 wjw_j(满足 ∑wj=1\sum w_j = 1),算出综合得分:Scorei=∑wj⋅zi,j\text{Score}_i = \sum w_j \cdot z_{i,j}。初学者最稳健的选择是等权打分(每个因子平分秋色);进阶做法是按历史 ICIR 倒数或多元回归赋权;
  3. 综合排序建仓:拿着每只股票的最终得分 Scorei\text{Score}_i 从高到低排序,等权买入排名前 20% 的股票。

手算两只股票的复合打分: 设定复合模型由两个因子组成:价值因子(权重 50%)与动量因子(权重 50%)。

  • 股票 A(大盘价值股):价值因子 Z-score 为 +1.4+1.4(估值极便宜),动量因子 Z-score 为 −0.6-0.6(近期弱势阴跌)。 ScoreA=0.5×1.4+0.5×(−0.6)=0.7−0.3=+0.4\text{Score}_A = 0.5 \times 1.4 + 0.5 \times (-0.6) = 0.7 - 0.3 = \mathbf{+0.4}
  • 股票 B(成长动量股):价值因子 Z-score 为 −0.2-0.2(估值略高),动量因子 Z-score 为 +1.2+1.2(近期强劲突破)。 ScoreB=0.5×(−0.2)+0.5×1.2=−0.1+0.6=+0.5\text{Score}_B = 0.5 \times (-0.2) + 0.5 \times 1.2 = -0.1 + 0.6 = \mathbf{+0.5}

结果:股票 B 的复合得分(0.5)高于股票 A(0.4),在打分榜上排名更靠前。多因子模型成功兼顾了两种逻辑。

A 股特色陷阱:市值与行业中性化

Section titled “A 股特色陷阱:市值与行业中性化”

在 A 股做多因子选股,如果不做中性化,你的策略大概率只是在裸暴露某种单一风格,甚至沦为「微盘股的提线木偶」。

银行股市盈率通常只有 5 倍,计算机和半导体股市盈率往往高达 50 倍。如果你直接拿估值因子在全市场排序:

  • 排名前 10% 的股票几乎全是银行、煤炭、钢铁;
  • 排名垫底的几乎全是科技、创新药。

你自以为在做「量化多因子精选个股」,实际上是在做**「重仓金融周期、极度做空高科技」的单向行业对赌**。一旦某一年科技暴涨、银行阴跌,策略会被打得落花流水。

对策(行业中性化):不要跨行业混排。先在每个行业内部独立排名(在银行里挑估值前 10% 的银行,在半导体里也挑估值前 10% 的半导体),再按基准指数中的行业权重组合合并。

这是 A 股量化史上最血淋淋的教训。

小微盘股票因为市值小、弹性大、壳价值、散户交易拥挤,在历史上绝大多数反转因子、短期波动因子、流动性因子上的表现都显著优于大盘股。如果你拿这些因子不做任何约束地全市场排序:

  • 模型挑出来的全是一批总市值 10 亿~20 亿的微盘股;
  • 2021~2023 年历史回测年化收益可能高达 40%~60%,夏普比率超过 3.0,美轮美奂。

但这个收益不是 Alpha(选股能力),而是 Bare Beta(承担了极端流动性踩踏风险的补偿)。2024 年初微盘股流动性危机中,这类策略在两周内暴跌 40%~50%,流动性瞬间枯竭无法离场。

对策(市值中性化):用横截面线性回归,剔除市值对因子值的影响:

fi=α+β⋅ln⁡(MarketCapi)+εif_{i} = \alpha + \beta \cdot \ln(\text{MarketCap}_i) + \varepsilon_i

回归后剩下的残差 εi\varepsilon_i,才是剔除了公司大小影响之后的纯净因子得分。只有经过市值中性化的多因子,选出来的才是无论在大市值还是小市值股票里都普遍成立的真实选股能力。

  1. 因子拥挤与衰减:IC 不是固定资产。一个因子被越多人用,它预测的价差就被越多人提前买走,IC 随时间下滑——这叫因子衰减;跌到一定程度,同样的持仓结构挤在同样一批股票里,一旦有人抢跑就是集体踩踏——这叫因子拥挤。读 IC 序列时务必看时间维度上的趋势:全期均值 0.05 可能是「前五年 0.10、近两年 0.01」平均出来的。滚动均值(本章第一张图的蓝线)缓慢而持续地下行,就是衰减的现场。对策不是找到「永不衰减的因子」(不存在),而是建立监控:IC 滚动均值跌破历史正常区间时降低该因子的权重,并持续储备候选因子(第 6 章的过拟合讨论会讲怎么储备才不踩新坑)。
  2. 未来函数在因子计算里的藏身术:用了「当季还没发布」的财报。第 1 章讲过的未来函数,在因子计算里比在择时信号里更隐蔽。最典型的版本:算「一季度 ROE」因子,拿一季报的数据去给 3 月 31 日的股票排序——但一季报的实际披露期是 4 月中下旬,3 月 31 日那天市场根本不知道这些数字,回测里你却已经用上了。IC 会因此虚高得漂亮,实盘全面落空。纪律只有一条:每个数据都要问「它哪天对公众可见」,因子只能用「可见日 ≤ 计算日」的数据。财报类因子用披露日期对齐(或保守地滞后一个季度),宏观数据用发布日期而不是数据期日期,分析师预期用当时快照而不是事后修订版。第 4 章的回测框架会把这个约束做成硬规则,但因子层面的对齐只能靠自己——框架不知道你的因子值是从哪个未来挖来的。
  3. 把 IC 高低当成因子好坏的全部。IC 度量的是排序质量,不度量幅度、不扣成本:IC 0.05 但多空价差被换手成本吃光的因子,不如 IC 0.03 但换手低的因子;IC 高但集中在小市值股票上的因子,大资金根本装不下。IC 是筛选因子的第一道滤网,不是终审判决——通过后还要走第 4 章的计费回测、第 5 章的指标体检。
  4. 因子值不处理就直接排序,裸暴露行业与市值。前文已详述:原始因子值如果不做行业和市值中性化,多因子模型会直接退化为全仓单赌某几个板块或全买微盘股。实盘前必须建立行业内分层或残差回归意识。

因子方法论到此成型:任何可排序的特征都能走「排序 → 分层 → IC / 分层净值」这条流水线,复合打分融合多种优势,市值与行业中性化防范风格踩踏。到这里,我们已经涵盖了单标的择时(趋势、均值回复)与多标的选股(截面动量、多因子);下一篇看事件研究——把「某件事发生后,市场平均怎么走」变成可以统计检验的问题。