风险平价模型的数学基础
说实话,很多做量化的人一看到协方差矩阵就头疼。我刚开始做风险平价的时候也一样,觉得这东西太抽象了。但后来我发现,搞懂这几个数学概念,其实就是搞懂了风险平价的核心逻辑。
今天咱们就来聊聊协方差矩阵、波动率、相关系数,还有风险贡献的计算。这些是风险平价模型的基石,绕不开的。
波动率:风险的“尺子”
波动率说白了就是资产价格的“上蹿下跳”程度。我习惯用年化波动率来衡量风险,因为这样不同资产之间才好比较。
计算波动率,最常用的就是标准差公式:
import numpy as np
# 假设我们有某资产的日收益率数据
returns = np.array([0.01, -0.005, 0.02, -0.01, 0.015])
# 计算日波动率(标准差)
daily_vol = np.std(returns, ddof=1)
# 年化波动率(假设252个交易日)
annual_vol = daily_vol * np.sqrt(252)
print(f"日波动率: {daily_vol:.4f}")
print(f"年化波动率: {annual_vol:.4f}")
我的小习惯:计算波动率时,我一般用对数收益率而不是简单收益率。因为对数收益率在时间上可加,而且更符合正态分布假设。这个细节在实盘中挺重要的。
相关系数:资产之间的“默契度”
相关系数衡量的是两个资产之间“同涨同跌”的程度。取值范围在-1到1之间。1表示完全正相关,-1表示完全负相关,0表示没关系。
你想想看,如果两个资产相关系数很高,那分散风险的效果就大打折扣了。我在做风险平价时,最怕遇到的就是“伪分散”——表面上配了很多资产,结果一跌全跌。
# 计算两个资产的相关系数
asset_a = np.array([0.01, -0.005, 0.02, -0.01, 0.015])
asset_b = np.array([0.008, -0.003, 0.015, -0.008, 0.012])
corr_matrix = np.corrcoef(asset_a, asset_b)
print(f"相关系数矩阵:\n{corr_matrix}")
协方差矩阵:风险的全貌
协方差矩阵是波动率和相关系数的“合体版”。它既包含了每个资产自身的波动,也包含了资产之间的联动关系。
我个人觉得,协方差矩阵是风险平价模型里最重要的输入。为什么?因为它决定了你最终的风险分配结果。
| 概念 | 含义 | 计算公式 |
|---|---|---|
| 方差 | 单个资产的风险 | σ² = E[(R - μ)²] |
| 协方差 | 两个资产之间的联动 | Cov(A,B) = E[(R_A - μ_A)(R_B - μ_B)] |
| 相关系数 | 标准化的协方差 | ρ = Cov(A,B) / (σ_A × σ_B) |
# 构建协方差矩阵
cov_matrix = np.cov(asset_a, asset_b)
print(f"协方差矩阵:\n{cov_matrix}")
# 从协方差矩阵提取波动率和相关系数
vols = np.sqrt(np.diag(cov_matrix))
corr = cov_matrix[0,1] / (vols[0] * vols[1])
print(f"资产A波动率: {vols[0]:.4f}")
print(f"资产B波动率: {vols[1]:.4f}")
print(f"相关系数: {corr:.4f}")
我曾经踩过的坑:直接用历史数据算协方差矩阵,结果遇到市场突变,矩阵变得不稳定。后来我改用指数加权移动平均(EWMA)来估计,效果好了很多。记住,历史数据只是参考,不是真理。
风险贡献:拆解风险的“手术刀”
风险平价的核心,就是让每个资产对组合的风险贡献相等。那风险贡献怎么算呢?
假设组合权重为 w,协方差矩阵为 Σ,那么组合的方差就是 wᵀΣw。第 i 个资产的风险贡献(RC)是:
RC_i = w_i × (Σw)_i / √(wᵀΣw)
其中 (Σw)_i 是协方差矩阵乘以权重向量的第 i 个分量
说白了,风险贡献就是“权重 × 边际风险”。边际风险衡量的是:增加一点点这个资产的权重,组合风险会变化多少。
def risk_contribution(weights, cov_matrix):
"""
计算每个资产的风险贡献
"""
portfolio_var = weights @ cov_matrix @ weights
portfolio_vol = np.sqrt(portfolio_var)
# 边际风险
marginal_risk = cov_matrix @ weights / portfolio_vol
# 风险贡献
rc = weights * marginal_risk
return rc / portfolio_vol # 归一化,总和为1
# 示例
weights = np.array([0.5, 0.5])
rc = risk_contribution(weights, cov_matrix)
print(f"资产A风险贡献: {rc[0]:.2%}")
print(f"资产B风险贡献: {rc[1]:.2%}")
核心要点:风险平价的目标就是让所有资产的 RC 相等。如果某个资产的 RC 偏高,说明它承担了过多的风险,需要降低它的权重。
知识体系总览
下面这张图帮你理清这几个概念之间的关系:
避坑指南
最后分享几个我踩过的坑:
- 协方差矩阵奇异:当资产数量大于时间窗口长度时,矩阵不可逆。我一般用收缩估计(Shrinkage)来处理。
- 相关系数不稳定:市场环境变了,相关系数也会变。我建议用滚动窗口重新估计,别用全历史数据。
- 忽略尾部风险:波动率只衡量了“正常”波动,极端情况它管不了。可以结合 VaR 或 CVaR 来补充。
嗯,数学基础就这些。搞懂了协方差矩阵、波动率、相关系数和风险贡献,风险平价模型的门槛就跨过去一半了。剩下的就是怎么优化权重,让风险贡献相等——这个咱们后面再聊。