单因子构建:以市盈率倒数(EP)为例
好了,咱们今天来聊聊单因子构建。说实话,很多新手一上来就搞复杂模型,结果因子质量不过关,后面全白搭。我个人习惯是,先拿一个最经典的估值因子练手——市盈率倒数(EP)。
为什么选EP?你想想看,市盈率是大家最熟悉的指标,但直接用市盈率有个问题:数值越大反而越贵。取倒数之后,EP越高代表越便宜,逻辑上更顺。我在项目中遇到过不少团队直接用PE做因子,结果回测效果总是不对劲,其实就是方向搞反了。
EP因子的原始计算
EP的定义很简单:
EP = 净利润 / 总市值
或者用每股收益除以股价:
EP = EPS / 股价
嗯,这里要注意:净利润要用最近12个月的滚动数据(TTM),别用单季度数据,波动太大。我见过有人用去年年报的净利润,结果因子失效了大半年——因为数据太滞后了。
下面是一段Python代码,演示如何从基础数据计算EP因子:
import pandas as pd
import numpy as np
# 假设df包含股票代码、日期、净利润TTM、总市值
def calc_ep_factor(df):
"""
计算市盈率倒数因子
"""
df = df.copy()
# 避免除零
df['EP'] = np.where(df['market_cap'] > 0,
df['net_profit_ttm'] / df['market_cap'],
np.nan)
# 去掉极端值(我一般用1%和99%分位数截断)
lower = df['EP'].quantile(0.01)
upper = df['EP'].quantile(0.99)
df['EP'] = df['EP'].clip(lower, upper)
return df
小提示:我习惯在计算因子后先看一眼分布。如果发现大量负值,说明这批股票整体盈利状况不好,可能需要考虑是否剔除亏损股。
行业中性化处理
原始EP因子有个大问题:不同行业的市盈率水平天差地别。银行业的EP普遍很低,科技股的EP普遍很高。如果你直接用原始EP选股,选出来的全是科技股——这不是因子有效,这是行业偏好。
行业中性化的目的,就是剔除行业对因子的影响。说白了,我们想知道的是:在同一行业内,哪些股票相对更便宜。
具体做法分两步:
- 将EP因子对行业虚拟变量做回归
- 取回归的残差作为中性化后的因子
数学表达就是:
EP = α + β₁*Industry₁ + β₂*Industry₂ + ... + ε
中性化EP = ε
代码实现如下:
from sklearn.linear_model import LinearRegression
def industry_neutralize(df, factor_col='EP', industry_col='industry_code'):
"""
行业中性化处理
"""
df = df.copy()
# 生成行业哑变量
industry_dummies = pd.get_dummies(df[industry_col], prefix='ind')
# 回归模型
model = LinearRegression()
# 注意:这里要去掉截距项,否则会共线性
model.fit(industry_dummies, df[factor_col])
# 预测值 = 行业解释的部分
predicted = model.predict(industry_dummies)
# 残差 = 中性化后的因子
df['EP_neutral'] = df[factor_col] - predicted
return df
注意:做行业中性化时,一定要在每个月(或每个调仓日)独立做回归。我见过有人把所有时间的数据混在一起做,结果中性化效果大打折扣——因为行业结构会随时间变化。
为什么需要行业中性化?
我举个例子你就明白了。假设有两个行业:
| 行业 | 平均EP | 标准差 |
|---|---|---|
| 银行 | 0.08 | 0.02 |
| 科技 | 0.03 | 0.01 |
如果不做中性化,银行股全部排前面,科技股全部排后面。但实际投资中,你可能想从银行里挑最便宜的,从科技里也挑最便宜的。中性化之后,每个行业的EP都变成了相对于行业均值的偏离度,这样跨行业比较才有意义。
核心逻辑流程图
下面这张图展示了EP因子构建的完整流程:
实际应用中的注意事项
做完行业中性化之后,我建议你再检查两件事:
- 检查行业分组效果:中性化后,每个行业的EP均值应该接近0。如果某个行业均值明显偏离,说明中性化不彻底。
- 检查因子IC:计算中性化前后EP因子与未来收益的IC(信息系数)。你会发现中性化后的IC更稳定,不会出现某几个月突然失效的情况。
核心要点:单因子构建不是简单的公式计算。原始因子只是半成品,行业中性化才是让它真正可用的关键一步。我做了这么多年量化,见过太多人栽在这个坑里——因子回测效果很好,实盘一跑就崩,十有八九是没做中性化。
好了,EP因子的构建和中性化处理就讲到这里。记住:因子构建的每一步都要经得起推敲,尤其是数据清洗和中性化处理,这两步决定了因子质量的80%。