第 10 章 · 01 PCA 与风险因子 本节摘要:本节进入无监督学习,从最经典的线性降维——主成分分析(PCA)开始。PCA 不需要标签,它能从资产收益矩阵中「凭空」抽出几个隐性因子,这些因子对应着市场里无法直接观察的系统性风险源。本节讲清四件事:PCA 的数学动机(找到方差最大的方向)、它与 SVD 的关系、为什么必须先做 winsorize 与标准化;如何用 sklearn 的 把 350 只美股的日收益压成几个主成分,并用 判断该留几个;以及如何用主成分构造「特征组合(eigen portfolio)」,把它们当作统计风险因子,与第 7 章的 Fama-French 显式因子做对比。
本节摘要:本节进入无监督学习,从最经典的线性降维——主成分分析(PCA)开始。PCA 不需要标签,它能从资产收益矩阵中「凭空」抽出几个隐性因子,这些因子对应着市场里无法直接观察的系统性风险源。本节讲清四件事:PCA 的数学动机(找到方差最大的方向)、它与 SVD 的关系、为什么必须先做 winsorize 与标准化;如何用 sklearn 的
PCA把 350 只美股的日收益压成几个主成分,并用explained_variance_ratio_判断该留几个;以及如何用主成分构造「特征组合(eigen portfolio)」,把它们当作统计风险因子,与第 7 章的 Fama-French 显式因子做对比。读完本节,你能用纯数据驱动的方式提取一组正交的风险因子,理解为什么「统计因子」是「显式因子」的补充而非替代。
内容来源:原项目
13_unsupervised_learning/01_linear_dimensionality_reduction/03_pca_and_risk_factor_models.ipynb,汉化并套用体系化模板。
⚠️ 学习提示:PCA 的核心假设之一是「数据近似正态」,而金融收益有肥尾和偏态。PCA 在风险因子提取上仍有用,但别把它的输出当成精确的因果归因——它是描述性工具,不是因果工具。
阅读完本节,你应当能够:
explained_variance_ratio_ 与 scree plot 判断保留几个主成分。数据集的维度越高,样本之间的平均距离越大,特征空间的密度呈指数下降——这就是维度灾难(curse of dimensionality)。对机器学习直接后果是:预测变难,过拟合变易。
降维的两大类方法:线性(PCA、ICA)与非线性(流形学习,见下一节)。PCA 是最基础也最常用的线性降维。
PCA 找原始特征的线性组合作主成分,要求:
几何上,PCA 等于在数据云里找一组互相垂直的轴,第一根轴沿着数据最「长」的方向,第二根轴垂直于第一根且次长,以此类推。代数上,这等价于对协方差矩阵做特征值分解,或对中心化后的数据做奇异值分解(SVD)。
| 概念 | 含义 |
|---|---|
| 主成分 | 原始特征的线性组合,构成新的正交基 |
| 载荷(loading) | 每个主成分在各原始特征上的权重 |
| 得分(score) | 每个样本在每个主成分上的投影值 |
| 解释方差比 | 该主成分方差占总方差的比例 |
💡 核心心法:PCA 的目标不是「预测」,而是「换坐标系」——把原始的「股价收益」坐标系换成「风险源」坐标系。第一个主成分通常是「市场因子」(所有股票同向),第二个可能是「规模/风格因子」,以此类推。这些因子是数据自己说出来的,不需要你预先指定。
PCA 是一个有强假设的方法,理解这些假设才知道它的局限:
| 假设 | 含义 | 金融数据是否满足 |
|---|---|---|
| 高方差 = 高信噪比 | 方差大的方向更有信息 | 大致成立 |
| 数据标准化 | 各特征方差可比 | 必须 winsorize + scale |
| 线性变换 | 关系是线性的 | 部分违背(非线性存在) |
| 高阶矩不重要 | 只看前两阶矩(均值、方差) | 违背(收益有肥尾、偏态) |
正态性假设是 PCA 最大的软肋——金融收益的非高斯性(黑天鹅、波动率聚集)意味着 PCA 会把这些高阶结构当噪声丢掉。但实践中,只要记得「PCA 给的是描述性近似」,它仍是极具价值的工具。
notebook 用 Quandl 的 2010-2018 日度数据,选市值最大的 500 只股票(实际有 351 只数据完整),算日收益:
idx = pd.IndexSlice with pd.HDFStore('../../data/assets.h5') as store: stocks = store['us_equities/stocks'].marketcap.nlargest(500) returns = (store['quandl/wiki/prices'] .loc[idx['2010': '2018', stocks.index], 'adj_close'] .unstack('ticker') .pct_change())
PCA 对异常值极度敏感(一个 10σ 的极端收益会主导主成分方向),所以必须先 winsorize 把极端值压回分位区间:
returns = returns.clip(lower=returns.quantile(q=.025), upper=returns.quantile(q=.975), axis=1)
这里把每只票的收益截断到 2.5% 和 97.5% 分位数——不是删除,而是「压回」分位边界。这是金融 PCA 的标准预处理,sklearn 还有专门的 PCA 默认不做标准化,记得手动做。
from sklearn.decomposition import PCA pca = PCA(n_components=10) pca.fit(returns)
explained_variance_ratio_ 给出每个主成分的解释方差占比。在美股上,通常第一个主成分(市场因子)就解释 30%~40% 的方差,前三四个加起来能解释一半多——再往后边际收益急剧下降。用 scree plot(主成分数 vs 累计解释方差)能直观看出该在哪个膝盖处截断。
| 主成分 | 典型解释 | 经验含义 |
|---|---|---|
| PC1 | 30%~40% | 市场因子(所有票同向) |
| PC2 | 5%~10% | 规模/风格因子 |
| PC3-PC5 | 各 2%~5% | 行业/动量等次要因子 |
| 更高 | <2% | 多为噪声 |
PCA 的载荷矩阵的每一列,就是一个主成分在所有股票上的权重。把这个权重当作「组合权重」,就得到一个特征组合(eigen portfolio)——它是该主成分的可投资表达。
# 载荷归一化为组合权重 weights = pca.components_.T / pca.components_.sum(axis=1) # 让权重和为 1
特征组合的收益序列就是该主成分的得分,可以当作「统计风险因子」,与第 7 章 Fama-French 的显式因子(MKT、SMB、HML)做对比:
两者互补:显式因子有金融含义但可能遗漏结构,统计因子覆盖全面但经济含义模糊。实务里常把它们一起放进风险模型,互相校验。
⚠️ 特征组合 ≠ 可投资组合:特征组合的权重常有正有负(多空组合),且忽略交易成本与流动性。它作为「风险因子代理」有意义,直接照抄去交易则未必可行——这点和「Fama-French 因子组合」类似,因子模型与可交易策略是两回事。
下一节,我们看 t-SNE 与 UMAP 资产流形——用非线性流形学习方法,把高维资产收益降到 2 维做可视化,看资产的聚类结构。