历史期望损失
Historical Expected Shortfall
开始编码风控部门的每日 tearsheet 会同时报告 99% 期望损失(CVaR)与 99% VaR:VaR 是 99% 置信度下不会超过的损失阈值,ES 则是落入最差 1% 尾部时的*平均*损失。ES 在尾部风险报告里更受欢迎,因为一个 99% VaR 刚好触线、99% ES 却是上限三倍的组合,意味着阈值之下还藏着重尾,光看 VaR 无法察觉。请实现 solution(pnl_samples: list[float], alpha: float) -> float:给定历史区间 PnL 序列(正数=盈利,负数=亏损)与 VaR 置信度 alpha,返回历史期望损失,并以正的损失数值报告。
例
solution([0.012, -0.008, 0.005, -0.030, 0.018, -0.022, 0.001, -0.045, 0.014, -0.011], 0.8) 应返回 0.0375。N = 10、alpha = 0.8,尾部大小 k = ceil(10 * 0.2) = 2。升序排序得 [-0.045, -0.030, -0.022, -0.011, -0.008, 0.001, 0.005, 0.012, 0.014, 0.018];最差两笔是 [-0.045, -0.030],均值 = -0.0375,因此 ES = -(-0.0375) = +0.0375——最差两天的平均亏损为 3.75%。
实践背景
三个常见正确性陷阱。第一,尾部大小必须用 ceil,不能用 floor 或 int(...):N = 99、alpha = 0.99 时,floor(99 * 0.01) = 0 会让尾部为空(NaN),而 ceil(99 * 0.01) = 1 才会正确取到最差的那一笔。还要小心 IEEE-754 漂移:100 * (1 - 0.99) 的实际值是 1.0000000000000009,朴素 ceil 会取到 2,而 N=100、alpha=0.99 的教科书答案是 k=1。用 k = max(1, ceil(N * (1 - alpha) - 1e-9)) 兜一下底,常见的 alpha(0.5、0.9、0.95、0.99、0.999)就都能得到教科书答案。第二,alpha 是对应 VaR 的*置信度*而不是尾部比例——alpha = 0.99 意味着我们对最差 1 - 0.99 = 0.01 比例的 PnL 取平均,也就是排序后的*底部*。把 sorted_pnl[-k:](最好那 k 笔盈利)当成尾部的写法会把 ES 翻成「最佳尾部」指标,悄悄把仪表盘的风险排序整个反转。第三,*符号约定*:损失尾部的 ES 报告为正数。最差 k 笔 PnL 的均值通常是负数(亏损),ES 就是它的相反数;ES > 0 表示平均亏损,ES < 0(少见)则表示连最差 k 笔都是净盈利。漏掉这一步取负,仪表盘那一格的符号就会反过来。
参考算法就是教科书一行:sorted(pnl_samples),取 k = ceil(N * (1 - alpha)),对前 k 个求均值再取相反数。O(N log N) 排序加 O(k) 尾部均值,对 N ≤ 1500 的规模绰绰有余。
约束条件
- 1 ≤ len(pnl_samples) ≤ 1500。
- |pnl_samples[i]| ≤ 1e6,均为有限浮点数。
- 0.5 ≤ alpha < 1.0(常见 VaR 置信度:0.5、0.9、0.95、0.99、0.999)。
- 尾部大小 k = ceil(N * (1 - alpha))(数学口径);在 IEEE-754 浮点下用 `1e-9` 量级的 epsilon 兜底,让例如 N=100、alpha=0.99 得到 k=1(而不是 `100 * (1 - 0.99) = 1.0000000000000009` 漂到 k=2)。在给定上下界下恒有 k ≥ 1。
- 输出 ES 为正的损失数值(若尾部仍盈利则为负)。
- 浮点容忍:rel_tol=1e-9,abs_tol=1e-9。
样例
Case 1 · statement-example, N=10 alpha=0.8 k=2
输入: [[0.012,-0.008,0.005,-0.03,0.018,-0.022,0.001,-0.045,0.014,-0.011],0.8]
期望: 0.0375
N=10、alpha=0.8,k=ceil(10*0.2)=2。升序排序后最差两笔是 [-0.045, -0.030],均值 -0.0375,ES = +0.0375。
Case 2 · typical, N=100 alpha=0.99 k=1 (single worst)
输入: [[0.001,-0.002,0.003,-0.004,0.005,-0.006,0.002,-0.001,0.004,-0.003,0,0.001,-0.005,0.006,-0.002,0.003,-0.004,0.005,0.001,-0.003,0.002,-0.001,0.004,-0.005,0.003,0,-0.002,0.001,-0.004,0.005,0.002,-0.001,0.003,-0.002,0.001,0,-0.003,0.004,-0.005,0.002,0.001,-0.002,0.005,-0.001,0.003,-0.004,0.002,0,-0.001,0.004,0.001,-0.005,0.002,0.003,-0.001,0,0.005,-0.003,0.002,0.001,-0.002,0.004,-0.001,0.003,-0.005,0.001,0.002,-0.003,0,0.004,-0.001,0.005,-0.002,0.003,0.001,-0.004,0.002,-0.005,0,0.001,0.003,-0.001,0.005,-0.002,0.004,-0.003,0.001,0,0.002,-0.001,0.005,-0.004,0.003,0.002,-0.001,0,0.001,-0.003,0.004,-0.0085],0.99]
期望: 0.0085
N=100、alpha=0.99,k=ceil(100*0.01)=1。最小元素为 -0.0085,因此 ES = +0.0085——99% VaR/ES 在 N=100 时只看单个最差观测。
Case 3 · visible, alpha=0.95 N=20 clean two-decimal entries
输入: [[-0.5,-0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3,0.4,-0.05,-0.15,-0.25,-0.35,-0.45,0.05,0.15,0.25,0.35,0.45],0.95]
期望: 0.5
N=20、alpha=0.95,k=ceil(20*0.05)=1。最差观测是 -0.50,因此 ES = +0.50。
Case 4 · visible, alpha=0.5 N=10 averaging the worst half
输入: [[-0.05,-0.04,-0.03,-0.02,-0.01,0.01,0.02,0.03,0.04,0.05],0.5]
期望: 0.03
N=10、alpha=0.5,k=ceil(10*0.5)=5。最差五笔 [-0.05, -0.04, -0.03, -0.02, -0.01] 均值 -0.03,ES = +0.03。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · statement-example, N=10 alpha=0.8 k=2
输入: [[0.012,-0.008,0.005,-0.03,0.018,-0.022,0.001,-0.045,0.014,-0.011],0.8]
期望: 0.0375
N=10、alpha=0.8,k=ceil(10*0.2)=2。升序排序后最差两笔是 [-0.045, -0.030],均值 -0.0375,ES = +0.0375。
Case 2 · typical, N=100 alpha=0.99 k=1 (single worst)
输入: [[0.001,-0.002,0.003,-0.004,0.005,-0.006,0.002,-0.001,0.004,-0.003,0,0.001,-0.005,0.006,-0.002,0.003,-0.004,0.005,0.001,-0.003,0.002,-0.001,0.004,-0.005,0.003,0,-0.002,0.001,-0.004,0.005,0.002,-0.001,0.003,-0.002,0.001,0,-0.003,0.004,-0.005,0.002,0.001,-0.002,0.005,-0.001,0.003,-0.004,0.002,0,-0.001,0.004,0.001,-0.005,0.002,0.003,-0.001,0,0.005,-0.003,0.002,0.001,-0.002,0.004,-0.001,0.003,-0.005,0.001,0.002,-0.003,0,0.004,-0.001,0.005,-0.002,0.003,0.001,-0.004,0.002,-0.005,0,0.001,0.003,-0.001,0.005,-0.002,0.004,-0.003,0.001,0,0.002,-0.001,0.005,-0.004,0.003,0.002,-0.001,0,0.001,-0.003,0.004,-0.0085],0.99]
期望: 0.0085
N=100、alpha=0.99,k=ceil(100*0.01)=1。最小元素为 -0.0085,因此 ES = +0.0085——99% VaR/ES 在 N=100 时只看单个最差观测。
Case 3 · visible, alpha=0.95 N=20 clean two-decimal entries
输入: [[-0.5,-0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3,0.4,-0.05,-0.15,-0.25,-0.35,-0.45,0.05,0.15,0.25,0.35,0.45],0.95]
期望: 0.5
N=20、alpha=0.95,k=ceil(20*0.05)=1。最差观测是 -0.50,因此 ES = +0.50。
Case 4 · visible, alpha=0.5 N=10 averaging the worst half
输入: [[-0.05,-0.04,-0.03,-0.02,-0.01,0.01,0.02,0.03,0.04,0.05],0.5]
期望: 0.03
N=10、alpha=0.5,k=ceil(10*0.5)=5。最差五笔 [-0.05, -0.04, -0.03, -0.02, -0.01] 均值 -0.03,ES = +0.03。