4、行业中性化原理:为什么要做行业中性化、行业分类标准、中性化数学原理
这一节,我们来聊聊行业中性化。
说实话,这是我在实际工作中踩坑最多的地方之一。刚入行那会儿,我辛辛苦苦挖了一个因子,回测曲线漂亮得不行,结果拿去实盘,直接翻车。后来一查,好家伙,因子暴露全压在某个行业上,市场风格一转,直接把我打回原形。
所以,行业中性化不是锦上添花,而是保命用的。
4.1 为什么要做行业中性化
先问一个问题:你选出来的股票,到底是因子在起作用,还是行业在起作用?
举个例子。你发现市盈率低的股票表现好。但仔细一看,这些低市盈率的股票全是银行股。那到底是「低市盈率」这个因子有效,还是「银行板块」本身在涨?
你想想看,如果不做行业中性化,你的因子组合其实偷偷暴露了行业风险。一旦银行板块暴跌,你的因子组合也跟着崩。这锅背得冤不冤?
核心观点:行业中性化的目的,就是剥离掉行业对因子收益的影响,让因子纯粹地反映个股自身的选股能力。
我在项目中遇到过一件事。有个同事做了一个「营收增长因子」,回测年化超额收益15%。我一看持仓,80%的仓位在新能源行业。那段时间新能源正好是风口,猪都能飞。后来风口过了,因子直接变成负收益。这就是典型的「行业伪装成因子」。
所以,行业中性化要解决三个问题:
- 消除行业偏差:不让某个行业主导因子的表现
- 提升因子纯净度:让因子真正反映个股的alpha能力
- 增强组合稳健性:避免因子收益被行业轮动带偏
4.2 行业分类标准
做中性化,首先得有个分类标准。总不能你说这是科技股,我说这是消费股,那还怎么玩?
目前主流的行业分类标准,我列一下:
| 分类标准 | 全称 | 层级 | 常见应用 |
|---|---|---|---|
| GICS | 全球行业分类标准 | 11个行业、24个行业组、69个行业 | MSCI、标普指数 |
| ICB | 行业分类基准 | 11个行业、20个超行业、45个行业 | 富时罗素、欧洲市场 |
| 申万 | 申银万国行业分类 | 31个一级行业、134个二级行业 | A股市场主流 |
| 中信 | 中信证券行业分类 | 30个一级行业、110个二级行业 | 国内机构常用 |
我个人习惯用申万一级行业分类做中性化。为什么?因为A股市场里,申万分类的覆盖面最广,数据也最容易获取。而且31个行业,数量适中,既不会太粗导致中性化效果差,也不会太细导致每个行业里股票太少。
小提示:行业分类不是越细越好。如果某个行业里只有三五只股票,中性化之后因子值会被严重压缩,反而失去区分度。我一般建议一级行业至少要有20只以上的股票。
4.3 中性化数学原理
好了,到了硬核部分。行业中性化到底怎么做?
说白了,就是两步:
- 识别行业暴露:每个股票属于哪个行业,这就是它的行业暴露
- 剥离行业影响:把因子值中能被行业解释的部分去掉,剩下的就是纯净的因子
数学上,我们通常用回归的方法。假设因子值为 \( y \),行业虚拟变量为 \( X \),那么:
y = X * β + ε
其中:
- \( y \) 是原始因子值(比如市盈率倒数、动量等)
- \( X \) 是行业虚拟变量矩阵(每个股票属于哪个行业,对应位置为1,其余为0)
- \( β \) 是行业收益系数
- \( ε \) 是残差,也就是中性化之后的纯净因子
我们真正要的,就是 \( ε \)。它代表「剔除了行业影响之后,个股在因子上的独特表现」。
关键公式:
中性化因子 = 原始因子 - 行业均值
或者更精确地:中性化因子 = 原始因子 - 行业虚拟变量回归的拟合值
嗯,这里要注意。最简单的做法是直接减去行业均值。但这样做有个问题——它假设每个行业对因子的影响是线性的、同质的。实际上,不同行业的因子分布可能差异很大,直接用均值减,效果不一定好。
我建议用回归法。代码实现也很简单:
import pandas as pd
import statsmodels.api as sm
# 假设 df 包含因子值 factor 和行业标签 industry
# 生成行业虚拟变量
dummies = pd.get_dummies(df['industry'], prefix='ind')
# 添加截距项(注意:要drop掉一个虚拟变量避免多重共线性)
X = sm.add_constant(dummies.iloc[:, 1:])
y = df['factor']
# 回归
model = sm.OLS(y, X).fit()
# 残差就是中性化后的因子
df['factor_neutral'] = model.resid
这段代码我用了很多年。每次跑完回归,我都会看一眼残差的分布。如果残差还有明显的行业聚集,说明中性化不彻底,得检查一下是不是行业分类太粗或者数据有问题。
避坑指南:我曾经犯过一个低级错误——做回归时忘了drop掉一个虚拟变量。结果模型报错说「奇异矩阵」,我查了半天才发现是多重共线性。记住,k个行业只需要k-1个虚拟变量,剩下的那个作为基准组。
4.4 行业中性化的可视化理解
光说数学可能有点抽象。我画了一张图,帮你直观理解:
你看,左边是原始因子,行业A的因子值明显高于行业C。如果不做中性化,你选出来的股票大概率集中在行业A。右边是中性化之后,各行业的因子均值被拉平了,这时候选股才真正看的是个股本身的质量。
4.5 实战中的几个细节
最后,分享几个我在实战中总结的经验:
- 频率问题:行业中性化一般每月做一次就够了。太频繁反而引入噪音,太稀疏又跟不上行业变化。
- 极端值处理:做中性化之前,先把因子值的极端值处理一下(比如MAD缩尾)。否则一个极端值会把整个行业的均值拉偏。
- 行业合并:如果某个行业股票太少(比如少于10只),我建议合并到相近的行业里,或者直接用二级行业分类。
- 交叉验证:中性化之后,我习惯算一下每个行业的因子均值。如果某个行业的均值显著不为零,说明中性化没做干净。
一个小技巧:做完行业中性化之后,可以画一张箱线图,看看每个行业的因子分布是否真的对齐了。如果还有明显的偏移,赶紧回去检查代码。
好了,行业中性化的原理就讲到这里。说白了,就是让因子回归它本来的样子——选股,而不是选行业。
公众号:蓝海资料掘金营,微信deep3321