3. 因子构建方法:从原始数据到可用信号
好,咱们进入实战环节。前面聊了因子数据怎么来、怎么清洗,现在要解决一个核心问题:怎么把一堆乱七八糟的原始数据,变成能用的因子信号?
我个人习惯把因子构建拆成四个步骤:标准化、加权、中性化处理。每一步都有坑,咱们一个一个说。
3.1 单一指标标准化
你想想看,ESG数据里,碳排放量是吨,员工满意度是百分数,董事会独立性是比例。这些量纲都不一样,怎么放一起比?
标准化就是解决这个问题的。我常用的方法有三种:
| 方法 | 公式 | 适用场景 |
|---|---|---|
| Z-score 标准化 | (x - μ) / σ | 数据近似正态分布 |
| Min-Max 归一化 | (x - min) / (max - min) | 数据有明确边界 |
| 排序百分位法 | rank(x) / N | 存在极端值 |
我在项目中遇到过一个问题:某家公司的碳排放数据有个极端值,用 Z-score 标准化后,其他公司全被压缩到 -0.1 到 0.1 之间,信号几乎失效。后来改用排序百分位法,效果就好多了。
核心原则:标准化不是越复杂越好,关键是匹配数据分布特征。
# Python 示例:三种标准化方法
import pandas as pd
import numpy as np
def zscore_standardize(series):
return (series - series.mean()) / series.std()
def minmax_normalize(series):
return (series - series.min()) / (series.max() - series.min())
def percentile_rank(series):
return series.rank(pct=True)
3.2 综合评分加权法
标准化之后,就要把多个指标合成一个综合得分。这里有个关键问题:权重怎么定?
我见过很多新手直接拍脑袋定权重,比如环境30%、社会30%、治理40%。这种做法其实很危险。为什么?因为权重决定了因子的表现,拍脑袋很容易过拟合。
我个人建议用以下三种方法之一:
- 等权重法:简单粗暴,但稳健。适合探索阶段。
- 主成分分析法(PCA):让数据自己说话,提取主要成分作为权重。
- IC 加权法:用每个子因子与未来收益的 IC 值作为权重,动态调整。
我的经验:等权重法在大多数情况下效果不差。别小看简单方法,它不容易过拟合。
# 综合评分计算示例
def composite_score(df, weights):
"""
df: 标准化后的因子数据框
weights: 权重字典,如 {'E': 0.3, 'S': 0.3, 'G': 0.4}
"""
score = pd.Series(0, index=df.index)
for factor, weight in weights.items():
score += df[factor] * weight
return score
3.3 行业中性化处理
嗯,这里要注意。不同行业的 ESG 水平天然不同。比如银行业几乎没有环境风险,但化工行业环境风险很高。如果不做行业中性化,你选出来的全是低环境风险的行业,而不是真正的好公司。
行业中性化的核心思想:在行业内比较,而不是跨行业比较。
具体做法分两步:
- 计算每个行业内因子的均值和标准差。
- 用行业内 Z-score 替代原始值。
我曾经踩过的坑:做行业中性化时,有些行业只有一两家公司,算出来的均值和标准差毫无意义。我的建议是:行业样本量少于5家时,合并到相近行业或者直接用全市场数据。
def industry_neutralize(df, factor_col, industry_col):
"""
行业中性化处理
"""
def group_zscore(group):
return (group - group.mean()) / group.std()
df['neutralized'] = df.groupby(industry_col)[factor_col].transform(group_zscore)
return df
3.4 市值中性化处理
市值中性化的逻辑和行业中性化类似。大市值公司和小市值公司的 ESG 表现天然不同——大公司有更多资源做 ESG 披露,小公司往往披露不足。
如果不做市值中性化,你选出来的可能全是大盘股,而不是真正的 ESG 优等生。
常用的方法有两种:
- 回归残差法:用因子值对市值做回归,取残差作为中性化后的因子。
- 分组标准化法:按市值分10组,组内做标准化。
我个人更推荐回归残差法,因为它更精细,能捕捉到市值对因子的非线性影响。
# 市值中性化:回归残差法
import statsmodels.api as sm
def market_cap_neutralize(factor, log_market_cap):
"""
factor: 原始因子值
log_market_cap: 对数市值
"""
X = sm.add_constant(log_market_cap)
model = sm.OLS(factor, X).fit()
residual = model.resid
return residual
知识体系总览
说了这么多,咱们用一张图把整个流程串起来:
这张图把整个流程串起来了。你想想看,从原始数据到最终因子,每一步都有它的道理。标准化解决量纲问题,加权解决合成问题,中性化解决偏差问题。缺一步都不行。
总结一下:因子构建不是简单的数学运算,而是对数据背后业务逻辑的深刻理解。标准化、加权、中性化,每一步都是在回答一个问题:我们到底想衡量什么?
好了,这一章的内容就到这里。记住,因子构建的质量直接决定了后续策略的上限。数据进,垃圾出——这个道理在量化投资里永远成立。