2. 量化因子基础:常见因子类型、计算逻辑与标准化方法
量化因子是将原始市场数据(价格、成交量、财务指标)转化为可预测收益信号的数学映射。因子的质量直接决定策略的夏普比率与最大回撤。本章从因子分类、计算逻辑到标准化方法,建立完整的因子研究基础。
2.1 常见因子类型
根据驱动逻辑与数据来源,量化因子通常分为四大类:动量、价值、质量与波动率。下表对比了各类因子的核心逻辑、典型指标与适用场景。
| 因子类别 | 核心逻辑 | 典型指标 | 数据来源 | 适用市场 |
|---|---|---|---|---|
| 动量因子 | 过去收益趋势延续或反转 | 过去N日收益率、RSI、MACD | 价格、成交量 | 股票、期货、加密货币 |
| 价值因子 | 价格低于内在价值时回归 | PE、PB、PS、股息率 | 财务报表 | 股票、债券 |
| 质量因子 | 高盈利能力、低财务风险 | ROE、毛利率、资产负债率 | 财务报表 | 股票、信用债 |
| 波动率因子 | 低波动股票长期跑赢高波动 | 历史波动率、ATR、Beta | 价格 | 股票、ETF |
实战提示: 在低延迟评分接口中,动量与波动率因子可直接从Tick或分钟级K线实时计算;价值与质量因子依赖财报更新频率(季报/年报),适合做低频截面因子。
2.2 因子计算逻辑
每种因子都有标准的数学定义。以下给出四个核心因子的计算逻辑与Python伪代码。
2.2.1 动量因子:过去N日收益率
最简单的动量因子是过去N个交易日的累计收益率,用于捕捉趋势延续效应。
def momentum(close_prices, window=20):
"""
计算过去N日收益率动量因子
:param close_prices: 收盘价序列 (numpy array)
:param window: 回溯窗口
:return: 动量因子值
"""
if len(close_prices) < window + 1:
return np.nan
return (close_prices[-1] - close_prices[-window - 1]) / close_prices[-window - 1]
2.2.2 价值因子:市盈率倒数(E/P)
市盈率倒数(Earnings Yield)是经典价值因子,数值越高代表股票相对盈利越便宜。
def earnings_yield(market_cap, net_income):
"""
计算市盈率倒数 E/P
:param market_cap: 总市值
:param net_income: 最近12个月净利润
:return: E/P 因子值
"""
if market_cap <= 0 or net_income <= 0:
return np.nan
return net_income / market_cap
2.2.3 质量因子:ROE(净资产收益率)
ROE衡量公司利用股东权益创造利润的能力,是质量因子的核心代表。
def roe(net_income, shareholders_equity):
"""
计算净资产收益率 ROE
:param net_income: 净利润
:param shareholders_equity: 股东权益
:return: ROE 因子值
"""
if shareholders_equity <= 0:
return np.nan
return net_income / shareholders_equity
2.2.4 波动率因子:历史波动率
历史波动率基于过去N日对数收益率的标准差,衡量价格的不确定性。
def historical_volatility(close_prices, window=20, annual_factor=252):
"""
计算年化历史波动率
:param close_prices: 收盘价序列
:param window: 波动率计算窗口
:param annual_factor: 年化因子(日数据用252)
:return: 年化波动率
"""
log_returns = np.log(close_prices[1:] / close_prices[:-1])
if len(log_returns) < window:
return np.nan
return np.std(log_returns[-window:]) * np.sqrt(annual_factor)
低延迟优化要点: 在评分接口中,动量与波动率因子应使用增量更新(rolling update)而非全量重算。例如,使用EMA递推公式替代全窗口标准差,可将计算复杂度从O(N)降至O(1)。
2.3 因子标准化方法
原始因子值量纲差异巨大(如PE可能从5到500,ROE从-50%到50%),直接用于截面选股或评分会导致量纲大的因子主导结果。标准化是因子研究的必要步骤。
下表对比了三种主流标准化方法的计算方式与适用场景。
| 标准化方法 | 计算公式 | 输出范围 | 对异常值敏感度 | 适用场景 |
|---|---|---|---|---|
| Z-Score | (x - μ) / σ | 无界(通常[-3,3]) | 高 | 正态分布因子 |
| Min-Max | (x - min) / (max - min) | [0, 1] | 极高 | 有界因子、神经网络输入 |
| Rank(排序分位) | rank(x) / N | [0, 1] | 低(鲁棒) | 截面选股、多因子合成 |
2.3.1 Z-Score 标准化
假设因子值服从正态分布,减去均值后除以标准差。适用于因子分布对称且异常值较少的场景。
def zscore_standardize(factor_values):
"""
Z-Score 标准化
:param factor_values: numpy array
:return: 标准化后的因子值
"""
mean = np.nanmean(factor_values)
std = np.nanstd(factor_values)
if std == 0:
return np.zeros_like(factor_values)
return (factor_values - mean) / std
2.3.2 Rank 排序分位标准化
将因子值转换为0到1之间的排序分位数,完全消除量纲与异常值影响,是量化研究中最常用的标准化方法。
def rank_standardize(factor_values):
"""
Rank 排序分位标准化
:param factor_values: numpy array
:return: [0,1] 之间的分位数值
"""
valid_mask = ~np.isnan(factor_values)
ranks = np.empty_like(factor_values)
ranks[valid_mask] = np.argsort(np.argsort(factor_values[valid_mask]))
ranks[~valid_mask] = np.nan
n_valid = np.sum(valid_mask)
if n_valid == 0:
return ranks
return ranks / n_valid
避坑指南: 在低延迟评分接口中,标准化必须在每个截面(如每日收盘后)重新计算均值和排序,不能使用历史全局参数。否则会导致因子值漂移,破坏截面可比性。
2.4 因子处理流程总览
下图展示了从原始数据到标准化因子的完整处理流程,涵盖数据清洗、因子计算与标准化三个核心阶段。
2.5 因子标准化对比实验
以下示例展示同一组原始因子值(含异常值)经过三种标准化方法后的输出差异,帮助理解标准化对评分结果的影响。
import numpy as np
# 原始因子值(含一个极端异常值)
raw_factors = np.array([10, 12, 11, 13, 100, 12, 11, 10, 14, 13])
# Z-Score 标准化
z_scores = (raw_factors - np.mean(raw_factors)) / np.std(raw_factors)
# Min-Max 标准化
min_val, max_val = np.min(raw_factors), np.max(raw_factors)
minmax = (raw_factors - min_val) / (max_val - min_val)
# Rank 排序分位标准化
ranks = np.argsort(np.argsort(raw_factors))
rank_norm = ranks / len(raw_factors)
print("原始值: ", raw_factors)
print("Z-Score: ", np.round(z_scores, 3))
print("Min-Max: ", np.round(minmax, 3))
print("Rank分位: ", np.round(rank_norm, 3))
输出结果分析:
- Z-Score:异常值100被映射到约2.8,仍显著偏离其他值,对后续加权评分影响大。
- Min-Max:异常值被映射到1.0,其他值被压缩到0~0.04之间,信息损失严重。
- Rank分位:异常值仅被映射到0.9(最高分位),其他值均匀分布在0~0.8之间,保留了排序信息且不受异常值幅度影响。
推荐实践: 在量化因子研究的评分接口中,优先使用 Rank排序分位标准化。它对异常值鲁棒、保持截面可比性,且计算复杂度低(O(N log N)),适合低延迟场景。若因子分布接近正态且已做去极值处理,可选用Z-Score。