4、移动平均模型:简单移动平均(SMA)、指数加权移动平均(EWMA)、模型参数选择与实战对比

波动率预测,说白了就是猜市场未来会怎么抖。你想想看,做风控的人最怕什么?不是亏钱,是亏得不明不白。移动平均模型,就是帮我们把历史波动捋顺了,再往前看。

我个人习惯把移动平均模型分成两类:一类是「人人都会」的简单移动平均(SMA),另一类是「老手常用」的指数加权移动平均(EWMA)。今天咱们就把这两兄弟掰开揉碎了讲清楚。

4.1 简单移动平均(SMA)—— 入门级但别小看

SMA 的逻辑极其简单:取过去 N 天的波动率,算个平均值。公式长这样:

σ²_t = (1/N) * Σ(r²_{t-i})   for i = 1 to N

其中 r² 是日收益率的平方。嗯,这里要注意:我们算的是方差,不是标准差。因为方差有可加性,后面做预测更方便。

我在项目中遇到过一件事:有个同事用 SMA 做期权定价的波动率输入,窗口选了 20 天。结果遇到一次突发暴跌,SMA 死活跟不上变化,定价全偏了。为什么?因为 SMA 给每一天的权重完全一样——20 天前的数据和昨天的数据,地位平等。这在平稳市场没问题,但市场一炸,它就反应迟钝了。

核心要点:SMA 适合波动率变化缓慢的市场。如果市场经常出现跳空、黑天鹅,SMA 会让你吃大亏。

4.2 指数加权移动平均(EWMA)—— 老司机的选择

EWMA 的改进思路很直接:越近的数据越重要。公式如下:

σ²_t = λ * σ²_{t-1} + (1 - λ) * r²_{t-1}

这里的 λ 叫衰减因子,通常取 0.94 或 0.97。λ 越大,历史数据衰减得越慢;λ 越小,模型对近期变化越敏感。

我曾经在风险管理系统中用 EWMA 做 VaR 计算。有一次市场连续三天大跌,SMA 的 VaR 值还在慢慢爬,EWMA 第二天就跳上去了。风控总监看到报告后问我:「你这模型是不是太敏感了?」我说:「敏感总比迟钝好,真出事的时候,早一天预警就是几千万的差别。」

实战技巧:我个人习惯把 λ 设为 0.94。这是 RiskMetrics 的经典参数,经过大量市场验证。如果你做的是高频交易,可以试试 0.92;如果是周度数据,0.97 更合适。

4.3 模型参数选择—— 别让参数毁了你的模型

参数选择是个坑,我踩过。简单列几个原则:

  • SMA 的窗口长度 N:N 越大,曲线越平滑,但滞后越严重。我一般用 20 天(一个月)或 60 天(一个季度)。做长期风控用 60 天,做短期交易用 20 天。
  • EWMA 的 λ:0.94 是基准。如果你发现模型对突发事件反应太慢,降低 λ;如果噪声太多,提高 λ。
  • 数据频率:日数据用 SMA 或 EWMA 都行。分钟级数据,我强烈建议用 EWMA,因为 SMA 的滞后在高频下会放大。
避坑指南:我曾经用 SMA 做 5 分钟高频波动率预测,窗口选了 50。结果模型几乎是一条直线——因为高频数据噪声太大,SMA 把信号全抹平了。后来换成 EWMA,λ=0.92,效果立竿见影。

4.4 实战对比—— 一张表看懂差异

对比维度 SMA EWMA
计算复杂度 极低,O(1) 更新 低,O(1) 更新
对近期变化的敏感度 低(等权重) 高(指数衰减)
滞后性 明显,N 越大越滞后 较小,λ 控制滞后
适用场景 平稳市场、长期风控 波动市场、高频交易、VaR 计算
参数调优难度 简单,选 N 即可 稍复杂,λ 需要经验

你看,没有绝对的好坏。SMA 简单可靠,EWMA 灵活敏感。我个人的建议是:先用 SMA 跑一遍,作为基准;再用 EWMA 做优化。如果两者差异不大,用 SMA 就行——简单的东西不容易出错。

4.5 核心逻辑框架图

下面这张图,是我自己画的知识体系。你看一眼就能明白移动平均模型在波动率预测中的位置:

移动平均模型知识体系 波动率预测 SMA 简单移动平均 EWMA 指数加权移动平均 等权重,N 天窗口 滞后明显,适合平稳市场 指数衰减,λ 控制敏感度 反应快,适合高频/VaR 实战建议:SMA 做基准,EWMA 做优化

4.6 代码实战—— 手把手教你算

光说不练假把式。下面是我用 Python 写的 SMA 和 EWMA 实现,你直接复制就能跑:

import numpy as np
import pandas as pd

# 模拟收益率数据
np.random.seed(42)
returns = np.random.randn(100) * 0.02  # 日收益率,标准差 2%

# SMA 计算
def sma_variance(returns, window=20):
    sq_returns = returns ** 2
    sma = pd.Series(sq_returns).rolling(window=window).mean()
    return sma.values

# EWMA 计算
def ewma_variance(returns, lam=0.94):
    sq_returns = returns ** 2
    ewma = np.zeros_like(sq_returns)
    ewma[0] = sq_returns[0]
    for t in range(1, len(sq_returns)):
        ewma[t] = lam * ewma[t-1] + (1 - lam) * sq_returns[t-1]
    return ewma

# 对比输出
sma_var = sma_variance(returns, window=20)
ewma_var = ewma_variance(returns, lam=0.94)

print("SMA 最后一天方差:", round(sma_var[-1], 8))
print("EWMA 最后一天方差:", round(ewma_var[-1], 8))
个人经验:代码里 EWMA 的初始值我用了第一个平方收益率。更严谨的做法是用前几天的均值初始化,但实际效果差别不大。别在细节上钻牛角尖。

好了,移动平均模型就讲到这里。记住一句话:模型是工具,不是真理。SMA 和 EWMA 各有各的脾气,你得根据市场状态选。下次遇到波动率突变,试试 EWMA,你会感谢我的。


专注资料整理