风险度量指标:波动率、VaR、CVaR、最大回撤、夏普比率、索提诺比率
做量化交易,说白了就是在跟风险打交道。你赚的每一分钱,本质上都是对风险的补偿。但问题来了——风险到底怎么量?
我刚开始做策略回测那会儿,看着账户曲线天天往上走,心里美滋滋。结果实盘一跑,三个月亏掉一半。后来复盘才发现,我根本没搞懂风险度量。今天咱们就把这几个核心指标掰开揉碎讲清楚。
1. 波动率:最基础的风险尺子
波动率,就是资产价格上下跳动的幅度。数学上通常用收益率的标准差来表示。
我个人习惯用年化波动率,这样不同时间周期的策略可以横向对比。计算公式很简单:
import numpy as np
# 假设 daily_returns 是日收益率序列
daily_vol = np.std(daily_returns, ddof=1)
annual_vol = daily_vol * np.sqrt(252) # 252个交易日
嗯,这里要注意:波动率只告诉你价格跳得有多猛,但不告诉你跳的方向。涨20%和跌20%在波动率眼里是一样的。
2. VaR:在险价值
VaR 回答的是这样一个问题:在95%的置信水平下,我最多亏多少钱?
举个例子,日 VaR(95%) = 2%,意思是有95%的概率,单日亏损不超过2%。
计算 VaR 有三种常见方法:
- 参数法: 假设收益率服从正态分布,直接用均值和标准差算
- 历史模拟法: 直接用过去N天的收益率排序,取第5%分位数
- 蒙特卡洛模拟: 随机生成大量路径,统计尾部损失
# 历史模拟法计算 VaR
def historical_var(returns, confidence=0.95):
sorted_returns = np.sort(returns)
index = int((1 - confidence) * len(sorted_returns))
return sorted_returns[index]
# 参数法计算 VaR
def parametric_var(returns, confidence=0.95):
from scipy.stats import norm
mu = np.mean(returns)
sigma = np.std(returns, ddof=1)
z = norm.ppf(1 - confidence)
return mu + z * sigma
3. CVaR:条件在险价值
VaR 有个致命缺陷:它只告诉你「最坏情况在第5%分位数」,但没告诉你一旦跌破这个阈值,到底会亏多少。
CVaR 就是来解决这个问题的。它计算的是「超过 VaR 的那些损失的平均值」。说白了,就是看尾部损失的期望。
def cvar(returns, confidence=0.95):
var = historical_var(returns, confidence)
# 找出所有比 VaR 更差的损失
tail_losses = returns[returns <= var]
return np.mean(tail_losses)
你想想看,两个策略的 VaR 可能都是2%,但一个 CVaR 是2.5%,另一个是5%。后者一旦出事,后果严重得多。我个人做风控时,CVaR 的权重比 VaR 高得多。
4. 最大回撤:最痛的记忆
最大回撤,就是从净值最高点到最低点的最大跌幅。它衡量的是你最多能扛住多大的浮亏。
这个指标特别直观。你跟客户说「年化收益20%」,他可能没感觉。但你说「最大回撤只有8%」,他立马就懂了。
def max_drawdown(equity_curve):
# equity_curve 是净值序列
peak = np.maximum.accumulate(equity_curve)
drawdown = (equity_curve - peak) / peak
return np.min(drawdown)
5. 夏普比率:收益与风险的性价比
夏普比率 = (策略收益率 - 无风险利率) / 波动率
它衡量的是每承担一单位风险,能获得多少超额收益。夏普比率大于1算及格,大于2算优秀,大于3就是顶级策略了。
但这里有个坑:夏普比率对非正态收益非常敏感。如果一个策略大部分时间小赚,偶尔大亏,它的夏普比率可能很高——因为波动率被小赚拉低了,但尾部风险被忽略了。
def sharpe_ratio(returns, risk_free_rate=0.03):
excess_returns = returns - risk_free_rate / 252
return np.sqrt(252) * np.mean(excess_returns) / np.std(excess_returns, ddof=1)
6. 索提诺比率:只惩罚下行风险
索提诺比率是夏普比率的改良版。它只考虑下行波动率——也就是亏损时的波动。上涨的波动?那叫收益,不该被惩罚。
我个人更喜欢索提诺比率。为什么?因为大多数策略的收益分布是不对称的。上涨和下跌的波动性质完全不同,混在一起算不合理。
def sortino_ratio(returns, risk_free_rate=0.03, target=0):
excess_returns = returns - risk_free_rate / 252
# 只计算下行波动率
downside_returns = returns[returns < target]
downside_vol = np.std(downside_returns, ddof=1) if len(downside_returns) > 0 else 1e-10
return np.sqrt(252) * np.mean(excess_returns) / downside_vol
知识体系总览
下面这张图把六个指标的关系梳理清楚了。我建议你把它存下来,做策略评估时对照着看:
六个指标怎么搭配使用?
单一指标都有盲区。我自己的评估框架是这样的:
| 评估维度 | 核心指标 | 辅助指标 | 我的阈值 |
|---|---|---|---|
| 波动控制 | 年化波动率 | 最大回撤 | 波动率 < 20%,回撤 < 15% |
| 尾部风险 | CVaR(95%) | VaR(95%) | CVaR < 3%(日度) |
| 收益质量 | 索提诺比率 | 夏普比率 | 索提诺 > 1.5,夏普 > 1.0 |
好了,这一章的内容就到这里。记住,风险度量不是算个数字就完事了——你得理解每个数字背后的含义,知道它的局限在哪。下一章咱们聊聊怎么把这些指标用到动态仓位管理中去。
公众号:蓝海资料掘金营,微信 deep3321