做量化研究的人大概都有过这么一个阶段:刚开始兴致勃勃地建了一个 Excel 表,把能想到的因子一股脑往里塞,PB、ROE、20日动量、换手率、波动率、股东户数变化……半年之后这张表膨胀到两百多行,回头一看,同一个"动量"有三个版本,计算窗口不一样、复权方式不一样、股票池也不一样,谁都说不清哪一版是线上在用的。股票交易里的因子汇总,难点从来不是"想出因子",而是把散落在几十个脚本、几份研报、若干次临时改动里的东西收敛成一份口径统一、可追溯、可复现的台账。我前后整理过三版因子库,前两版都死在"没人维护"上,第三版才算跑通。这篇就把因子汇总这件事拆开讲透:因子怎么分类、口径怎么定、有效性怎么验、台账怎么建、坑在哪里,适合刚接触多因子框架的朋友,也适合已经在跑策略但因子管理一团乱麻的同行对照自查。
1. 先想清楚"因子汇总"到底在汇总什么
1.1 因子不是指标,是被检验过的假设
很多人入门时把因子等同于财务指标或者行情指标,这是个很要命的认知偏差。指标是描述性的,比如"市盈率 15 倍";因子是预测性的,它背后必须挂着一个可证伪的假设——"估值低的股票,未来一段时间相对同类股票的收益更高"。没有假设的指标堆在一起,不叫因子库,叫数据字典。
我在第一版因子表里犯的错就是把所有能算的字段都列进去了,结果做单因子测试时一片混乱:算出来的 IC 忽正忽负,排查半天发现是某个字段在部分股票上是空的,缺失值被当成 0 参与了排序。这件事让我确立了一条规矩:**每个因子入库前必须写清楚三件事——它想捕捉什么市场行为、它的计算依赖哪些原始字段、它在什么市场环境下可能失效。**这三条写不出来,就不许进库。
举个具体例子。同样是"低估值",PB 低和 EV/EBITDA 低背后的假设其实不一样。PB 低更多对应资产端的安全边际,在重资产行业里解释力更强;EV/EBITDA 把负债结构考虑进去了,在杠杆差异大的行业之间横向比较更公平。如果不把这种差异写进台账,后面做因子相关性分析时你就会困惑:为什么这两个因子相关性只有 0.4,明明都叫"价值"。
1.2 一张因子台账至少要有的字段
我把因子库的元数据设计成"身份信息 + 计算口径 + 检验结果 + 生命周期"四段式。身份信息解决"这是谁",计算口径解决"怎么算的",检验结果解决"有没有用",生命周期解决"还能不能用"。四段缺一段,这个因子就是半成品。
| 字段类别 | 具体字段 | 为什么必须要有 |
|---|---|---|
| 身份信息 | 因子ID、中文名、英文名、所属大类、子类 | 唯一标识,防止同名不同算法 |
| 计算口径 | 原始字段、计算公式、窗口长度、频率、复权方式、股票池、行业分类标准 | 复现的唯一依据 |
| 检验结果 | 全样本IC均值、ICIR、t值、分层单调性、多空年化、换手率、最大回撤 | 判断是否值得保留 |
| 生命周期 | 入库日期、最近检验日期、状态(观察/在用/停用)、停用原因 | 防止僵尸因子长期占用资源 |
这里的"股票池"和"行业分类标准"最容易被忽视,但恰恰是最容易出问题的。同一套财务数据,用全市场口径算出来的 ROE 分位数,和剔除金融地产后算出来的,差异可能非常大。行业分类更麻烦,有的分类标准把某类公司归到制造业,换个标准就归到信息技术,因子中性化的结果就完全变了。我的做法是在因子ID里直接把股票池和分类标准编进去,比如VAL_PB_EP_AllA_SW2021这种命名,看到 ID 就知道口径,比翻文档快得多。
1.3 先分类再汇总,别急着写代码
新手最容易犯的第二个错,是拿到需求就开始写计算脚本。因子汇总本质上是个信息架构问题,架构没搭好,代码写得再漂亮也是返工。我现在的顺序是:先画因子地图,再定口径,再写代码,最后补检验。
因子地图的作用是让你知道"我有什么、我缺什么、我重复了什么"。常见的做法是按数据来源分四大块:量价类、基本面类、预期类、另类与事件类。量价类数据成本最低、更新最快,是绝大多数策略的主力;基本面类季度更新,滞后性强但稳定性好;预期类依赖分析师覆盖,中小市值股票上缺失严重;另类和事件类信噪比通常较低,但与其他因子的相关性也低,能提供增量信息。
这四块的比例关系很重要。如果你的因子库里量价类占了八成,那基本可以预判:策略换手会很高,容量有限,而且在市场风格剧烈切换时会集体失效。这不是说量价因子不好,而是说因子汇总的第一层价值是让你看清自己信息源的偏斜程度,这个洞察比单个因子的 IC 高低重要得多。
2. 主流因子族谱与各自的构建口径
2.1 量价类:最容易上手,也最容易过拟合
量价因子的诱惑在于数据现成、计算简单、回测好看,但它也是最容易骗人的一类。我见过太多"动量因子年化 30%"的回测,一上实盘就哑火,原因往往是没做行业市值中性化、没考虑停牌股、没扣交易成本,或者干脆就是在全样本上反复调参调出来的。
量价因子往下细分,至少有动量、反转、波动、流动性、量能、微观结构六支。每一支的口径差异都很大:
- 动量:常见的是过去 20/60/120 日累计收益,但要不要剔除最近一个月争议很大。剔除的理由是短期存在反转效应,会污染动量信号;不剔除的理由是剔除后信号滞后。我实测下来,在 A 股这种以中短线交易为主的市场里,剔除最近 20 个交易日效果更稳,代价是信号衰减快一些。
- 反转:5 日或 10 日收益取负,本质是捕捉短期超跌反弹。这个因子在流动性差的小票上效果特别强,但也特别容易踩到"跌不停"的坑,所以必须叠加流动性过滤。
- 波动:过去 60 日收益率标准差,或者日内高低价振幅的均值。低波动因子长期有效,但在单边急涨行情里会显著跑输,需要有心理准备。
- 流动性:换手率的均值或分位数。注意换手率有很强的非线性,极高换手往往对应投机情绪,极低换手对应流动性折价,两头都不好,中间段才有 alpha,所以我一般用换手率的分位数再取绝对值距离。
- 量能:成交量的变化率,或者量价相关性。这类因子稳定性一般,但在识别资金异动上有独特价值。
- 微观结构:大单净买入、买卖盘口不平衡之类,需要逐笔数据,成本高,中低频策略用不上。
提示:量价因子的窗口长度不要设得太细。我见过有人把窗口从 5 到 250 每 5 天扫一遍挑最优,这就是标准的过拟合。合理做法是先根据经济逻辑定一个宽区间,比如"中期动量用 60 到 120 天",然后在这个区间内取几个代表性窗口做稳健性检验,结果差别不大才说明信号是真的。
2.2 基本面类:价值、质量、成长三条腿
基本面因子最大的优势是逻辑扎实、换手低、容量大,最大的劣势是更新慢、有财报滞后、且容易被"财务粉饰"污染。构建时有两个关键决策:用哪个时点的数据,以及怎么处理行业差异。
时点问题是新手最容易翻车的地方。财报有披露截止日,你用报告期当日期去做回测,等于用了未来信息,回测收益会虚高得离谱。正确做法是用实际披露日或者披露截止日加缓冲。我自己的经验是,定期报告统一用"报告期后 60 个自然日"作为可用日期,虽然保守一点,但能有效避免数据穿越。部分公司的实际披露日期可以从公告数据里取,能进一步优化。
行业差异问题更微妙。银行和制造业的 ROE 水平完全不在一个量级,直接在全市场排序纯粹是在比谁的行业景气度高。所以基本面因子几乎都必须做行业中性化。这里有个实操细节:行业中性化用的是"行业内标准化"还是"对行业哑变量回归",两者在行业内股票数很少时结果差异明显。我的偏好是回归法,因为它在小样本行业里更稳定,但前提是行业内股票数不能少于 8 到 10 只,太少的行业干脆合并或者直接置为缺失。
三条腿的典型代表:
| 大类 | 代表因子 | 计算要点 | 常见陷阱 |
|---|---|---|---|
| 价值 | EP、BP、SP、股息率 | 分母用最新总市值还是流通市值要统一 | 负值处理(亏损股的 EP 是负数,直接排序会把它们排到最后,可能反而合理,但需要明确) |
| 质量 | ROE、毛利率、资产周转率、应计利润 | 用TTM还是单季度要统一 | TTM 计算时如果中间有报告期缺失,容易算错 |
| 成长 | 营收增速、净利增速、ROE变化 | 同比还是环比、单季还是累计 | 低基数导致的增速畸高,需要做截尾或使用两年复合增速 |
质量因子里的应计利润值得单独说一句。它等于(净利润 - 经营现金流)/ 总资产,逻辑是"利润里没收到现金的部分质量差"。这个因子在很多市场都被验证过,但它在财务造假高发的环境里会有反向风险,因为造假公司的应计项往往异常。所以我不建议单独用它做选股信号,而是作为质量因子的一个组成成分,权重不宜过高。
2.3 预期类与另类因子:成本高,但增量信息明显
预期类因子主要指分析师的一致预期,比如一致预期 EPS 上调幅度、目标价上调比例、覆盖分析师数量变化。这类因子的价值在于它反映的是"边际变化"而不是"存量水平",与基本面因子相关性低,能提供明显的增量信息。
但它的坑也很实在。第一是覆盖偏差,大市值公司分析师覆盖多,小市值公司可能一个覆盖都没有,直接做全市场排序等于在选大票。第二是更新滞后,很多数据源的一致预期更新频率是月度甚至季度,捕捉不到快速变化。第三是幸存者偏差,部分数据源只保留当前仍在覆盖的分析师,历史上撤销覆盖的记录会丢失。我的处理方式是:只在有覆盖的样本内做排序,再把因子值按行业映射到无覆盖股票上,或者干脆把这个因子限制在大中市值池里使用。
另类因子和事件因子包括供应链关系、招聘数据、专利数据、股东增减持、股权激励、业绩预告等。这类因子的共同特点是单因子有效性不稳定、事件窗口短、但与其他因子相关性极低。它们在因子汇总表里的定位应该是"卫星因子",权重控制在 10% 到 20% 以内,不要指望它们扛大梁。
2.4 一个常被忽略的类别:风险因子与风格因子
严格来说,风险因子不算 alpha 因子,但在因子汇总里绝对不能缺席。市值、行业、Beta、估值风格、波动风格这些,既是你要中性化的对象,也是解释组合收益归因的基础。很多人做因子汇总只关心"哪个因子能赚钱",不关心"我的收益到底来自哪里",结果是策略回撤了也不知道是因子失效还是风格暴露。
我的做法是在因子库里单独划一个"风险因子"分区,和 alpha 因子分开管理。风险因子不做有效性检验,只做暴露度监控。每周出一张组合的风格暴露表,看看市值暴露、行业偏离、Beta 偏离有没有超出预设阈值。这张表救过我很多次——有一次组合连续两周跑输基准,看归因才发现是小市值暴露过大,而那段时间正好是小盘股调整,跟因子有效性一点关系都没有。
3. 单因子的标准化处理流水线
3.1 去极值:三种方法各自的脾气
原始因子值直接拿去做排序,会被极端值严重干扰。一个市值异常大的公司,它的换手率可能是同行的几十倍,排名直接冲到第一,把整个分布拉偏。所以去极值是标准流程的第一步。
常用的三种方法,我用下来各有适用场景:
MAD 法(中位数绝对偏差):计算因子值的中位数,再算每个值到中位数的绝对偏差的中位数,把超过中位数加减 N 倍偏差的值截断。N 一般取 3 到 5。这个方法对异常值不敏感,因为它用中位数而不是均值做基准,是我默认的首选。
分位数截断法:直接把小于 1% 分位和大于 99% 分位的值替换成边界值。简单粗暴,但问题是它一定会截断 2% 的样本,哪怕这批数据本来就很干净。在因子分布本身很均匀的情况下会造成信息损失。
3σ 法:均值加减 3 倍标准差。这个方法在正态分布下最经典,但金融数据普遍厚尾,均值和标准差本身就被极端值污染了,所以实际效果常常不如 MAD。
import numpy as np import pandas as pd def winsorize_mad(series, n=5): """MAD 法去极值,n 为截断倍数""" median = series.median() mad = (series - median).abs().median() if mad == 0 or pd.isna(mad): return series upper = median + n * 1.4826 * mad lower = median - n * 1.4826 * mad return series.clip(lower, upper) def winsorize_quantile(series, lower=0.01, upper=0.99): lo = series.quantile(lower) hi = series.quantile(upper) return series.clip(lo, hi)代码里那个 1.4826 是个换算系数,作用是让 MAD 在正态分布下能对应到标准差,这样 N 取 3 就大致等价于 3σ。这个细节很多教程不讲,但如果你要跨因子统一截断强度,这个小系数就得用上。
注意:去极值必须在横截面上做,也就是每个交易日在当期股票池内单独计算,而不是把整个时间序列堆在一起算。把三年数据堆起来去极值,等于让 2021 年的极端值影响了 2019 年的排序,这是隐性未来信息。
3.2 标准化与中性化:顺序不能反
去极值之后要标准化,目的是让不同量纲的因子可以比较、可以合成。最常用的是 Z-Score 标准化,减均值除标准差,处理后近似标准正态。
但标准化之后的中性化才是重头戏。中性化的目的是剥离因子中混入的行业和市值信息,让因子只保留"纯粹的选股信号"。这一步做不做,结果差异极大。举个直观的例子:某段时期小盘股整体表现好,"换手率"因子会显得特别有效,因为小盘股换手率本来就高,因子实际上在偷偷做多小市值。不做中性化,你以为自己发现了换手率 alpha,其实只是在做市值暴露。
中性化的实现方式是横截面回归:
$$Factor_i = \alpha + \sum_k \beta_k \cdot Industry_{k,i} + \gamma \cdot \ln(MktCap_i) + \varepsilon_i$$
取残差 $\varepsilon_i$ 作为中性化后的因子值。行业用哑变量,市值用对数。这里有几个实操要点:
- 回归要在每个交易日单独做,不要跨期。
- 行业哑变量要留一个基准组,或者干脆不设截距项,否则会有完全共线性问题。用 statsmodels 的话设置
hasconst=False或者手动去掉一列。 - 是否也把市值中性化要看因子性质。价值因子做市值中性化是标准操作;但如果你要做"小市值溢价"策略,那就不能中性化市值,否则信号被你自己抹掉了。
- 回归残差要再标准化一次,因为残差的量纲和原因子不同了。
我踩过的一个坑是:某次更新因子库时,中性化代码里行业哑变量的顺序变了(因为行业分类标准升级),导致残差整体偏移了一个常数。单因子看 IC 变化不大,但多因子合成时权重被带偏了,排查了两天才找到原因。从那以后我在中性化之后强制加一道 Z-Score,把偏移抵消掉。
3.3 因子有效性的三张体检表
因子做完标准化,不能直接丢进模型,得先体检。我固定看三张表,缺一张都不敢用。
**第一张:IC 时序表。**每个交易日算一次因子值与下期收益的横截面相关系数(Pearson 或 Spearman),得到一条 IC 时间序列。看四个指标:IC 均值(方向对不对)、IC 标准差(稳不稳)、ICIR = 均值/标准差(性价比)、IC 大于 0 的比例(胜率)。经验上,IC 均值绝对值 0.03 以上、ICIR 0.3 以上,就算有基本可用性;ICIR 到 0.5 以上算不错。
第二张:分层回测表。按因子值把股票分成 5 组或 10 组,看每组的年化收益、超额收益、最大回撤。核心看单调性——如果第 1 组到第 5 组的收益是阶梯式上升的,说明因子在整条分布上都有效;如果只有头尾两组有效、中间打乱,说明因子可能只在极端区域有信号,用的时候要做非线性处理。还要看多空组合的表现,纯多策略看多头组超额,对冲策略看多空净值。
**第三张:换手与容量表。**算因子值的分位数变动带来的持仓周转率。有些因子 IC 很漂亮,但每期排名大洗牌,换手率 300%,扣掉交易成本后所剩无几。我一般要求单因子年化双边换手控制在 800% 以内,超过这个数就得考虑加平滑(比如用因子值的移动平均,或者设置调仓缓冲带)。
| 体检指标 | 及格线参考 | 不及格时的处理 |
|---|---|---|
| IC 均值绝对值 | ≥ 0.025 | 检查方向、检查是否有数据问题 |
| ICIR | ≥ 0.3 | 加长测试窗口,看是否特定时期有效 |
| IC 胜率 | ≥ 55% | 检查因子分布是否稳定 |
| 分层单调性 | 5 组中有 4 组单调 | 考虑分位数变换或截尾重做 |
| 多空年化 | 有正收益且回撤可控 | 检查是否只在单边行情有效 |
| 年化双边换手 | ≤ 800% | 加平滑、加缓冲带、降低调仓频率 |
这三张表我建议每季度重跑一次,因为因子有效性会漂移。有的因子十年前很猛,现在已经被套利掉了;有的因子在特定市场环境下才苏醒。台账里那个"最近检验日期"字段就是干这个用的。
4. 因子汇总台账的落地做法
4.1 从 Excel 到代码化台账
我第一版台账是 Excel,撑了一年就崩了。原因有二:一是多人协作时版本混乱,谁改了哪个单元格根本说不清;二是 Excel 没法自动跑检验,所有数据靠手工贴。
第二版换成了代码化方案,核心思路是"配置文件 + 自动计算 + 结果落库"三层结构:
- 配置文件:每个因子一个 YAML 或 Python dict,写清楚计算逻辑的引用、参数、股票池、分类标准、假设描述。这是唯一的真相来源。
- 计算层:一个统一的因子计算框架,按配置调用对应的计算函数,输出标准格式的因子值表(索引是日期和股票代码,列是因子名)。
- 结果层:因子值存 Parquet 或数据库,检验结果存另一张表,元数据存第三张表。三者用因子 ID 关联。
这样做的最大好处是可复现。任何时候想验证某个因子,读配置、跑计算、出结果,三步搞定,不用去翻半年前的脚本。而且配置可以进版本管理,谁改了什么一目了然。
# 因子配置示例 factor_id: VAL_EP_TTM_AllA_SW2021 name_cn: 盈利收益率 category: 基本面 sub_category: 价值 description: 净利润TTM除以总市值,衡量股东盈利回报的相对水平 hypothesis: 盈利收益率高的股票存在估值折价,长期有超额收益 inputs: - field: net_profit_ttm source: financial_report - field: total_mktcap source: market_data formula: "net_profit_ttm / total_mktcap" universe: all_a_share_ex_st industry_standard: SW2021 lag_days: 60 frequency: daily neutralize: industry: true market_cap: true winsorize: method: mad n: 5 status: active owner: research_team这份配置信息量其实挺大:lag_days: 60明确了财报滞后处理,universe明确了股票池,neutralize明确了中性化方式。看到配置就能复现,这是台账的意义。
4.2 相关性矩阵与因子去重
因子库膨胀到三五十个之后,必然出现冗余。两个相关系数 0.85 的因子放一起,对组合的贡献几乎为零,还徒增过拟合风险。所以定期做相关性分析是必须的。
我的做法是分两步。第一步算全样本的因子值相关性矩阵,用每日横截面相关系数的时序均值。这里要注意,必须是时序均值,不能把面板数据拍平了算,否则会把时序相关性混进去。第二步做聚类,把相关系数 0.7 以上的因子归为一簇,每簇里挑一个代表(通常是 ICIR 最高的那个,或者逻辑最清晰的那个)。
相关性高的处理不能一刀切。有些因子虽然高相关,但失效的时间点不一样,组合起来反而有平滑作用。所以我在聚类之后还会看一个指标:两个因子 IC 时序的相关系数。如果因子值相关性高但 IC 时序相关性低,说明它们在预测能力上互补,可以都留着;如果 IC 时序也高度同步,那就果断砍掉一个。
提示:相关性分析要按因子大类分开做,别把量价因子和基本面因子混在一个矩阵里看。跨大类的高相关往往是有意义的(比如某量价因子在某段时间代理了市值),同类内的高相关才是真正的冗余。
4.3 因子合成:等权、IC 加权与机器学习的取舍
因子汇总到最后一定要合成,否则几十个因子没法直接用。合成方法的选择,决定了你是"稳健但平庸"还是"激进但脆弱"。
等权法是最笨也最稳的。每个因子标准化后取平均,逻辑简单、不需要估计参数、不会过拟合。缺点是它隐含假设所有因子同等重要,实际上有的因子就是比别的强。我见过的实盘组合里,等权法活下来的比例反而最高。
IC 加权法用历史 IC 的均值或者 ICIR 做权重。听起来合理,但有个致命问题:权重估计本身有误差。如果某段时间某因子 IC 突然飙升,权重会被打得很高,结果下一期因子失效,组合直接被打穿。缓解办法是用滚动窗口的 IC 均值、加权重上限、加权重平滑。
机器学习合成包括线性回归、XGBoost、神经网络等。它的优势是能捕捉因子间的非线性关系和交互效应,劣势是黑箱、易过拟合、稳定性差。我的建议是:先跑等权基线,如果机器学习方法在样本外能稳定跑赢等权 2 个百分点以上,再考虑上;如果只赢 0.5 个点,不如省下这个复杂度。
| 合成方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 等权 | 稳健、无参数、易解释 | 忽略因子强弱差异 | 因子数量少、刚起步 |
| IC 加权 | 自动偏向有效因子 | 权重估计误差大、易追高 | 因子库成熟、有长历史 |
| ICIR 加权 | 兼顾方向与稳定性 | 对极端期敏感 | 追求风险调整后收益 |
| 机器学习 | 捕捉非线性 | 黑箱、过拟合风险高 | 因子多、样本足、有调优经验 |
还有一点很重要:合成前一定要做因子方向统一。有的因子是越大越好,有的是越小越好,方向不统一直接加总等于互相抵消。我的做法是在配置里加一个direction字段,合成时自动取负号,比人工记忆靠谱。
5. 实操踩坑记录与排查清单
5.1 数据层面最容易翻车的四处
**复权方式不统一。**这是量价因子的头号杀手。前复权、后复权、不复权,算出来的动量和反转因子天差地别。更隐蔽的是,有的数据源在除权日附近复权因子更新有延迟,导致某几天的收益率异常。我的处理是:所有量价计算强制用同一套复权因子,而且复权因子本身要做一次交叉校验,方法是"复权后价格连乘的收益率"与"复权因子变动"要对得上。
**停牌与退市处理。**停牌期间价格不动,收益率是 0,会稀释动量信号;退市股票如果不剔除,回测里会出现"最后一天暴跌"的假信号。标准做法是:停牌超过一定天数(比如 10 个交易日)的股票从当期股票池剔除,退市股票在退市前一个月剔除。
**ST 与新股。**ST 股票涨跌幅限制不同,波动特征也完全不同,通常要排除。新股上市初期没有历史数据,很多因子算不出来,一般要求上市满 60 或 120 个交易日才纳入。
**缺失值。**这是最容易被糊弄过去的。缺失值填 0、填均值、填行业中位数,结果完全不同。填 0 在财务因子上等于把"没有数据"当成"极差";填均值等于假设它平庸。我的原则是:缺失值在排序时单独归为一组或者直接排除,绝不无声无息地填充。如果某个因子缺失率超过 30%,这个因子就不该进库。
5.2 计算层面的三个隐性 bug
**滚动窗口引入了未来数据。**用rolling计算时,如果没注意center参数或者窗口对齐方式,很容易把 t+1 的数据用到 t 时刻。这类 bug 最阴险,回测收益会莫名好看,但实盘完全复现不了。排查办法是:把因子值往后平移一期再算 IC,对比平移前后的结果差异,差异大就说明有问题。
**分组排序遇到并列值。**因子值有大量并列(比如很多股票的某个财务指标恰好是 0),排序时顺序随机,会导致回测结果不可复现。解决方法是加一个稳定的次级排序键,比如股票代码。
**行业分类变更未同步。**行业分类标准每隔几年会调整,如果历史数据用旧标准、新数据用新标准,中性化的基准就变了。台账里那个industry_standard字段就是为了锁定版本,任何变更必须整体重算。
5.3 常见问题速查表
| 现象 | 可能原因 | 排查动作 |
|---|---|---|
| 单因子 IC 突然由正转负 | 因子失效或被套利 | 拉长窗口看是否持续,检查是否有风格切换 |
| 回测收益远高于实盘 | 未来数据、幸存者偏差、成本未计 | 逐项对照数据时点,加上双边千三成本重跑 |
| 分层回测不单调 | 极端值未处理、因子非线性 | 换去极值方法,试分位数变换 |
| 多因子合成后不如单因子 | 因子方向未统一、共线性严重 | 检查 direction 字段,算 VIF |
| 换手率异常高 | 因子噪声大、排名不稳定 | 加因子平滑,设置调仓缓冲带 |
| 某些股票因子值长期缺失 | 数据源覆盖不足 | 检查覆盖度,考虑限制股票池 |
| 中性化后因子完全失效 | 原始信号主要来自行业或市值暴露 | 检查因子逻辑是否本身就是风格因子 |
6. 因子库的维护节奏与迭代心法
因子库不是建完就完事的静态资产,它更像一个需要持续打理的园子。我给自己定的节奏是:日更因子值、周更暴露监控、季更有效性检验、年做一次大扫除。
日更就是每天收盘后跑一遍因子计算,输出当日因子值,同时做数据质量检查——缺失率、极值数量、分布偏移,任何一项超阈值就报警。周更看组合的风格暴露和因子贡献归因,确认没有意外偏离。季更重跑那三张体检表,把 ICIR 明显下滑的因子标为"观察",连续两个季度不达标就转"停用"。年度大扫除则包括:清理僵尸因子、重算相关性矩阵、重新评估合成方法、检查数据源变更。
这里有个心法值得说:停用因子不等于删除因子。我保留所有历史因子的计算逻辑和检验记录,只是标记状态。因为因子失效往往不是永久的,市场环境变化后可能复活。而且保留历史记录,能让你在复盘时看清"我当年为什么会选中这个因子",这个反思比因子本身更有价值。
另一个体会是,因子汇总的价值有一半在"减法"上。刚开始做的人总想加因子,觉得多一个多一份保险。实际做下来,因子数量从 80 个精简到 25 个,组合表现反而更稳。因为每多一个因子,就多一份参数估计误差、多一份过拟合风险、多一份维护成本。真正的好因子库,应该是每个因子都能说出它为什么存在、什么时候会失效、失效了怎么办。
最后分享一个我自己用的小技巧:给每个因子写一段"讣告"。就是在因子停用时,用三五句话写清楚它是什么时候开始不行的、当时市场发生了什么、我判断是暂时失效还是永久失效。这个习惯坚持了两年,回头翻看时能明显看出市场结构的变化轨迹,比任何研报都直观。因子汇总这件事,做的越久越会发现,你汇总的其实不是因子,是自己对市场的理解。