多因子组合:打分、中性化与权重分配
本课目标:学会把多个单因子加工成一个组合信号——包括去极值与标准化、行业/市值中性化、因子合成方法的选择,以及从因子分走到组合权重。
前几课我们逐个检验了单因子。实盘中几乎没有人只用一个因子——单因子波动大、有明显的失效期,多因子组合的意义在于让互相不太相关的信号互补:估值因子失灵的年份,动量或质量可能正好接力,组合层面的体验远好于任何单因子。把散装因子组装成组合,有一条标准流水线:预处理、中性化、合成、落地成权重。本课按顺序过一遍,每一步都说明”为什么要做”和”怎么做”。本文不构成投资建议。
第一步:去极值与标准化
不同因子量纲完全不同(EP 在 0.05 上下,动量可能是 ±80%),直接相加没有意义,必须先统一到可比的尺度。
去极值(winsorize):截面上少数极端值会主导后续的 z-score,比如一只股票的市盈率因为利润接近零而飙到几千倍,标准化后它一家就能扭曲整个截面的分布。常用中位数绝对偏差法(MAD)设定上下边界并截断,它比”均值 ± 3 倍标准差”更稳健,因为均值和标准差本身就会被极端值污染:
import numpy as np
def winsorize_mad(s: pd.Series, k: float = 5.0) -> pd.Series: med = s.median() mad = (s - med).abs().median() upper, lower = med + k * 1.4826 * mad, med - k * 1.4826 * mad return s.clip(lower, upper)标准化(z-score):去极值后,截面上减均值、除标准差,让每个因子都变成均值 0、方差 1 的分布:
def zscore(s: pd.Series) -> pd.Series: return (s - s.mean()) / s.std()顺序不能反:先去极值再标准化。缺失值的处理也要定规则——常见做法是行业内中位数填充,或直接不给该股票此因子的打分。两种做法各有代价:中位数填充相当于假设”缺数据的股票是行业平均水平”,会稀释因子区分度;直接不打分则会让不同因子的覆盖股票池不一致,合成时需要额外对齐。无论选哪种,规则要全程统一并写进文档。
对分布严重偏斜的因子(如市值、成交额),还有一个常用变体是排名标准化:先转成截面排名百分位,再映射到正态分布分位数。它完全抹掉了原始分布形态,只保留排序信息,稳健性最好,代价是丢失了”因子值差多少”的强度信息。
第二步:行业中性与市值中性
动机:很多因子的原始得分里混着行业和市值的”顺风车”。比如低波动因子天然偏好银行、公用事业;很多因子在小盘股上得分极端。如果不处理,你的”多因子组合”实际上是一个行业和市值的押注组合——风险集中,而且你并不知道自己在押。
做法:把因子值对行业哑变量和对数市值做截面回归,取残差作为中性化后的因子:
import statsmodels.api as sm
def neutralize(factor, industry_dummies, log_mktcap): X = pd.concat([industry_dummies, log_mktcap], axis=1) X = sm.add_constant(X) model = sm.OLS(factor, X, missing="drop").fit() return model.resid # 残差 = 剔除行业与市值后的纯因子残差的含义是:同行业、同市值水平下,这只股票的因子得分还有多少超额信息。中性化后记得再做一次标准化,让残差回到均值 0、方差 1 的尺度,才能与其他因子合成。
中性化不是免费午餐——它会剔除因子里真实存在的行业选择能力,是否中性化取决于你想不想承担对应的风险敞口。一个实用的判断方法:分别检验中性化前后的因子。如果中性化后 RankIC 大幅下降,说明这个因子的预测力主要来自行业或市值押注,“选股能力”其实很薄;如果基本不变,说明它有独立于风格的增量信息,是更值得保留的因子。
第三步:因子合成——打分法 vs 回归法
多个标准化后的因子怎么合成一个总分?两条主流路线:
| 维度 | 打分法(加权求和) | 回归法(截面回归) |
|---|---|---|
| 做法 | 总分 = Σ 权重 × 因子 z-score | 每期用因子暴露回归收益,估出因子收益率,再用其预测 |
| 权重来源 | 等权、ICIR 加权、人工设定 | 由回归系数内生决定 |
| 优点 | 简单透明、稳健、好调试 | 理论完整,自动处理因子间相关性 |
| 缺点 | 忽略因子相关性,权重带主观性 | 对共线性和异常值敏感,估计噪声大 |
对进阶阶段的建议是从打分法起步:等权合成是极难被打败的基准。ICIR 加权(用各因子历史 ICIR 作为权重)是常见的第一个改进,但要警惕用了太短的窗口去追逐因子的近期表现——因子权重本身也会过拟合,窗口越短、调整越频繁,样本外掉链子的概率越大。
因子相关性与冗余
合成前必须检查因子间的截面相关性。两个相关系数很高的因子(比如低波动与低换手)同时等权放入,等于给同一个信号加了双倍权重,组合的分散化是虚假的。
实用检查清单:
- 计算因子两两的截面 RankIC 式相关(每期截面相关取时序均值);
- 相关系数明显偏高的因子对,考虑只保留检验表现更好的一个,或先合并成一个”家族因子”再参与总合成;
- 新因子入库前,对存量因子做正交化检验:把新因子对老因子回归,看残差是否还有 IC。残差没有预测力,说明新因子只是老因子的换皮。
从因子分到组合权重
总分只是排序,还要落地成”每只股票买多少”。由简到繁的三种方案:
- 分位数等权:取总分最高的前 10% 或前 N 只,等权持有,定期调仓。最简单,也是检验因子分质量的基准做法;
- 打分加权:权重正比于总分(或总分的秩),分数越高买越多,注意设置单票权重上限;
- 优化器方案:把因子分作为预期收益输入组合优化器,同时施加风险和交易约束——这是下一课的主题。
无论哪种方案,都要在回测里叠加换手率统计和交易成本假设。多因子组合的换手率由变化最快的那个因子主导,合成时给高换手因子降权是控制成本的常用手段。另一个降换手的技巧是设置缓冲区:股票掉出前 10% 但仍在前 15% 时暂不卖出,只有跌出缓冲带才调仓。排序边缘的小幅抖动是换手的主要来源,缓冲区能以很小的信号损失换来可观的成本节约。
本课小结
- 流水线顺序:去极值 → 标准化 → 中性化 → 合成 → 落地权重,每一步都有明确动机;
- 行业与市值中性化的本质是剥离你不想押注的风险敞口,剥不剥取决于你想承担什么;
- 等权打分是极强的合成基准,任何花哨的加权方法都应先证明能稳定胜过它;
- 高相关因子共同入选会造成虚假分散,新因子必须通过对老因子的正交化检验;
- 从因子分到权重,从分位数等权起步,成本与换手要纳入评价。
动手练习:选两个前几课检验过的因子(如 20 日反转 + EP),完成整条流水线:MAD 去极值、z-score、行业市值中性化、等权合成,然后做 5 组分层回测,对比合成因子与两个单因子的 RankIC 与单调性,观察合成是否带来了改进。