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 因子处理流程总览

下图展示了从原始数据到标准化因子的完整处理流程,涵盖数据清洗、因子计算与标准化三个核心阶段。

因子处理流程总览 原始数据输入 价格 / 成交量 / 财报 数据清洗 去极值 / 填充缺失 / 对齐 因子计算 动量 / 价值 / 质量 / 波动率 因子标准化 Z-Score / Min-Max / Rank 评分接口输出 多因子加权 / 排名 / 信号 低延迟关键路径 增量更新 + 预计算 避免全量重算

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。