风险度量指标:从波动率到风险贡献
各位同学,今天我们来聊聊风险度量指标。说实话,我刚入行那会儿,觉得风险度量就是算算波动率,简单得很。直到有一次,我管理的组合在一天内暴跌了5%,而波动率模型却告诉我风险可控——嗯,从那以后我才真正理解,单一指标是远远不够的。
这一章,我会带你逐一拆解7个核心指标。每个指标我都会讲清楚:它是什么、怎么算、什么时候用、有什么坑。你想想看,如果连风险都量不准,那风险预算还怎么调优?
核心观点:风险度量不是选一个指标,而是构建一套指标体系。每个指标都有它的盲区,组合使用才能看清全貌。
1. 波动率:最基础的度量
波动率,说白了就是资产收益率的波动程度。我习惯用年化波动率,因为不同时间尺度下好比较。
计算公式:
import numpy as np
def annualized_volatility(returns):
"""
计算年化波动率
returns: 日收益率序列
"""
daily_vol = np.std(returns, ddof=1)
annual_vol = daily_vol * np.sqrt(252) # 252个交易日
return annual_vol
这里有个细节:ddof=1 表示用样本标准差,而不是总体标准差。我在项目中遇到过有人用 ddof=0,结果算出来的波动率偏小,导致风险预算过于激进。
我的经验:波动率对极端值很敏感。如果数据里有异常值,建议先做 winsorize(缩尾处理),不然一个跳空就能把波动率拉高20%。
2. VaR:风险价值
VaR 回答的问题是:在95%的置信水平下,我最多亏多少钱?听起来很直观,但实际用起来有不少坑。
三种计算方法:
- 参数法:假设收益率服从正态分布,直接用均值和标准差算。快,但不准——金融数据哪有那么乖?
- 历史模拟法:直接用历史数据的分位数。简单,但历史会重演吗?
- 蒙特卡洛模拟:随机生成大量路径。灵活,但计算量大。
def historical_var(returns, confidence=0.95):
"""
历史模拟法计算VaR
"""
var = np.percentile(returns, (1 - confidence) * 100)
return abs(var) # 返回正值,表示损失
我曾经踩过的坑:VaR 不满足次可加性。什么意思?就是两个组合合并后的VaR,可能比各自VaR之和还大。这在风险预算里会出大问题——你分散了风险,但VaR告诉你风险反而增加了。所以,别只用VaR做风险预算。
3. CVaR:条件风险价值
CVaR 是 VaR 的升级版。它不只看那个分位点,而是看超过VaR部分的平均损失。说白了,VaR 告诉你最差情况下的底线,CVaR 告诉你底线以下有多惨。
def historical_cvar(returns, confidence=0.95):
"""
历史模拟法计算CVaR
"""
var = historical_var(returns, confidence)
# 找出所有超过VaR的损失
tail_losses = returns[returns < -var]
cvar = np.mean(tail_losses)
return abs(cvar)
我个人更偏爱CVaR。为什么?因为它考虑了尾部风险。你想想看,两个组合的VaR可能一样,但一个的尾部损失是-10%,另一个是-30%,你能说它们风险一样吗?
4. 最大回撤
最大回撤,就是从最高点到最低点的最大跌幅。这个指标很直观,投资者一看就懂。但要注意,它只关注一个点——最惨的那个时刻。
def max_drawdown(cumulative_returns):
"""
计算最大回撤
cumulative_returns: 累计收益率序列
"""
peak = np.maximum.accumulate(cumulative_returns)
drawdown = (cumulative_returns - peak) / peak
max_dd = np.min(drawdown)
return abs(max_dd)
避坑指南:最大回撤对数据频率很敏感。日频数据算出来的回撤,通常比周频数据大。我建议统一用日频,这样不同策略之间才好比较。
5. 夏普比率
夏普比率 = (组合收益率 - 无风险利率) / 波动率。它衡量的是每承担一单位风险,能获得多少超额收益。
嗯,这里要注意:无风险利率怎么选?有人用国债收益率,有人用SHIBOR。我个人习惯用一年期国债收益率,因为期限匹配,而且数据好拿。
def sharpe_ratio(returns, risk_free_rate=0.03):
"""
计算夏普比率
risk_free_rate: 年化无风险利率
"""
excess_returns = returns - risk_free_rate / 252
annual_excess = np.mean(excess_returns) * 252
annual_vol = np.std(returns, ddof=1) * np.sqrt(252)
return annual_excess / annual_vol
注意:夏普比率假设收益率是正态分布。如果策略有偏度或厚尾,夏普比率会失真。我在项目中见过一个策略,夏普比率高达3.0,但仔细一看,它的收益主要来自几次极端事件——这种策略你敢用吗?
6. 信息比率
信息比率和夏普比率很像,但基准不同。夏普比率对比的是无风险利率,信息比率对比的是某个基准指数。
公式:信息比率 = (组合收益率 - 基准收益率) / 跟踪误差
这里的跟踪误差,就是超额收益的标准差。说白了,信息比率衡量的是你相对于基准的主动管理能力。
def information_ratio(portfolio_returns, benchmark_returns):
"""
计算信息比率
"""
excess_returns = portfolio_returns - benchmark_returns
tracking_error = np.std(excess_returns, ddof=1)
annual_excess = np.mean(excess_returns) * 252
annual_tracking_error = tracking_error * np.sqrt(252)
return annual_excess / annual_tracking_error
我一般用信息比率来评价主动管理型策略。如果一个策略的信息比率长期低于0.5,那还不如直接买指数基金,省心省力。
7. 风险贡献:风险预算的核心
终于到了最关键的部分。风险贡献,就是每个资产对组合总风险的贡献度。它是风险预算调优的基础。
边际风险贡献:每增加一单位资产权重,组合风险的变化量。
总风险贡献:权重 × 边际风险贡献。所有资产的总风险贡献之和,等于组合的总风险。
def risk_contribution(weights, cov_matrix):
"""
计算各资产的风险贡献
weights: 权重向量
cov_matrix: 协方差矩阵
"""
portfolio_vol = np.sqrt(weights.T @ cov_matrix @ weights)
marginal_contrib = (cov_matrix @ weights) / portfolio_vol
total_contrib = weights * marginal_contrib
risk_contrib_pct = total_contrib / portfolio_vol
return risk_contrib_pct
核心思想:风险预算调优的目标,就是让每个资产的风险贡献相等(或达到预设比例)。这样,组合就不会过度依赖某一个资产的风险。
知识体系总览
下面这张图,帮你理清这7个指标的关系。我画的是三层结构:底层是基础指标,中层是风险调整收益指标,顶层是风险分解指标。
你看,从下往上,我们一步步从「风险有多大」到「风险值不值」,再到「风险从哪里来」。这就是风险预算调优的完整逻辑链。
我的建议:刚开始做风险预算时,别贪多。先把波动率和风险贡献这两个指标吃透,其他的慢慢加。我见过太多人一上来就搞十几个指标,结果自己都搞晕了。
好了,这一章的内容就到这里。记住,风险度量不是目的,而是手段。我们最终的目标,是通过这些指标来指导风险预算的调优。下一章,我们会把这些指标串起来,看看怎么在实际组合中应用。
公众号:蓝海资料掘金营,微信deep3321