3. 因子计算与标准化
因子计算与标准化是量化因子研究流程中的核心环节。原始因子数据通常包含极端值、量纲差异和行业/市值干扰,必须经过系统化处理才能用于后续的因子有效性检验和组合构建。本章将详细讲解因子计算公式、去极值、标准化和中性化处理的标准流程。
3.1 因子计算公式
因子计算是将原始市场数据(价格、成交量、财务指标等)转化为具有预测能力的数值信号的过程。常见的因子计算公式可分为以下几类:
| 因子类别 | 典型公式 | 参数说明 |
|---|---|---|
| 动量因子 | Momentum = (Pt / Pt-n) - 1 |
Pt为当日收盘价,n为回溯期(如20日) |
| 反转因子 | Reversal = (Pt-1 / Pt-21) - 1 |
使用过去1日与21日均价之比 |
| 波动率因子 | Volatility = std(returnt-20:t-1) |
过去20日收益率的标准差 |
| 价值因子 | BP = BookValue / MarketCap |
账面市值比,需使用最新财报数据 |
| 质量因子 | ROE = NetIncome / Equity |
净资产收益率,反映盈利能力 |
实战要点:因子计算时需注意数据对齐——财务数据应使用最新披露的季报/年报,价格数据需考虑复权处理(前复权或后复权),避免因分红送股导致的价格跳跃影响因子值。
3.2 去极值处理
原始因子数据中常包含极端异常值,这些值可能由数据错误、特殊事件或市场极端波动引起。若不处理,会严重扭曲后续标准化和回归分析的结果。常用的去极值方法有两种:
3.2.1 MAD(中位数绝对偏差)法
MAD法基于中位数和绝对偏差,对异常值具有较好的鲁棒性。处理步骤如下:
- 计算因子序列的中位数
median - 计算每个因子值与中位数的绝对偏差
|xi - median| - 计算绝对偏差的中位数
MAD = median(|xi - median|) - 设定阈值
n(通常取3~5),将超出median ± n × MAD的值替换为边界值
import numpy as np
def mad_winsorize(factor, n=5):
median = np.median(factor)
mad = np.median(np.abs(factor - median))
upper = median + n * mad
lower = median - n * mad
return np.clip(factor, lower, upper)
3.2.2 百分位法
百分位法直接根据数据分布的分位数设定上下限,操作简单直观:
def percentile_winsorize(factor, lower_pct=0.01, upper_pct=0.99):
lower = np.percentile(factor, lower_pct * 100)
upper = np.percentile(factor, upper_pct * 100)
return np.clip(factor, lower, upper)
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| MAD法 | 对极端值不敏感,鲁棒性强 | 计算稍复杂,需选择n值 | 因子分布偏态严重时 |
| 百分位法 | 简单直观,易于解释 | 可能剔除过多正常值 | 因子分布较对称时 |
常见误区:去极值不等于删除数据。正确的做法是使用“截尾(Winsorize)”将极端值替换为边界值,而非直接删除样本点,否则会破坏截面数据的完整性,导致后续分析产生偏差。
3.3 标准化处理
标准化旨在消除不同因子之间的量纲差异,使因子值具有可比性。常用的标准化方法包括Z-score和Rank标准化。
3.3.1 Z-score标准化
Z-score将因子转换为均值为0、标准差为1的标准正态分布:
def zscore_normalize(factor):
mean = np.mean(factor)
std = np.std(factor)
return (factor - mean) / std
Z-score的优点是保留了因子值的相对距离信息,但要求因子分布接近正态分布,且对异常值敏感。因此,Z-score标准化前必须先进行去极值处理。
3.3.2 Rank标准化
Rank标准化将因子值转换为排序后的百分位数,最终映射到[0,1]或[-1,1]区间:
def rank_normalize(factor):
rank = factor.rank()
return (rank - 1) / (len(rank) - 1) # 映射到[0,1]
Rank标准化的优势在于:
- 对异常值不敏感,无需预先去极值
- 适用于任何分布形态的数据
- 保留了因子间的排序关系
方法对比:Z-score适合因子值本身具有实际意义、分布较对称的场景(如估值类因子);Rank标准化更适合因子值仅需排序信息、分布不确定的场景(如情绪类因子)。在实际多因子模型中,Rank标准化更为常用。
3.4 中性化处理
中性化处理旨在剔除因子中与行业、市值等系统性变量相关的部分,提取因子特有的选股能力。最常用的方法是回归残差法:
- 以因子值为因变量,行业虚拟变量和市值(或市值对数)为自变量,建立线性回归模型
- 提取回归残差作为中性化后的因子值
import statsmodels.api as sm
def neutralize_factor(factor, industry_dummies, market_cap):
# 构建自变量矩阵:行业哑变量 + 市值对数
X = pd.concat([industry_dummies, np.log(market_cap)], axis=1)
X = sm.add_constant(X)
# 回归并提取残差
model = sm.OLS(factor, X).fit()
return model.resid
中性化要点:
- 行业中性化:使用申万一级或二级行业分类,每个股票属于且仅属于一个行业
- 市值中性化:通常使用市值对数而非原始市值,以降低市值分布的偏态影响
- 中性化应在截面(横截面)上进行,即每个时间点独立处理
3.5 完整处理流程
下图展示了因子计算与标准化的完整处理流程:
3.6 处理顺序与注意事项
因子处理的顺序至关重要,错误的顺序会导致结果失真。推荐的处理顺序为:
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 因子计算 | 根据公式计算原始因子值 |
| 2 | 去极值 | 使用MAD或百分位法处理极端值 |
| 3 | 标准化 | Z-score或Rank标准化,消除量纲 |
| 4 | 中性化 | 回归残差法剔除行业/市值影响 |
顺序陷阱:若先中性化再去极值,极端值会通过回归模型影响中性化系数,导致中性化效果变差。若先标准化再去极值,标准化后的均值和标准差会被极端值扭曲。因此,去极值 → 标准化 → 中性化是标准且不可颠倒的顺序。
完成上述全部处理后,得到的因子值即为可用于后续有效性检验和组合构建的标准化因子。该因子值在不同股票之间具有可比性,且剔除了行业和市值的系统性影响,能够更纯粹地反映因子本身的选股能力。