R中使用cvar包计算参数化Expected Shortfall结果不符排查求助
问题排查与修正:cvar包与自定义/QRM包ES结果不一致
核心问题
你的代码出现结果差异的原因有两个:
- ES的方向定义不匹配:自定义函数和QRM的
ESnorm计算的是收益分布的右尾ES(收益高于95%分位数的条件期望),而cvar包默认计算的是损失分布的上侧ES(对应收益的左尾ES),方向完全相反。 - 分布参数传递错误:直接传递
pnorm给cvar的ES函数时,mean和sd无法正确绑定到分布函数上,导致计算用的是标准正态分布而非你指定的参数分布。
修正后的代码
# 自定义正态分布ES函数(右尾) calculate_expected_shortfall <- function(mean, sigma, alpha) { z_alpha <- qnorm(alpha) phi_z_alpha <- dnorm(z_alpha) mean + sigma * (phi_z_alpha / (1 - alpha)) } # 参数配置 mean <- 100 sigma <- 15 alpha <- 0.95 # 方法1:自定义函数 es_custom <- calculate_expected_shortfall(mean, sigma, alpha) # 方法2:QRM包(默认右尾ES) library(QRM) es_qrm <- ESnorm(0.95, mu = mean, sd = sigma) # 方法3:修正后的cvar包调用(两种有效方式) library(cvar) # 方式A:用分位数函数qnorm,直接指定右尾ES es_cvar_qf <- ES(qnorm, dist.type = "qf", p_loss = alpha, mean = mean, sd = sigma, side = "upper") # 方式B:用匿名函数绑定pnorm参数,指定右尾ES es_cvar_cdf <- ES( function(q) pnorm(q, mean = mean, sd = sigma), dist.type = "cdf", p_loss = 1 - alpha, side = "upper" ) # 验证一致性 cat("自定义函数结果:", round(es_custom, 4), "\n") cat("QRM包结果:", round(es_qrm, 4), "\n") cat("cvar包(分位数函数)结果:", round(es_cvar_qf, 4), "\n") cat("cvar包(CDF匿名函数)结果:", round(es_cvar_cdf, 4), "\n")
关键修正说明
1. 对齐ES方向
- 自定义函数和
ESnorm的alpha=0.95对应右尾5%的极端收益,cvar包需要通过side="upper"指定计算上侧(右尾)ES,并调整p_loss参数:- 用分位数函数时,
p_loss=alpha=0.95直接对应收益的95%分位数。 - 用CDF时,
p_loss=1-alpha=0.05表示右尾5%的概率区间。
- 用分位数函数时,
2. 正确传递分布参数
- 使用分位数函数
qnorm时,mean和sd可直接通过...参数传递给qnorm,无需额外处理。 - 使用CDF时,必须用匿名函数将
mean和sd绑定到pnorm上,否则cvar会默认使用标准正态分布进行计算。
验证结果
运行修正后的代码,四个结果将完全一致(约为130.9402),符合你的预期。
内容的提问来源于stack exchange,提问作者R_us3r
相关产品推荐
相关产品推荐

