风险度量基础:波动率、协方差矩阵、VaR、CVaR、最大回撤、风险因子模型
各位同学,欢迎来到风险度量的世界。
说实话,做量化投资这么多年,我最大的体会就是:不懂风险,赚再多钱也是白搭。你想想看,一次黑天鹅事件,可能就把你几年的利润全吞了。所以,这一章我们得把风险度量的基本功打扎实。
1. 波动率:最朴素的“心跳”指标
波动率,说白了就是资产价格上下跳动的幅度。我习惯把它比作一个人的“心跳”——跳得太快,你紧张;跳得太慢,你又担心它是不是挂了。
在金融里,我们通常用年化波动率来衡量。计算方式很简单:
import numpy as np
# 假设我们有日收益率数据
daily_returns = np.array([0.01, -0.02, 0.015, -0.005, 0.008])
# 计算日波动率(标准差)
daily_vol = np.std(daily_returns, ddof=1)
# 年化(假设252个交易日)
annual_vol = daily_vol * np.sqrt(252)
print(f"年化波动率: {annual_vol:.4f}")
2. 协方差矩阵:资产之间的“关系网”
单看一个资产的波动率还不够。你想想,如果两个资产同涨同跌,那组合的风险并没有分散。协方差矩阵就是用来描述资产之间“联动关系”的。
举个例子,假设我们有3只股票:
import numpy as np
# 假设3只股票的日收益率数据(5天)
returns = np.array([
[0.01, 0.02, -0.01],
[-0.02, 0.01, 0.03],
[0.015, -0.01, 0.02],
[-0.005, 0.005, -0.015],
[0.008, -0.02, 0.01]
])
# 计算协方差矩阵
cov_matrix = np.cov(returns, rowvar=False)
print("协方差矩阵:")
print(cov_matrix)
嗯,这里要注意:协方差矩阵必须是半正定的,否则在后续做优化时会出问题。我曾经因为数据缺失导致矩阵不正定,结果优化出来的权重全是负数,亏了不少钱。
3. VaR:你的钱最多会亏多少?
VaR(Value at Risk),风险价值。它回答一个问题:在给定的置信水平下,未来一段时间内,你的投资组合最多可能亏损多少?
比如,95%置信水平下的日VaR为100万,意思是:有95%的把握,明天亏损不超过100万;但还有5%的可能,亏损超过100万。
计算VaR有三种常见方法:
- 参数法(方差-协方差法): 假设收益率服从正态分布,直接用均值和标准差算。
- 历史模拟法: 直接用过去的历史收益率排序,取分位数。
- 蒙特卡洛模拟法: 假设一个随机过程,模拟出大量路径,再取分位数。
import numpy as np
# 历史模拟法计算95% VaR
returns = np.random.normal(0.001, 0.02, 1000) # 模拟1000个日收益率
confidence_level = 0.95
VaR = np.percentile(returns, (1 - confidence_level) * 100)
print(f"95% VaR: {VaR:.4f}")
4. CVaR:比VaR更“诚实”的指标
CVaR(Conditional VaR),也叫期望损失。它弥补了VaR的缺陷——它计算的是超过VaR那部分损失的期望值。
说白了,VaR告诉你“最坏情况的下限”,CVaR告诉你“最坏情况下的平均损失”。
# 计算95% CVaR
threshold = np.percentile(returns, (1 - confidence_level) * 100)
CVaR = returns[returns <= threshold].mean()
print(f"95% CVaR: {CVaR:.4f}")
5. 最大回撤:投资者的“心理底线”
最大回撤(Maximum Drawdown),就是从最高点到最低点的最大跌幅。它衡量的是:如果你在最倒霉的时候入场,最多会亏多少?
这个指标特别重要,因为它直接关系到投资者的心理承受能力。我见过很多策略,年化收益很高,但最大回撤超过50%,结果客户根本拿不住,最后割肉离场。
def max_drawdown(price_series):
peak = np.maximum.accumulate(price_series)
drawdown = (price_series - peak) / peak
return drawdown.min()
# 模拟价格序列
prices = np.cumprod(1 + np.random.normal(0.001, 0.02, 1000))
mdd = max_drawdown(prices)
print(f"最大回撤: {mdd:.2%}")
6. 风险因子模型:拆解风险的“显微镜”
前面讲的都是整体风险。但实际投资中,我们需要知道风险到底来自哪里。是市场波动?是行业轮动?还是某个特定风格?
风险因子模型就是用来干这个的。最经典的是Fama-French三因子模型:市场因子、规模因子(小盘股 vs 大盘股)、价值因子(高账面市值比 vs 低账面市值比)。
后来还有五因子模型、甚至十因子模型。我个人习惯用Barra模型,它把风险拆解成:
- 市场因子: 大盘涨跌的影响
- 行业因子: 你重仓了哪个行业
- 风格因子: 比如动量、价值、波动率等
- 特异风险: 个股自己的“脾气”
# 简单示例:用线性回归分解风险
import statsmodels.api as sm
# 假设我们有组合收益率和因子收益率数据
portfolio_returns = np.random.normal(0.001, 0.02, 100)
market_returns = np.random.normal(0.0005, 0.015, 100)
size_factor = np.random.normal(0.0002, 0.01, 100)
X = np.column_stack([market_returns, size_factor])
X = sm.add_constant(X)
model = sm.OLS(portfolio_returns, X).fit()
print(model.summary())
知识体系总览
为了让你更直观地理解这些概念之间的关系,我画了一张图:
这张图清晰地展示了我们这一章的知识脉络。从最基础的波动率、协方差矩阵,到进阶的VaR、CVaR,再到风险因子模型,最终都指向一个目标——风险预算。
好了,这一章的内容就到这里。记住,风险度量不是目的,控制风险才是。下一章我们会把这些工具串起来,真正开始做风险预算。