← 返回编程题库
coding-pit-standardized-var-forecast-residual中等免费版2000ms未尝试

标准化 VaR 预测残差流:先去均值再除以波动率

Standardized VaR-Forecast Residual Stream — De-Mean Then Divide By Vol

开始编码

实现 solution(realized_pnls: list[float], mean_forecast: list[float], vol_forecast: list[float]) -> list[float]。给定三条等长的日级序列——已实现 PnL、当日均值预测、当日波动率预测(注意是标准差,不是方差)——输出标准化残差序列

> z[t] = (realized_pnls[t] − mean_forecast[t]) / vol_forecast[t]

vol_forecast[t] == 0 时该索引的标准化无定义;合约是仅在该索引输出 float('nan'),其余索引按公式正常计算。空输入返回空列表。

例:solution([0.5, 1.2, -0.3], [0.0, 0.2, -0.1], [1.0, 2.0, 0.5]) 返回 [0.5, 0.5, -0.4]。第一日均值预测为 0、波动率为 1,所以 z_0 = 0.5;第二日把 1.2 去均值到 1.0,再除以 2.0 得 0.5;第三日把 −0.3 去均值到 −0.2,再除以 0.5 得 −0.4。把第二日的波动率换成 0,即 vol_forecast = [1.0, 0.0, 0.5],则返回 [0.5, nan, -0.4],只有索引 1 变成 NaN。

区分点都是合约性的,而非算法性的。(1) 先去均值再除:分子是 realized − mean,不是裸 realized;漏掉这一步得到的不是零均值序列,下游任何 PIT(概率积分变换)或 Berkowitz LR 检验都不会把它当作标准正态。(2) 除以波动率而非方差vol_forecast[t] 是标准差,平方后会把残差再缩 vol 倍。(3) 零波动率是逐元素 NaN:仅在该索引输出 float('nan'),绝不能为了"稳定"把分母 clamp 到极小常数(这会掩盖"模型认为今天退化"的有意义信号),也绝不能全局传播或跳过该索引。(4) 输入顺序保持:output[t] 仅由 inputs[t] 决定;不排序、不重排、不去重。复杂度为 O(T) 时间、O(T) 输出空间。

函数骨架见 stubs/stub.py

实践背景

标准化残差是 VaR 预测诊断里最基础的原语:PIT 检验、Kolmogorov–Smirnov 拟合优度检验、以及无条件 Berkowitz 似然比检验都从同一步骤起手——先用当日均值预测对已实现 PnL 做去均值,再除以当日波动率预测;在均值+波动率模型校准正确且新息服从高斯的前提下,得到的 z 序列应当是 i.i.d. N(0,1)。本题的四个陷阱恰好对应真实风控管线里最常见的四种 bug:漏掉去均值这一步(z 不再以零为中心)、把分母错写成方差(z 被过度收缩、看起来"过分漂亮")、用 epsilon clamp 把零波动率"修补"掉(诊断丢掉了"模型崩了"的真实告警)、把序列做了某种排序(下游自相关检验看到的不再是按日历对齐的序列)。把这条原语写对,是后续所有 VaR backtesting 套件能够开动的第一道兼容性检查。

约束条件

  • 0 <= len(realized_pnls) == len(mean_forecast) == len(vol_forecast) <= 1500
  • 每个 |realized_pnls[t]|, |mean_forecast[t]| <= 1e6
  • 0.0 <= vol_forecast[t] <= 1e6(允许为 0,零波动率会触发逐元素 NaN 哨兵)
  • 输出是与输入等长的浮点列表;每个元素或为有限带符号浮点数,或为 float('nan');空输入返回空列表
  • 比较器:rel_tol = abs_tol = 1e-9;预期输出在某索引为 NaN 时,参与者输出在同一索引为 NaN 即视为匹配

样例

Case 1 · statement-example: zero-mean unit-vol day, plus demean and divide-by-2

输入: [[0.5,1.2,-0.3],[0,0.2,-0.1],[1,2,0.5]]

期望: [0.5,0.5,-0.39999999999999997]

第一日均值为 0、波动率为 1:z_0=0.5;第二日去均值得 1.0,再除以 2.0:z_1=0.5;第三日去均值得 -0.2,再除以 0.5:z_2=-0.4。

Case 2 · statement-example: zero-vol day -> per-element NaN sentinel only at that index

输入: [[0.5,1.2,-0.3],[0,0.2,-0.1],[1,0,0.5]]

期望: [0.5,"NaN",-0.39999999999999997]

索引 1 的 vol_forecast=0,仅该索引输出 NaN,其余索引按公式正常计算(0.5 与 -0.4)。

Case 3 · statement-example: empty inputs return empty list

输入: [[],[],[]]

期望: []

空输入直接返回空列表。

最近提交

还没有提交记录。

编码区

实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。

加载编辑器...
计时0:00

默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。

Case 1 · statement-example: zero-mean unit-vol day, plus demean and divide-by-2

输入: [[0.5,1.2,-0.3],[0,0.2,-0.1],[1,2,0.5]]

期望: [0.5,0.5,-0.39999999999999997]

第一日均值为 0、波动率为 1:z_0=0.5;第二日去均值得 1.0,再除以 2.0:z_1=0.5;第三日去均值得 -0.2,再除以 0.5:z_2=-0.4。

Case 2 · statement-example: zero-vol day -> per-element NaN sentinel only at that index

输入: [[0.5,1.2,-0.3],[0,0.2,-0.1],[1,0,0.5]]

期望: [0.5,"NaN",-0.39999999999999997]

索引 1 的 vol_forecast=0,仅该索引输出 NaN,其余索引按公式正常计算(0.5 与 -0.4)。

Case 3 · statement-example: empty inputs return empty list

输入: [[],[],[]]

期望: []

空输入直接返回空列表。