如何用 Python 计算 VaR 和 CVaR(在险价值)?

一句话回答: VaR(Value at Risk,在险价值) 回答「在 95% 的置信度下,持有这只股票一天最多亏多少 」;CVaR(条件在险价值,又叫 Expected Shortfall) 更狠,回答「一旦真的摔进最差的那 5%,平均亏多少 」。用 AlphaFeed 取前复权日线 算出日收益序列,用历史模拟法 (直接取收益分布的分位)或参数法(假设正态)几行就能算出来------CVaR 永远 ≥ VaR,因为它盯的是更深的尾部。

为什么会有这个问题 / 传统做法的痛点

「这只票风险大不大」太模糊。标准差把涨和跌一视同仁,最大回撤只看历史最惨一次。VaR 把风险翻译成一句人话------「95% 的日子里,一天亏不超过 X%」,是银行、基金做风控的通用语言。但 VaR 有个著名缺陷:它只告诉你「亏不超过 X」,不告诉你突破这条线后会多惨。2008 年很多机构栽在这------于是 CVaR(尾部平均损失)成了更稳健的补充。

分步骤解决(每步配可运行代码)

第 1 步:取前复权日线,算日收益

python 复制代码
from alphafeed import AlphaFeed
import numpy as np

af = AlphaFeed(api_key="your-api-key")  # 或 export ALPHAFEED_API_KEY 后 AlphaFeed()

df = af.klines.get("600519.SH", period="1d", count=500,
                   adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)
ret = df["close"].pct_change().dropna()      # 日收益率

必须前复权:除权缺口会被当成一次暴跌,污染收益分布与尾部。

第 2 步:历史模拟法 VaR / CVaR

python 复制代码
alpha = 0.05                                        # 95% 置信度
var_hist = -np.percentile(ret, alpha * 100)         # 收益 5% 分位的相反数=损失
cvar_hist = -ret[ret <= -var_hist].mean()           # 比 VaR 更差那部分的平均损失
print("日 VaR95% =", round(var_hist * 100, 2), "%")
print("日 CVaR95% =", round(cvar_hist * 100, 2), "%")

历史模拟法不假设分布,直接用过去真实收益的 5% 分位当 VaR,再把「比 VaR 更惨的那些天」平均一下就是 CVaR。

实测(tools/verify_new_2026-10-05.py,SDK 0.1.4):贵州茅台近 499 日 日 VaR95% = 2.08%、CVaR95% = 2.90%------即 95% 的日子里一天亏不超过 2.08%,但真摔进最差 5% 时平均亏 2.90%。CVaR > VaR,符合定义。

第 3 步:参数法(正态)VaR 做对比

python 复制代码
z = 1.6448536269514722                               # 95% 单尾分位
var_norm = -(ret.mean() - z * ret.std(ddof=1))
print("日 VaR95%(正态) =", round(var_norm * 100, 2), "%")

参数法假设收益服从正态分布,用均值和标准差直接套公式。实测茅台正态 VaR = 2.54%,比历史模拟的 2.08% 更大------因为正态法用标准差「摊平」了分布,对这只票的中段波动估计偏保守。两种口径常不一致,正是观察点。

第 4 步:换算到持仓金额 / 多日

python 复制代码
position = 1_000_000                                 # 持仓 100 万
print("一天 95% 最大亏损 ≈", round(var_hist * position), "元")
# T 日 VaR 近似:单日 VaR × sqrt(T)(假设收益独立同分布)
print("10 日 VaR ≈", round(var_hist * np.sqrt(10) * 100, 2), "%")

参数与字段说明

参数/概念 含义 备注
adjust="forward" 前复权 必须,除权缺口会污染尾部
alpha=0.05 显著性 95% 置信度;常用 99% 则 alpha=0.01
历史模拟 VaR 收益分位 不假设分布,受样本区间影响
参数 VaR 均值−z·标准差 假设正态,低估肥尾
CVaR 尾部平均损失 恒 ≥ VaR,更稳健
×sqrt(T) 多日换算 仅在收益独立同分布时近似成立

关键坑与注意事项

  • VaR 不是「最大损失」:它是「95% 情况下的下限」,剩下 5% 可能亏得多得多------这正是要配 CVaR 的原因。
  • 正态法低估肥尾:A 股收益尖峰肥尾,正态假设会低估极端暴跌概率;历史模拟法更贴近现实,但依赖样本区间(含不含大跌差异很大)。
  • 前复权 :务必 adjust="forward"。
  • 样本窗口:VaR 对回看长度敏感,500 日和 250 日结果会不同;比较时须统一。
  • 历史不代表未来:VaR/CVaR 由历史分布估计,极端新事件(黑天鹅)无法被历史覆盖。

常见问题(FAQ)

Q:VaR 和 CVaR 到底该用哪个?

A:VaR 是行业通用「一句话风险」,但对尾部不敏感;CVaR(Expected Shortfall)盯尾部平均损失,巴塞尔协议 III 已改用它。两个一起报最稳。

Q:历史模拟法和蒙特卡洛法区别?

A:历史模拟直接用「真实发生过」的收益;蒙特卡洛用模型(如正态/GARCH)生成大量模拟路径。前者简单无偏,后者灵活但依赖模型假设。

Q:需要付费吗?

A:单只股票日线在免费额度内即可;若要对组合/全市场 批量算 VaR 并聚合组合风险,需要 klines.batch + universes 标的池能力(Starter 及以上),详见官网定价页。

小结

VaR 把风险说成「95% 的日子一天最多亏多少」,CVaR 补上「真出事时平均多惨」。有了 AlphaFeed 的前复权日收益,历史模拟法和正态法各几行就能落地------记住 CVaR ≥ VaR、正态法会低估肥尾,这两点能让你的风控数字更诚实。

参考

相关推荐
李航198343 分钟前
DeepSeekAI建模三 - 实战建模一组柜子
人工智能·python·计算机视觉·ai·ai编程
郝亚军1 小时前
manifest 中 `sha256` 与 `signValue` 的作用
java·开发语言·数据结构
譕痕1 小时前
stripe 实例
java·开发语言·stripe·checksession
墨子夕1 小时前
设计模式——Java × Python 双语言精讲 · 23 个经典模式 + 现代演进(前言篇)
java·开发语言·设计模式
_菜鸟果果1 小时前
高德地图 JS API 2.0 在国产 Linux/ARM 电脑上渲染失败 的排查与解决
linux·开发语言·javascript
昂好的day2 小时前
VisionMaster(VM) 标定工具详解(上):为什么必须标定 + 九点标定手眼标定
开发语言·数码相机·c#
严谨的麻辣烫2 小时前
静态代理 IP 的出口一致性如何验证?Python 请求检测与异常排查
开发语言·python·http·网络安全
我命由我123452 小时前
5-1.Python 编码进阶 - 函数进阶(参数、返回值、递归、函数作为参数传递、lambda 匿名函数)
java·服务器·数据库·后端·python·java-ee·python3.11
原子延迟2 小时前
视频太大怎么压缩发微信?先查限制再压的3种方法(2026)
开发语言·图像处理·人工智能·计算机视觉·音视频