RiskMetrics EWMA 波动率预测
RiskMetrics EWMA Volatility Forecast
开始编码某日频 VaR 引擎需要为桌台每期收益流给出快速且稳定的波动率预测,每期随新收益实现刷新一次。团队使用 RiskMetrics EWMA 方差递推:一个指数加权移动方差,带一个可调平滑因子 lambda 和一个初始方差种子。
实现 solution(returns: list[float], decay: float, initial_var: float) -> list[float],顺序返回 T = len(returns) 个每期方差预测 [sigma2_1, sigma2_2, ..., sigma2_T]。递推为
其中 lambda = decay,r_{t-1} = returns[t-1]。种子 sigma2_0 *不*输出;第一个输出是 sigma2_1。输出长度为 T,不是 T+1。
递推是因果的:sigma2_t(t 期方差预测)由 sigma2_{t-1} 和刚刚在 t-1 期实现的平方收益 r_{t-1}^2 构成。在产出 sigma2_t 时索引 returns[t] 等于在偷看尚未观测的 t 期收益。
示例
solution([0.01, -0.02, 0.005], 0.94, 0.0001) 返回 [0.0001, 0.000118, 0.00011242]。手算演示,lambda = 0.94(1 - lambda = 0.06):种子 sigma2_0 = 0.0001。t = 1:sigma2_1 = 0.94 * 0.0001 + 0.06 * 0.01^2 = 0.000094 + 0.000006 = 0.0001。t = 2:sigma2_2 = 0.94 * 0.0001 + 0.06 * (-0.02)^2 = 0.000094 + 0.000024 = 0.000118。t = 3:sigma2_3 = 0.94 * 0.000118 + 0.06 * 0.005^2 = 0.00011092 + 0.0000015 = 0.00011242。输出长度 3,与 T = 3 一致——initial_var 本身不出现。
再如 solution([], 0.94, 0.0001) 返回 [](空收益流 → 空输出)。又如 solution([0.1, -0.2, 0.05, 0.0, -0.15], 0.001, 0.5) 展示 decay 接近零的极限:lambda = 0.001 时递推几乎完全遗忘上一步方差,所以每个 sigma2_t 基本就是 (1 - lambda) * returns[t-1]^2 ≈ returns[t-1]^2——输出近似等于平方收益。
一次前向扫一遍、维护一个标量,即得 O(T) 时间和 O(T) 输出空间;评测使用绝对+相对容差 1e-9。
参见 stubs/stub.py 的函数骨架。
实践背景
RiskMetrics(1996)把这个递推作为日频波动率的标准估计量:sigma2_t = lambda * sigma2_{t-1} + (1 - lambda) * r_{t-1}^2,日频取 lambda = 0.94,月频取 lambda = 0.97。该预测喂参数化 VaR(高斯置信水平下 sigma_t * z_alpha)、期权定价重校准,以及资本投影。EWMA 是 GARCH(1,1) 在 omega = 0、alpha = 1 - lambda、beta = lambda 时的特例——它没有长期均值(没有 omega 常数),会平滑地适应而不会回归到无条件方差。生产中四个常见实现陷阱:(a) 用 returns[t] 而不是 returns[t-1](偷看未来);(b) 喂带符号收益而不是其平方(方差只跟幅度有关);(c) 把 initial_var 当成第一个输出(错位一期);(d) 把两个系数分别再归一化(累积浮点漂移)。本题要的就是干净版:一个 O(T) 紧致循环,lambda 衰减旧方差,(1 - lambda) 加权刚到的平方冲击。
约束条件
- 0 <= len(returns) <= 1500(T 为预测步数)
- -1.0 <= returns[t] <= 1.0(带符号的每期收益;只有平方进入递推)
- 0.001 <= decay < 1.0(RiskMetrics 平滑因子 lambda;日频标准为 0.94)
- 0.0 <= initial_var <= 1.0(种子 sigma2_0;通常取长期样本方差或一个固定先验)
- 输出为长度恰为 T 的 `list[float]`,各元素非负方差。
- 浮点比较容差:`rel_tol = 1e-9`,`abs_tol = 1e-9`。
样例
Case 1 · statement-example: 3-step EWMA with daily lambda=0.94 and seed 0.0001
输入: [[0.01,-0.02,0.005],0.94,0.0001]
期望: [0.0001,0.00011800000000000002,0.00011242000000000001]
种子 σ²₀=0.0001;σ²₁=0.94*0.0001+0.06*0.01²=0.0001;σ²₂=0.94*0.0001+0.06*0.0004=0.000118;σ²₃ 类似递推。
Case 2 · statement-example: empty returns yields empty output
输入: [[],0.94,0.0001]
期望: []
T=0 时输出为空 list []。
Case 3 · statement-example: near-zero decay collapses output to squared returns
输入: [[0.1,-0.2,0.05,0,-0.15],0.001,0.5]
期望: [0.010490000000000003,0.03997049000000001,0.0025374704900000006,0.0000025374704900000006,0.022477502537470488]
decay=0.001 时 σ²_t ≈ returns[t-1]²,旧方差几乎被遗忘;输出几乎等于平方收益。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · statement-example: 3-step EWMA with daily lambda=0.94 and seed 0.0001
输入: [[0.01,-0.02,0.005],0.94,0.0001]
期望: [0.0001,0.00011800000000000002,0.00011242000000000001]
种子 σ²₀=0.0001;σ²₁=0.94*0.0001+0.06*0.01²=0.0001;σ²₂=0.94*0.0001+0.06*0.0004=0.000118;σ²₃ 类似递推。
Case 2 · statement-example: empty returns yields empty output
输入: [[],0.94,0.0001]
期望: []
T=0 时输出为空 list []。
Case 3 · statement-example: near-zero decay collapses output to squared returns
输入: [[0.1,-0.2,0.05,0,-0.15],0.001,0.5]
期望: [0.010490000000000003,0.03997049000000001,0.0025374704900000006,0.0000025374704900000006,0.022477502537470488]
decay=0.001 时 σ²_t ≈ returns[t-1]²,旧方差几乎被遗忘;输出几乎等于平方收益。