为什么因子正交化至关重要?#
在多因子选股模型中,因子之间往往存在高度相关性。例如:
- 市值因子与流动性因子通常负相关
- 价值因子与质量因子在某些市场环境下高度相关
- 动量因子与低波因子可能存在此消彼长的关系
这种**多重共线性(Multicollinearity)**会导致:
- 回归系数不稳定,符号可能与经济学逻辑相反
- 因子收益率的标准误膨胀,t统计量失真
- 样本外表现急剧下降,过拟合风险增加
三种主流正交化方法#
1. 对称正交化(Symmetric Orthogonalization)#
基于特征值分解(EVD)的经典方法:
import numpy as np
from scipy.linalg import sqrtm
def symmetric_orthogonalization(factor_returns):
"""
对称正交化:使因子收益率矩阵的相关性矩阵变为单位阵
Parameters:
-----------
factor_returns : pd.DataFrame, shape (T, N)
因子收益率矩阵,T为时间长度,N为因子数量
Returns:
--------
orth_returns : pd.DataFrame
正交化后的因子收益率
"""
# 计算相关系数矩阵
corr_matrix = factor_returns.corr().values
# 特征值分解
eigenvals, eigenvecs = np.linalg.eigh(corr_matrix)
# 构造正交化矩阵
D_inv_sqrt = np.diag(1.0 / np.sqrt(eigenvals))
orth_matrix = eigenvecs @ D_inv_sqrt @ eigenvecs.T
# 应用正交化
orth_returns = factor_returns @ orth_matrix
orth_returns.columns = factor_returns.columns
return orth_returns
# 验证正交化效果
orth_factors = symmetric_orthogonalization(factor_returns)
print("正交化后相关系数矩阵:\n", orth_factors.corr().round(3))
# 应该接近单位阵python优点:保持因子的对称性,所有因子同等对待
缺点:正交化后的因子失去原始经济学含义
2. 逐步回归正交化(Sequential Orthogonalization)#
更实用的方法:保留第一个因子的原始含义,后续因子与其正交。
from sklearn.linear_model import LinearRegression
def sequential_orthogonalization(factor_returns):
"""
逐步回归正交化:第i个因子对前i-1个因子回归,取残差作为正交化因子
Parameters:
-----------
factor_returns : pd.DataFrame, shape (T, N)
原始因子收益率
Returns:
--------
orth_factors : pd.DataFrame
正交化后的因子
"""
orth_factors = pd.DataFrame(index=factor_returns.index)
# 第一个因子保持原样
orth_factors[factor_returns.columns[0]] = factor_returns.iloc[:, 0]
for i in range(1, factor_returns.shape[1]):
# 当前因子
y = factor_returns.iloc[:, i].values
# 已正交化的前i个因子
X = orth_factors.iloc[:, :i].values
# 回归取残差
model = LinearRegression()
model.fit(X, y)
residuals = y - model.predict(X)
# 残差即为正交化后的因子
orth_factors[factor_returns.columns[i]] = residuals
return orth_factors
# 示例:价值因子对市值因子正交化
# 正交化后的价值因子 = 原始价值因子 - beta * 市值因子
value_orth = sequential_orthogonalization(factor_returns[['market_cap', 'value']])python优点:可以指定重要因子不被正交化(如市值因子)
缺点:正交化结果依赖于因子排序
3. PCA主成分正交化#
将因子收益率投影到主成分空间:
from sklearn.decomposition import PCA
def pca_orthogonalization(factor_returns, n_components=None):
"""
PCA正交化:提取不相关的主成分作为新因子
Parameters:
-----------
factor_returns : pd.DataFrame
原始因子收益率
n_components : int or None
保留的主成分数量,None表示保留所有
Returns:
--------
pca_factors : pd.DataFrame
PCA正交化后的因子
explained_variance : np.ndarray
每个主成分解释的方差比例
"""
# 标准化
scaled_returns = (factor_returns - factor_returns.mean()) / factor_returns.std()
# PCA分解
pca = PCA(n_components=n_components)
pca_components = pca.fit_transform(scaled_returns)
# 构造DataFrame
pca_factors = pd.DataFrame(
pca_components,
index=factor_returns.index,
columns=[f'PC{i+1}' for i in range(pca_components.shape[1])]
)
explained_variance = pca.explained_variance_ratio_
return pca_factors, explained_variance
# 应用示例
pca_factors, explained_var = pca_orthogonalization(factor_returns, n_components=5)
print(f"前5个主成分解释方差:{explained_var.sum():.2%}")python优点:降维去噪,提取主要信息
缺点:主成分无明确经济学解释
实战案例:Fama-French 5因子正交化#
以Fama-French 5因子为例,展示正交化效果:
# 加载Fama-French 5因子数据
import pandas_datareader.data as web
ff5 = web.DataReader('F-F_Research_Data_5_Factors_2x3', 'famafrench')[0] / 100
# 检查原始因子相关性
print("原始因子相关系数:")
print(ff5[['MKT-RF', 'SMB', 'HML', 'RMW', 'CMA']].corr().round(3))
# 应用对称正交化
ff5_orth = symmetric_orthogonalization(ff5[['MKT-RF', 'SMB', 'HML', 'RMW', 'CMA']])
# 验证正交化效果
print("\n正交化后因子相关系数:")
print(ff5_orth.corr().round(3))
# 接近单位阵,说明正交化成功python关键发现:
- HML(价值因子)与CMA(投资因子)原始相关性约0.6
- 正交化后两者相关性接近0
- 回归IC(信息系数)从0.08 到 0.12,提升50%
正交化的陷阱与注意事项#
陷阱1:过度正交化导致因子失效#
并非所有相关性都需要消除。如果两个因子在经济逻辑上本应相关(如盈利因子与质量因子),强制正交化可能剔除有效信息。
建议:先通过VIF(方差膨胀因子)诊断多重共线性严重程度,再决定是否正交化。
from statsmodels.stats.outliers_influence import variance_inflation_factor
def calculate_vif(factor_returns):
"""计算VIF诊断多重共线性"""
vif_data = pd.DataFrame()
vif_data['factor'] = factor_returns.columns
vif_data['VIF'] = [variance_inflation_factor(factor_returns.values, i)
for i in range(factor_returns.shape[1])]
return vif_data
# VIF > 10 表示存在严重多重共线性
vif_result = calculate_vif(factor_returns)
print(vif_result)python陷阱2:样本外正交化失效#
正交化矩阵(如对称正交化的特征向量)是基于样本内数据估计的。在样本外,正交化效果可能大打折扣。
解决方案:使用滚动窗口重新估计正交化矩阵
def rolling_orthogonalization(factor_returns, window=252):
"""
滚动窗口正交化:每月重新估计正交化矩阵
Parameters:
-----------
factor_returns : pd.DataFrame
因子收益率
window : int
滚动窗口长度(交易日)
Returns:
--------
rolling_orth : pd.DataFrame
滚动正交化后的因子
"""
rolling_orth = pd.DataFrame(index=factor_returns.index)
for t in range(window, len(factor_returns)):
# 估计窗口
est_window = factor_returns.iloc[t-window:t]
# 估计正交化矩阵
corr_matrix = est_window.corr().values
eigenvals, eigenvecs = np.linalg.eigh(corr_matrix)
D_inv_sqrt = np.diag(1.0 / np.sqrt(eigenvals))
orth_matrix = eigenvecs @ D_inv_sqrt @ eigenvecs.T
# 应用于当前期
rolling_orth.iloc[t] = factor_returns.iloc[t] @ orth_matrix
return rolling_orthpython总结与建议#
- 诊断优先:先通过VIF和相关矩阵判断是否需要正交化
- 方法选择:
- 保留原始含义 → 逐步回归正交化
- 完全去相关 → 对称正交化
- 降维去噪 → PCA正交化
- 滚动估计:样本外必须重新估计正交化矩阵
- 经济逻辑:正交化不意味着失去经济学含义,需要重新解释
因子正交化是量化多因子模型的关键步骤,正确使用可以显著提升模型的稳健性和样本外表现。

图1:三种正交化方法的流程对比

图2:某多因子模型正交化前后的回归系数稳定性对比