1. 这节究竟解决什么实际问题?¶
5.2 风险平价策略 (Risk Parity) 的具体任务是:让各资产贡献相近风险,而不是简单平均资金权重。 本节将明确输入数据、计算过程、输出及其在后续研究中的用途。
2. 前置知识¶
理解收益率、协方差、波动率和矩阵的基本含义。 对公式的理解应包括变量定义、单位、时间索引和适用条件。
3. 数据说明¶
固定多资产价格样本用于演示;不把少量资产、单一时期的最优权重当作配置建议。 运行前先检查 shape、日期范围、列名与缺失值。数据看起来能画图,不代表它适合回答研究问题。
4. 学习目标与完成标准¶
完成本节后,你应能用自己的话解释 5.2 风险平价策略 (Risk Parity) 的输入、计算步骤、输出和局限;尤其能说明:让各资产贡献相近风险,而不是简单平均资金权重。 你还应能独立改动一个参数并解释结果为什么变化,指出至少一个会让结论失真的假设。
5. 核心概念与公式¶
组合配置同时考虑单项资产风险和资产之间的协方差,目标是控制整体风险暴露。
组合收益是权重加权和;风险由协方差矩阵决定,权重之和、杠杆和做空限制必须写清楚。 看到公式时依次确认:每个符号的单位是什么?它属于哪个时点?分母会不会为零?它是描述性统计量、预测量,还是交易规则?
6. 从零实现¶
原始代码按照“准备输入 → 计算中间量 → 得到结果 → 解释输出”的顺序组织。每个单元应检查变量类型、索引、维度和代表性数值。中间变量用于核对公式实现和定位计算错误。
7. 成熟库实现¶
优化器可以求满足约束的数值解;它不会告诉你输入的预期收益是否可信。 使用库函数前先阅读参数含义、默认值和返回对象;库输出一个数字,并不说明这个数字适合你的交易假设。
8. 两种实现的差异¶
从零实现便于核对公式、调试和识别隐含假设;成熟库适合在计算逻辑已验证后复用。两种实现依赖相同的数据口径与时点假设,使用库函数不会改变输入数据的质量。
9. 预期结果与检查范围¶
你应看到维度正确的 Series/DataFrame、日期单调递增的索引,以及能支持“让各资产贡献相近风险,而不是简单平均资金权重。”这一任务的表格或图形。金融日收益率均值通常接近 0;若出现极大的连续收益、空表、全 NaN 或索引错位,应先排查数据和对齐逻辑,而不是立即相信结果。
10. 常见错误与诊断¶
协方差矩阵不可逆、权重未归一化、用样本内最优权重宣称可投资、忽略再平衡成本。
诊断顺序:先打印类型与 shape,再看 head()/tail(),接着检查日期和 NaN,最后才比较数值。这样能避免在错误的对象上反复改参数。
11. 研究偏差检查¶
均值估计噪声极大;需要样本外比较、参数敏感性和等权等简单基线。 结果至少应与一个简单基线比较,并明确哪些部分只是教学演示。
12. 三层练习与答案¶
- 基础练习:验证一个中间变量、补全一段小计算,并用一句话解释输出。
- 研究练习:改变窗口、样本区间、约束或标的,记录哪些结论仍成立。
- 开放项目:把本节方法嵌入模块项目,报告基线、失败结果和限制。
题目在 ../exercises/05_portfolio/02_risk_parity_exercises.ipynb;完整推导、可运行参考实现与结果检查在 ../solutions/05_portfolio/02_risk_parity_solutions.ipynb。请先独立作答,再打开答案。
13. 延伸阅读¶
延伸材料:Portfolio Selection(Markowitz, 1952)。阅读记录应包括研究假设、数据频率、样本范围和结论适用条件。
14. 下一节¶
下一节是 03_capm_apt。本节的概念会成为理解它的输入,而不是孤立的名词。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf
from scipy.optimize import minimize
from sklearn.decomposition import PCA
plt.rcParams['figure.figsize'] = (12, 6)
plt.style.use('seaborn-v0_8-muted')
# 多元资产池:构建一个典型的“全天候”风格组合
tickers = ['SPY', 'TLT', 'GLD', 'QQQ', 'VIXY']
labels = ['标普500', '长期美债', '黄金', '纳指100', '恐慌指数']
prices = yf.download(tickers, start='2015-01-01', end='2024-01-01',
progress=False)['Close'].dropna()
returns = prices.pct_change().dropna()
cov = returns.cov() * 252
n = len(tickers)
print('数据准备就绪。')
数据准备就绪。
# 默认使用固定样本,保证课程与 CI 不依赖实时接口。
USE_OFFLINE_DATA = True
if USE_OFFLINE_DATA:
from pathlib import Path
import sys
docs_root = next(parent for parent in [Path.cwd(), *Path.cwd().parents]
if (parent / 'utils' / 'offline_data.py').exists())
sys.path.insert(0, str(docs_root))
from utils.offline_data import configure_yfinance_offline
configure_yfinance_offline(yf)
else:
print('在线下载为扩展步骤;请核对数据字段、时区和下载日期。')
import matplotlib.pyplot as plt
# 1. 设置系统自带的中文字体(这里使用黑体 SimHei)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 如果你想用微软雅黑,可以改成 ['Microsoft YaHei']
# 2. 解决更换字体后,负号(-)显示为方块的问题
plt.rcParams['axes.unicode_minus'] = False
1. 风险贡献:谁在拖后腿?¶
在等权组合中,每个资产买一样多。但因为股票的波动率是债券的 4-5 倍,所以组合 90% 以上的风险其实来自股票。风险平价的目标是让每类资产提供的“波动”是一样多的。
def get_risk_contributions(w, cov):
p_vol = np.sqrt(w @ cov @ w)
mrc = cov @ w / p_vol # 边际风险贡献
trc = w * mrc # 总风险贡献
return trc / trc.sum()
eq_w = np.ones(n) / n
eq_rc = get_risk_contributions(eq_w, cov)
plt.bar(labels, eq_rc, alpha=0.7)
plt.axhline(1/n, color='red', linestyle='--', label='理想持平线')
plt.title("等权组合的资产风险贡献")
plt.legend()
plt.show()
2. 深度普及:主成分风险分析 (PCA Risk)¶
进阶视角: 有时你买了 5 只股票,以为分散了风险。但 PCA 可能会告诉你,这 5 只股票 90% 的波动都来自同一个方向。这就是隐性相关性。
资产层面的风险贡献相近,不代表底层风险因子的贡献也相近;两种口径需要分别计算。
pca = PCA()
pca.fit(returns)
evr = pca.explained_variance_ratio_
plt.bar(range(1, n+1), evr, alpha=0.6, color='purple')
plt.plot(range(1, n+1), np.cumsum(evr), marker='o', color='red')
plt.title("组合风险的隐性构成:前两个主成分解释了绝大部分波动")
plt.xlabel("主成分编号")
plt.ylabel("解释方差比例")
plt.show()
print(f"结论:虽然我们有 5 类资产,但本质上只有 {np.where(np.cumsum(evr) > 0.9)[0][0] + 1} 个核心力量在驱动组合。")
结论:虽然我们有 5 类资产,但本质上只有 2 个核心力量在驱动组合。
3. 求解风险平价权重¶
我们通过优化,寻找一组权重,使得 (每个资产的风险贡献 - 1/N)^2 的总和最小。
def obj_fun(w, cov):
rc = get_risk_contributions(w, cov)
return np.sum((rc - 1/len(w))**2)
res = minimize(obj_fun, eq_w, args=(cov,),
bounds=[(0.01, 1)]*n, constraints={'type':'eq', 'fun': lambda w: w.sum()-1})
rp_w = res.x
print("--- 风险平价配置方案 ---")
for l, w in zip(labels, rp_w):
print(f"{l:<10}: {w:.2%}")
--- 风险平价配置方案 --- 标普500 : 28.79% 长期美债 : 16.72% 黄金 : 21.64% 纳指100 : 31.85% 恐慌指数 : 1.00%
练习¶
- 极端测试:如果加入一个波动率极大的资产(如比特币),风险平价策略会给它分配多少权重?
- 因子平衡:尝试计算这 5 个资产在第一主成分(PC1)上的暴露,思考如何降低组合对“市场共同下跌”的敏感度。
- 现实调整:风险平价通常会导致组合收益过低,在现实中往往需要配合杠杆使用。思考:如何在不改变风险比例的前提下提升预期收益?
下一模块 → ../06_ml_trading/(我们将学习如何利用机器学习识别复杂的盈利模式)