跳到主内容
研究主线因子策略、对冲与尾部风险 · 第37–42讲6/6模块导览 →
讲义

第42讲:风险价值和条件风险价值 (VaR and CVaR)

统一以正损失金额定义 VaR 与 CVaR,比较正态法和历史法,演示滚动估计并说明尾部与样本限制。

完成状态保存在当前浏览器,可随时取消。

一、核心概念解析#

VaR(风险价值):在给定置信水平 α 和持有期下,损失分布的 α 分位数。本文统一把 VaR 报告为正的损失金额。例如 95% VaR 为 10 万元,表示在模型和历史分布假设下,损失不超过 10 万元的概率为 95%。

CVaR(条件风险价值):当损失超过VaR时,这些极端损失的平均值。反映尾部风险,比VaR更能体现危机情境。

关键公式对比#

正态分布VaR计算公式:

VaRα=(μ+σz1α)V\text{VaR}_\alpha = -(\mu + \sigma z_{1-\alpha})V

其中:

  • μ\mu 为期望收益率

  • σ\sigma 为波动率

  • z1αz_{1-\alpha} 为标准正态分布的左尾分位数

  • VV 为投资组合价值

历史模拟法VaR计算公式:

VaRα=Percentile(R,1α)V\text{VaR}_\alpha = -\text{Percentile}(R, 1-\alpha) \cdot V

其中:

  • RR 为历史收益率序列

  • α\alpha 为置信水平

条件风险价值(CVaR)计算公式:

CVaRα=E[RRq1α]V\text{CVaR}_\alpha = -E[R \mid R \le q_{1-\alpha}]V

其中:

  • q1αq_{1-\alpha} 为收益率分布的左尾分位数

  • RR 为组合收益率

  • α\alpha为置信水平

二、模拟数据实战#

生成模拟收益率#

code
import numpy as np
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
from scipy.stats import norm

# 生成10个正态分布的虚拟资产收益率
np.random.seed(42)
returns = np.random.normal(0.01, 0.1, (1000, 10))
returns = pd.DataFrame(returns, columns=[f'Asset_{i}' for i in range(10)])

权重设置与可视化#

code
# 生成等权重组合
weights = np.ones(10) / 10

plt.figure(figsize=(10,4))
plt.bar(range(10), weights)
plt.title('等权重投资组合分配')
plt.xlabel('资产编号')
plt.ylabel('权重比例');

计算历史VaR#

code
def historical_var(returns, weights, alpha=0.95, value=1e6):
    port_returns = returns.dot(weights)
    var = -np.percentile(port_returns, 100*(1-alpha)) * value
    return var

print(f"95% VaR: {historical_var(returns, weights):,.2f} 元")

输出示例:95% VaR: 42,567.89 元

三、真实市场数据分析#

获取历史数据#

code
# 获取苹果、微软历史数据
tickers = ['AAPL', 'MSFT']
data = yf.download(
    tickers, start='2015-01-01', end='2020-01-01',
    auto_adjust=True, group_by='column', multi_level_index=True,
)['Close']

# 计算收益率
returns = data.pct_change().dropna()
returns.plot.hist(bins=50, alpha=0.6, figsize=(10,4))
plt.title('苹果与微软历史收益率分布');

动态权重VaR分析#

code
# 生成随机权重
np.random.seed(42)
weights = np.random.random(len(tickers))
weights /= weights.sum()

# 先得到组合收益,再在一维序列上计算滚动 VaR
window = 252  # 1年交易天数
portfolio_returns = returns @ weights
var_series = -portfolio_returns.rolling(window).quantile(0.05) * 1e6

plt.figure(figsize=(10,4))
var_series.plot()
plt.title('滚动一年期95% VaR')
plt.ylabel('风险价值(元)');

四、进阶对比分析#

正态假设 vs 历史法#

code
def normal_var(mu, sigma, alpha=0.95, value=1e6):
    return -norm.ppf(1-alpha, loc=mu, scale=sigma) * value

mu = returns.mean().dot(weights)
sigma = np.sqrt(weights.T @ returns.cov() @ weights)

print(f"正态法VaR: {normal_var(mu, sigma):,.2f} 元")
print(f"历史法VaR: {historical_var(returns, weights):,.2f} 元")

CVaR计算实现#

code
def conditional_var(returns, weights, alpha=0.95, value=1e6):
    port_returns = returns.dot(weights)
    var = np.percentile(port_returns, 100*(1-alpha))
    cvar = -port_returns[port_returns <= var].mean() * value
    return cvar

print(f"CVaR: {conditional_var(returns, weights):,.2f} 元")

五、关键要点总结#

  1. 正态假设常低估尾部风险(见下图对比)

  2. 历史法依赖数据质量,需定期更新

  3. CVaR比VaR更全面反映尾部风险

  4. 回看周期需平衡时效性与稳定性

code
# 分布对比可视化
plt.figure(figsize=(10,4))
plt.hist(returns.dot(weights), bins=50, density=True, alpha=0.6)
x = np.linspace(-0.1, 0.1, 100)
plt.plot(x, norm.pdf(x, mu, sigma), 'r-')
plt.legend(['正态分布', '实际收益'])
plt.title('收益分布对比');

六、练习题#

  1. 使用yfinance获取标普500指数(^GSPC)过去5年数据,计算其95% VaR

  2. 比较等权重组合与70%股票+30%债券组合的CVaR差异

  3. 当置信水平从95%提升到99%时,VaR和CVaR变化幅度有何不同?为什么?

提示:债券数据可使用TLT(20年以上美国国债ETF)