第2章:风险度量基础——波动率、协方差矩阵、VaR与CVaR

做量化投资,说白了就是跟风险打交道。我刚开始入行那会儿,带我的老交易员跟我说过一句话,我一直记到现在——「你赚的钱,其实都是你承担风险的补偿」。所以,怎么度量风险,就成了咱们这行的基本功。

这一章,咱们就把几个最核心的风险度量指标掰开揉碎了讲清楚。波动率、协方差矩阵、VaR、CVaR,这些概念你肯定听过,但真正在实战中怎么算、怎么用,里面有不少坑。

风险度量知识体系 风险度量基础 波动率 (Volatility) 协方差矩阵 VaR / CVaR 核心应用 衡量资产价格波动幅度 年化/日化波动率计算 核心应用 多资产相关性分析 投资组合风险分解 核心应用 最大可能损失估计 尾部风险度量 三者层层递进:从单资产 → 多资产 → 极端损失

2.1 波动率:风险的「体温计」

波动率,英文叫Volatility,是衡量资产价格变动幅度的指标。你想想看,一个股票一天涨跌0.5%,另一个一天能涨跌5%,哪个风险大?显然是后者。波动率就是量化这个「蹦跶程度」的。

我个人习惯用对数收益率来计算波动率,而不是简单收益率。为什么?因为对数收益率在时间上可加,而且更符合正态分布的假设。嗯,这里要注意——实际收益率并不完全服从正态分布,尾部更厚,但这是后话了。

核心公式:
日波动率 σ = std(ln(Pt / Pt-1))
年化波动率 σ = σ × √252

252是A股一年的实际交易天数。美股用252,港股用247左右。我在项目中遇到过有人直接用365,结果年化波动率算出来虚高不少,回测绩效看着很差,其实是被这个细节坑了。

import numpy as np
import pandas as pd

def calc_volatility(price_series, annual_factor=252):
    """
    计算年化波动率
    price_series: 价格序列,pandas Series
    """
    log_returns = np.log(price_series / price_series.shift(1))
    # 去掉NaN
    log_returns = log_returns.dropna()
    daily_vol = np.std(log_returns)
    annual_vol = daily_vol * np.sqrt(annual_factor)
    return annual_vol

# 举个实际例子
prices = pd.Series([100, 102, 101, 105, 103, 107, 106])
vol = calc_volatility(prices)
print(f"年化波动率: {vol:.4f}")
实战小技巧: 计算波动率时,窗口期的选择很关键。我一般用60个交易日(约3个月)作为滚动窗口。太短了噪声大,太长了反应迟钝。做高频策略时,我会用20天窗口。

2.2 协方差矩阵:多资产之间的「关系网」

单看一个资产的波动率,其实不够。你想想看,如果你同时持有茅台和五粮液,它们俩的走势往往是同向的——白酒板块一涨都涨。这时候组合的风险就不是简单相加了。

协方差矩阵,就是用来描述多个资产之间联动关系的工具。矩阵的对角线是各资产的方差(波动率的平方),非对角线是资产两两之间的协方差。

协方差矩阵结构(以3个资产为例):
Var(资产1)Cov(1,2)Cov(1,3)
Cov(2,1)Var(资产2)Cov(2,3)
Cov(3,1)Cov(3,2)Var(资产3)

协方差的值受量纲影响很大,所以实战中我更常用相关系数矩阵。相关系数其实就是标准化后的协方差,取值在-1到1之间,直观多了。

def calc_cov_matrix(returns_df):
    """
    计算协方差矩阵
    returns_df: 各资产收益率DataFrame,每列一个资产
    """
    cov_matrix = returns_df.cov()
    # 年化处理
    annual_cov = cov_matrix * 252
    return annual_cov

# 假设我们有3只股票的日收益率数据
import pandas as pd
data = {
    '茅台': [0.01, -0.005, 0.02, -0.01, 0.015],
    '五粮液': [0.008, -0.003, 0.018, -0.008, 0.012],
    '招商银行': [0.005, 0.002, -0.003, 0.006, -0.002]
}
returns_df = pd.DataFrame(data)
cov_mat = calc_cov_matrix(returns_df)
print(cov_mat)
⚠️ 我曾经踩过的坑: 协方差矩阵必须是半正定的,否则在后续做优化时会出现奇异解。如果数据量太少(比如资产数 > 时间序列长度),矩阵就会「病态」。我建议至少要有2倍于资产数量的观测值。实在不行,可以用收缩估计(Shrinkage)方法来修正。

2.3 VaR:在险价值——「最坏情况下亏多少」

VaR,全称Value at Risk。这个概念在90年代由J.P. Morgan推广开来,现在已经是金融风控的标配了。说白了就是:在给定的置信水平和持有期内,你的投资组合最多可能亏多少钱。

举个例子:95%置信水平下,日VaR为100万。意思是——在100天里,大概有5天亏损会超过100万。注意,它没说超过多少,只说「至少亏100万」。

VaR的三种计算方法:
  1. 参数法(方差-协方差法): 假设收益率服从正态分布,直接用均值和标准差算。
  2. 历史模拟法: 直接用过去N天的收益率排序,取第(1-置信水平)分位数。
  3. 蒙特卡洛模拟法: 假设一个随机过程,模拟出大量路径,再取分位数。

我个人最常用的是历史模拟法。为什么?因为它不需要假设分布形态,简单粗暴,而且监管也认可。参数法虽然计算快,但遇到极端行情(比如2020年3月)就完全失效了——正态分布假设在尾部根本不成立。

def historical_var(returns, confidence_level=0.95):
    """
    历史模拟法计算VaR
    returns: 收益率序列
    confidence_level: 置信水平,默认95%
    """
    sorted_returns = np.sort(returns)
    index = int((1 - confidence_level) * len(sorted_returns))
    var = -sorted_returns[index]  # 取正值表示损失
    return var

# 示例
np.random.seed(42)
returns = np.random.normal(0.001, 0.02, 1000)  # 模拟1000个日收益率
var_95 = historical_var(returns, 0.95)
var_99 = historical_var(returns, 0.99)
print(f"95% VaR: {var_95:.4f}")
print(f"99% VaR: {var_99:.4f}")
实战经验: 做VaR时,样本窗口选多长很讲究。我一般用250个交易日(1年)。太短了,样本不够;太长了,市场结构可能已经变了。另外,记得定期回测VaR的准确性——如果实际亏损超过VaR的次数明显多于理论值,说明模型该调整了。

2.4 CVaR:条件在险价值——「亏钱时的平均亏损」

VaR有个明显的缺陷:它只告诉你「会亏超过某个值」,但没告诉你「一旦亏了,平均亏多少」。举个例子,95% VaR是100万,那剩下的5%极端情况,可能是亏101万,也可能是亏1000万。这两种情况的风险完全不一样,但VaR给出的数字是一样的。

CVaR(Conditional VaR),也叫Expected Shortfall,就是来解决这个问题的。它计算的是「超过VaR的那些损失的平均值」。说白了就是:在那些最倒霉的日子里,你平均亏多少钱。

CVaR公式:
CVaRα = E[ -R | -R > VaRα ]
其中R是收益率,α是置信水平。
def historical_cvar(returns, confidence_level=0.95):
    """
    历史模拟法计算CVaR
    """
    sorted_returns = np.sort(returns)
    index = int((1 - confidence_level) * len(sorted_returns))
    # 取所有超过VaR的损失
    tail_losses = -sorted_returns[:index]
    cvar = np.mean(tail_losses)
    return cvar

# 接上面的例子
cvar_95 = historical_cvar(returns, 0.95)
print(f"95% CVaR: {cvar_95:.4f}")
⚠️ 注意: CVaR在数学上具有「次可加性」,这是VaR不具备的。什么意思?就是组合的CVaR不会大于各资产CVaR的加权和。这个性质在做投资组合优化时特别重要。我建议在做风险预算时,优先用CVaR而不是VaR作为约束条件。

2.5 四个指标怎么选?我的实战建议

指标 适用场景 优点 缺点
波动率 日常风控、仓位管理 计算简单,直观 只反映波动幅度,不区分方向
协方差矩阵 多资产组合、风险分解 刻画资产间关系 高维时不稳定
VaR 监管报告、止损线设定 监管认可,易于理解 忽略尾部风险
CVaR 极端风险控制、优化目标 考虑尾部风险,数学性质好 计算量稍大

我个人习惯的组合是:日常监控用波动率,做组合优化用协方差矩阵+CVaR,给老板汇报用VaR。你想想看,老板只想知道「最多亏多少」,VaR就够了。但真正做策略时,CVaR才能帮你躲过那些「黑天鹅」。

最后说一句: 这些指标都是基于历史数据的,而历史不一定会重演。我见过太多人把VaR模型跑得漂漂亮亮,结果一次市场结构突变就爆仓了。风险度量是工具,不是护身符。永远要对市场保持敬畏。

公众号:蓝海资料掘金营,微信deep3321