1. 这节究竟解决什么实际问题?¶
5.7 协方差矩阵估计:Ledoit-Wolf 收缩法 的具体任务是:用 Ledoit-Wolf 收缩缓解小样本协方差矩阵的不稳定。 本节将明确输入数据、计算过程、输出及其在后续研究中的用途。
2. 前置知识¶
理解收益率、协方差、波动率和矩阵的基本含义。 对公式的理解应包括变量定义、单位、时间索引和适用条件。
3. 数据说明¶
固定多资产价格样本用于演示;不把少量资产、单一时期的最优权重当作配置建议。 运行前先检查 shape、日期范围、列名与缺失值。数据看起来能画图,不代表它适合回答研究问题。
4. 学习目标与完成标准¶
完成本节后,你应能用自己的话解释 5.7 协方差矩阵估计:Ledoit-Wolf 收缩法 的输入、计算步骤、输出和局限;尤其能说明:用 Ledoit-Wolf 收缩缓解小样本协方差矩阵的不稳定。 你还应能独立改动一个参数并解释结果为什么变化,指出至少一个会让结论失真的假设。
5. 核心概念与公式¶
组合配置同时考虑单项资产风险和资产之间的协方差,目标是控制整体风险暴露。
组合收益是权重加权和;风险由协方差矩阵决定,权重之和、杠杆和做空限制必须写清楚。 看到公式时依次确认:每个符号的单位是什么?它属于哪个时点?分母会不会为零?它是描述性统计量、预测量,还是交易规则?
6. 从零实现¶
原始代码按照“准备输入 → 计算中间量 → 得到结果 → 解释输出”的顺序组织。每个单元应检查变量类型、索引、维度和代表性数值。中间变量用于核对公式实现和定位计算错误。
7. 成熟库实现¶
优化器可以求满足约束的数值解;它不会告诉你输入的预期收益是否可信。 使用库函数前先阅读参数含义、默认值和返回对象;库输出一个数字,并不说明这个数字适合你的交易假设。
8. 两种实现的差异¶
从零实现便于核对公式、调试和识别隐含假设;成熟库适合在计算逻辑已验证后复用。两种实现依赖相同的数据口径与时点假设,使用库函数不会改变输入数据的质量。
9. 预期结果与检查范围¶
你应看到维度正确的 Series/DataFrame、日期单调递增的索引,以及能支持“用 Ledoit-Wolf 收缩缓解小样本协方差矩阵的不稳定。”这一任务的表格或图形。金融日收益率均值通常接近 0;若出现极大的连续收益、空表、全 NaN 或索引错位,应先排查数据和对齐逻辑,而不是立即相信结果。
10. 常见错误与诊断¶
协方差矩阵不可逆、权重未归一化、用样本内最优权重宣称可投资、忽略再平衡成本。
诊断顺序:先打印类型与 shape,再看 head()/tail(),接着检查日期和 NaN,最后才比较数值。这样能避免在错误的对象上反复改参数。
11. 研究偏差检查¶
均值估计噪声极大;需要样本外比较、参数敏感性和等权等简单基线。 结果至少应与一个简单基线比较,并明确哪些部分只是教学演示。
12. 三层练习与答案¶
- 基础练习:验证一个中间变量、补全一段小计算,并用一句话解释输出。
- 研究练习:改变窗口、样本区间、约束或标的,记录哪些结论仍成立。
- 开放项目:把本节方法嵌入模块项目,报告基线、失败结果和限制。
题目在 ../exercises/05_portfolio/07_covariance_estimation_exercises.ipynb;完整推导、可运行参考实现与结果检查在 ../solutions/05_portfolio/07_covariance_estimation_solutions.ipynb。请先独立作答,再打开答案。
13. 延伸阅读¶
延伸材料:Portfolio Selection(Markowitz, 1952)。阅读记录应包括研究假设、数据频率、样本范围和结论适用条件。
14. 下一节¶
下一节是 08_dynamic_asset_allocation。本节的概念会成为理解它的输入,而不是孤立的名词。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.covariance import LedoitWolf, EmpiricalCovariance
np.random.seed(42)
print('Libraries loaded')
Libraries loaded
import matplotlib.pyplot as plt
# 1. 设置系统自带的中文字体(这里使用黑体 SimHei)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 如果你想用微软雅黑,可以改成 ['Microsoft YaHei']
# 2. 解决更换字体后,负号(-)显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
1. 样本协方差矩阵的缺陷¶
当股票数量 N 接近或超过历史数据行数 T 时,样本协方差矩阵会出现严重问题:
- 矩阵估计噪音大:历史有限,样本协方差包含大量估计误差
- 条件数极大:矩阵几乎奇异,求逆不稳定
- Markowitz 优化放大误差:优化器会过度利用噪音,产生极端权重
这就是马科维茨优化被称为 "误差放大器" (Error Maximizer) 的原因。
# 演示:T/N 比例对协方差估计质量的影响
N = 50 # 股票数量
T = 100 # 历史数据行数 (T/N = 2)
# 模拟真实协方差结构
true_vols = np.random.uniform(0.1, 0.3, N) / np.sqrt(252) # 日波动率
true_corr = np.eye(N)
true_corr[0:10, 0:10] = 0.6 # 前10只股票高度相关(同一板块)
np.fill_diagonal(true_corr, 1.0)
true_cov = np.outer(true_vols, true_vols) * true_corr
# 从真实协方差生成模拟收益率
returns = np.random.multivariate_normal(np.zeros(N), true_cov, T)
# 样本协方差矩阵
sample_cov = np.cov(returns.T)
# 误差:Frobenius 范数
error = np.linalg.norm(sample_cov - true_cov, 'fro')
print(f'样本协方差矩阵 Frobenius 误差: {error:.4f}')
print(f'矩阵条件数(越大越不稳定): {np.linalg.cond(sample_cov):.1f}')
样本协方差矩阵 Frobenius 误差: 0.0008 矩阵条件数(越大越不稳定): 158.5
2. Ledoit-Wolf 收缩估计¶
Ledoit-Wolf(2004) 提出了最优线性收缩估计器:
$$\hat{\Sigma}_{LW} = (1-\alpha) \hat{\Sigma}_{sample} + \alpha \cdot \mu I$$
- $\alpha$ 是最优收缩系数(自动计算)
- $\mu I$ 是目标矩阵(单位矩阵乘以平均特征值)
收缩有效地将极端的特征值拉向均值,使矩阵更接近真实分布,更适合优化器使用。
# Ledoit-Wolf 收缩估计
lw = LedoitWolf()
lw.fit(returns)
lw_cov = lw.covariance_
error_lw = np.linalg.norm(lw_cov - true_cov, 'fro')
print(f'Ledoit-Wolf 协方差矩阵 Frobenius 误差: {error_lw:.4f}')
print(f' vs 样本协方差误差: {error:.4f}')
print(f'LW 减少误差: {(error - error_lw)/error:.2%}')
print(f'\n收缩系数 alpha: {lw.shrinkage_:.4f}')
print(f'LW 矩阵条件数: {np.linalg.cond(lw_cov):.1f} (远比样本协方差小)')
# 可视化:特征值分布对比
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
for ax, cov_mat, title in zip(axes,
[true_cov, sample_cov, lw_cov],
['真实协方差', '样本协方差(噪音大)', 'Ledoit-Wolf 收缩']):
eigvals = np.linalg.eigvalsh(cov_mat)
ax.hist(eigvals, bins=30, color='steelblue', alpha=0.7, edgecolor='white')
ax.set_title(f'{title}')
ax.set_xlabel('特征值大小')
ax.set_ylabel('频率')
ax.grid(alpha=0.3)
plt.suptitle('特征值分布对比:收缩后更集中(减少极端值)', fontsize=12)
plt.tight_layout()
plt.show()
Ledoit-Wolf 协方差矩阵 Frobenius 误差: 0.0008 vs 样本协方差误差: 0.0008 LW 减少误差: 4.97% 收缩系数 alpha: 0.3723 LW 矩阵条件数: 11.5 (远比样本协方差小)
练习¶
- 将股票数量 N 改为 100,保持 T=100(T/N=1),观察样本协方差矩阵的条件数如何爆炸。
- 使用两种协方差矩阵(样本 vs Ledoit-Wolf)分别运行最小方差优化(
scipy.optimize.minimize),对比权重向量的差异。 - 查阅
sklearn的OAS(Oracle Approximating Shrinkage)估计器,对比其与 Ledoit-Wolf 的误差。
下一节 → ../06_ml_trading/04_dangers_of_overfitting.ipynb