2. 因子模型构建:单因子模型、多因子模型、因子暴露与因子收益率的计算

因子模型是量化组合风险归因与收益分解的核心工具。它将资产的收益率分解为系统性因子贡献与特质性残差两部分,从而将高维的资产协方差矩阵降维到低维的因子协方差矩阵,极大简化了风险建模与组合优化的复杂度。

2.1 单因子模型:CAPM 与市场模型

单因子模型假设资产收益率仅受一个共同因子驱动,最经典的实现是资本资产定价模型(CAPM)与市场模型(Market Model)。

模型 公式 核心假设 因子含义
CAPM \(R_i - R_f = \beta_i (R_m - R_f) + \epsilon_i\) 市场组合有效、投资者同质预期 市场超额收益
市场模型 \(R_i = \alpha_i + \beta_i R_m + \epsilon_i\) 仅需线性回归假设 市场收益率(含截距)
实践要点: 市场模型不要求 \(R_f\) 已知,直接对原始收益率做 OLS 回归,更便于工程实现。但 CAPM 在理论上要求 \(\alpha_i = 0\),若回归发现显著非零的 \(\alpha\),则意味着存在定价异象或模型设定偏误。

2.2 多因子模型:从 Fama-French 到 Barra 体系

单因子模型无法解释大量横截面收益差异,多因子模型应运而生。常见体系包括:

  • Fama-French 三因子模型: 市场因子 (MKT)、规模因子 (SMB)、价值因子 (HML)。
  • Carhart 四因子模型: 在三因子基础上加入动量因子 (MOM)。
  • Barra 风险模型: 包含国家因子、行业因子、风格因子(如市值、波动率、成长、杠杆等),通常使用 10~50 个因子。
  • 统计因子模型: 通过 PCA、ICA 等无监督方法从收益率协方差矩阵中提取主成分作为因子。
工程选择建议: 在组合风险归因场景中,Barra 风格因子模型因其因子经济含义明确、行业暴露可解释性强,成为业界主流。统计因子模型虽拟合优度高,但因子缺乏经济含义,不利于向投资者解释风险来源。
多因子模型体系分类 多因子模型 经济因子模型 统计因子模型 混合因子模型 Fama-French Barra 风格 PCA 主成分 ICA 独立成分 先验+统计增强 应用场景:组合风险归因、绩效分解、因子择时、Smart Beta 策略构建 选择依据:因子可解释性 > 统计拟合优度(面向投资者场景)

2.3 因子暴露的计算

因子暴露(Factor Exposure / Factor Loading)衡量资产对每个因子的敏感度。根据因子类型不同,计算方法分为两类:

2.3.1 基于回归的暴露估计

对于经济因子模型,通常使用时间序列回归估计因子暴露:

# Python: 使用滚动窗口 OLS 估计因子暴露
import pandas as pd
import statsmodels.api as sm

def estimate_factor_exposure(returns, factor_returns, window=252):
    """
    returns: 个股日收益率 Series
    factor_returns: 因子收益率 DataFrame (每列一个因子)
    window: 滚动窗口长度
    """
    exposures = []
    for i in range(window, len(returns)):
        y = returns.iloc[i-window:i]
        X = factor_returns.iloc[i-window:i]
        X = sm.add_constant(X)  # 加入截距项 alpha
        model = sm.OLS(y, X).fit()
        exposures.append(model.params[1:])  # 排除截距
    return pd.DataFrame(exposures, index=returns.index[window:], columns=factor_returns.columns)

2.3.2 基于截面特征的暴露赋值

对于 Barra 风格因子,暴露通常由资产自身的特征值直接计算:

因子名称 暴露计算方法 数据来源
市值因子 (Size) \(\text{ln(总市值)}\) 经 Z-score 标准化 日频市值数据
波动率因子 (Volatility) 过去 60 日收益率年化波动率的秩标准化 日频收益率
价值因子 (Value) \(\text{ln(B/P)}\) 经行业中性化处理 财报账面价值
动量因子 (Momentum) 过去 12 个月累计收益率(剔除最近 1 个月) 月频收益率
行业因子 哑变量编码:属于该行业为 1,否则为 0 行业分类标准
工程陷阱: 截面标准化时需注意异常值处理。市值因子常呈现右偏分布,直接 Z-score 会导致极端值主导回归结果。建议先取对数,再使用中位数绝对偏差(MAD)替代标准差做稳健标准化。

2.4 因子收益率的计算

因子收益率(Factor Return)是因子在截面上的溢价,即每单位暴露所获得的超额收益。计算方法取决于模型设定:

2.4.1 时间序列回归法(两步法)

  1. 第一步: 对每只股票做时间序列回归,估计因子暴露 \(\beta_{i,k}\)。
  2. 第二步: 在每个截面时点 \(t\),以股票收益率 \(R_{i,t}\) 为因变量,以第一步估计的暴露 \(\beta_{i,k}\) 为自变量,做截面回归,回归系数即为因子收益率 \(f_{k,t}\)。
# Python: 截面回归估计因子收益率
def estimate_factor_returns(returns_cross_section, exposures):
    """
    returns_cross_section: 截面收益率 Series (index=股票)
    exposures: DataFrame (index=股票, columns=因子)
    """
    X = sm.add_constant(exposures)
    model = sm.OLS(returns_cross_section, X).fit()
    return model.params  # 包含截距和所有因子收益率

2.4.2 组合排序法(Fama-French 经典方法)

通过构建多空组合直接计算因子收益率,无需回归:

  • SMB (Small Minus Big): 小市值股票组合收益率减去大市值股票组合收益率。
  • HML (High Minus Low): 高账面市值比组合收益率减去低账面市值比组合收益率。
  • MOM (Momentum): 过去收益最高组合减去过去收益最低组合。

2.5 因子模型的风险归因公式

一旦获得因子暴露矩阵 \(B\) 和因子协方差矩阵 \(\Sigma_f\),组合风险可分解为:

风险成分 公式 含义
因子风险 \(\sigma^2_{factor} = w^T B \Sigma_f B^T w\) 由因子波动引起的组合风险
特质风险 \(\sigma^2_{specific} = w^T \Delta w\) 由个股残差波动引起的组合风险
总风险 \(\sigma^2_{total} = \sigma^2_{factor} + \sigma^2_{specific}\) 组合总方差
因子边际贡献 \(MCR_k = \frac{w^T B_k \Sigma_f B^T w}{\sigma_{total}}\) 第 k 个因子对总风险的边际贡献
实践要点: 因子协方差矩阵 \(\Sigma_f\) 的估计通常使用指数加权移动平均(EWMA)或收缩估计(Shrinkage),以平衡估计偏差与方差。特质风险矩阵 \(\Delta\) 通常假设为对角矩阵,即残差之间不相关。
因子模型风险归因计算流程 组合权重 w (N x 1) 因子暴露 B (N x K) 因子协方差 Σ_f (K x K) 特质方差 Δ (N x N 对角) 组合因子暴露 w^T B (1 x K) 因子风险方差 w^T B Σ_f B^T w 因子风险贡献 % 因子风险 / 总风险 特质风险贡献 % 特质风险 / 总风险 因子边际贡献 MCR_k

2.6 模型验证与诊断

构建因子模型后,需进行以下诊断以确保模型质量:

  • 因子显著性检验: 截面回归中因子收益率的 t 统计量是否显著(|t| > 2)。
  • 残差自相关检验: 个股残差序列的 Durbin-Watson 统计量是否接近 2。
  • 因子多重共线性: 因子暴露矩阵的条件数(Condition Number)是否小于 30,若过大需考虑因子正交化。
  • R² 分布: 模型对个股收益率的解释力度,横截面 R² 中位数应 > 30%。
  • 因子收益率序列平稳性: ADF 检验确保因子收益率序列平稳,避免伪回归。
工程实践: 在生产环境中,因子模型通常每日重新估计一次暴露,但因子收益率可保持周频或月频更新以降低噪声。建议使用 pandas.DataFrame.rolling 实现滚动回归,并利用 numba 或 joblib 并行加速多只股票的暴露估计。