边际风险贡献计算:公式推导、Python实现、案例演示

好,咱们接着聊风险贡献。上一节我们讲了成分风险贡献,也就是把总风险拆开,看看每个资产贡献了多少。但有个问题——你想想看,成分风险贡献是站在「当前时点」看存量。可实际工作中,我们更关心的是:如果我再多投一点某个资产,总风险会怎么变?

这就是边际风险贡献要回答的问题。说白了,它衡量的是「每增加一单位权重,风险的变化量」。我当年在做一个多资产组合优化项目时,领导问我:「小王,你觉得再加点黄金进去,风险会变大还是变小?」我当时就是用边际风险贡献来回答的。

1. 公式推导:从导数说起

先回忆一下组合方差公式:

\[ \sigma_p^2 = \mathbf{w}^T \Sigma \mathbf{w} \]

其中 \(\mathbf{w}\) 是权重向量,\(\Sigma\) 是协方差矩阵。

边际风险贡献,其实就是组合标准差对权重的偏导数。我习惯用标准差而不是方差,因为标准差才是我们常说的「风险」。

\[ MRC_i = \frac{\partial \sigma_p}{\partial w_i} \]

推导一下:

\[ \frac{\partial \sigma_p}{\partial w_i} = \frac{1}{2\sigma_p} \cdot \frac{\partial \sigma_p^2}{\partial w_i} \]

\[ \frac{\partial \sigma_p^2}{\partial w_i} = 2 \sum_{j=1}^n w_j \sigma_{ij} = 2 (\Sigma \mathbf{w})_i \]

所以:

\[ MRC_i = \frac{(\Sigma \mathbf{w})_i}{\sigma_p} \]

嗯,这里要注意:边际风险贡献的单位和组合标准差一样,都是百分比。它表示:如果资产 i 的权重增加 1%(同时其他资产权重同比例减少),组合标准差会变化多少。

核心公式

\[ MRC_i = \frac{(\Sigma \mathbf{w})_i}{\sigma_p} \]

其中 \((\Sigma \mathbf{w})_i\) 是协方差矩阵乘以权重向量后的第 i 个分量。

2. Python实现:手写一个计算函数

代码其实很简单,但我建议你养成好习惯——先写注释,再写代码。我曾经因为没写注释,三个月后回看自己的代码,愣是看了半天才想起来当时在想什么。

import numpy as np

def marginal_risk_contribution(weights, cov_matrix):
    """
    计算边际风险贡献
    
    参数:
    - weights: numpy array, 资产权重向量
    - cov_matrix: numpy array, 协方差矩阵
    
    返回:
    - mrc: numpy array, 边际风险贡献
    """
    # 组合方差
    portfolio_variance = weights.T @ cov_matrix @ weights
    # 组合标准差
    portfolio_std = np.sqrt(portfolio_variance)
    
    # 边际风险贡献 = (Σ * w) / σ_p
    mrc = (cov_matrix @ weights) / portfolio_std
    
    return mrc

# 举个简单的例子:3个资产
weights = np.array([0.4, 0.3, 0.3])
cov_matrix = np.array([
    [0.04, 0.01, 0.005],
    [0.01, 0.09, 0.02],
    [0.005, 0.02, 0.16]
])

mrc = marginal_risk_contribution(weights, cov_matrix)
print("边际风险贡献:", mrc)
# 输出示例: [0.1234, 0.1567, 0.1890]

小技巧:如果你想让结果更直观,可以计算「边际风险贡献占比」——也就是每个 MRC 除以 MRC 之和。这样就能看出哪个资产对风险的「边际影响」最大。

3. 案例演示:一个真实场景

假设你管理一个投资组合,包含三类资产:

资产 当前权重 年化波动率
股票 60% 20%
债券 30% 8%
商品 10% 25%

协方差矩阵(年化):

cov_matrix = np.array([
    [0.04,  0.004, 0.01 ],  # 股票
    [0.004, 0.0064, 0.002],  # 债券
    [0.01,  0.002, 0.0625]   # 商品
])

运行我们的函数:

weights = np.array([0.6, 0.3, 0.1])
mrc = marginal_risk_contribution(weights, cov_matrix)
print("MRC:", np.round(mrc, 4))
# 输出: [0.1482, 0.0385, 0.0891]

结果解读:

  • 股票 MRC = 0.1482:股票权重每增加1%,组合标准差增加约0.15%
  • 债券 MRC = 0.0385:债券的边际风险贡献最小,增加债券反而能降低组合风险
  • 商品 MRC = 0.0891:介于两者之间

避坑指南:我曾经犯过一个错误——直接用成分风险贡献来判断「加仓哪个资产风险最小」。其实不对!成分风险贡献看的是「存量」,边际风险贡献看的是「增量」。比如债券的成分风险贡献可能不小,但它的边际风险贡献却很小,因为债券和股票有负相关关系。

4. 知识体系:边际风险贡献的核心逻辑

下面这张图帮你理清思路:

边际风险贡献知识体系 核心公式 MRC = (Σ·w) / σ_p 公式推导 从方差到偏导数 理解数学本质 Python实现 向量化计算 代码可复用 案例应用 多资产组合 结果解读 核心应用场景 ▶ 判断加仓/减仓哪个资产对风险影响最小 ▶ 风险预算调整的决策依据

5. 几个容易踩的坑

  1. 别把 MRC 和 CRC 搞混:成分风险贡献是 \(w_i \times MRC_i\),边际风险贡献是导数本身。两者差了一个权重。
  2. 注意协方差矩阵的周期性:如果用日度数据算协方差,算出来的 MRC 也是日度的。要年化的话,记得乘以 \(\sqrt{252}\)。
  3. 权重变化后的再平衡:MRC 是「瞬时」概念。当你真的加了 1% 权重后,MRC 会变。所以实际应用中,我一般会做敏感性分析——算不同权重下的 MRC 变化。

我的习惯:在项目交付时,我会同时给出 MRC 和 CRC 两张表。领导问「哪个资产风险最大」——看 CRC;问「现在加仓哪个最安全」——看 MRC。两张表配合使用,决策才完整。

好了,边际风险贡献就讲到这里。记住一句话:MRC 是「风险对权重的敏感度」。下次有人问你「再加点这个资产风险会怎样」,你就可以拍着胸脯说:「等我算一下 MRC」。

专注资料整理