跳到主要内容

波动率估计:历史 / EWMA / 已实现

直觉

「波动率」就是收益率的离散程度,是风险的代名词。但「怎么算」有好几种,结论可能差很多:历史波动率看一段固定窗口的方差;EWMA 让近期波动权重更大、能快速响应;已实现波动率用高频数据累积。本节对比三种。

三种估计

1. 历史波动率

过去 NN 期收益的样本标准差,年化乘 252\sqrt{252}

σt=1N1i(rtirˉ)2252\sigma_t = \sqrt{\frac{1}{N-1}\sum_{i}(r_{t-i}-\bar r)^2}\cdot\sqrt{252}

2. EWMA 波动率(RiskMetrics)

让方差呈指数衰减,近期冲击权重更大

σt2=λσt12+(1λ)rt12,λ0.94\sigma_t^2 = \lambda\,\sigma_{t-1}^2 + (1-\lambda)\,r_{t-1}^2, \qquad \lambda\approx 0.94

3. 已实现波动率

一段时间内平方收益的累加(高频视角的离散近似):

RVt=iri2\text{RV}_t = \sqrt{\sum_{i} r_i^2}
「人话」解释:为什么要分这几种?

历史波动率简单稳定,但「反应慢」——大跌之后还要等满 NN 天才体现。 EWMA 用衰减权重,大跌当天方差就跳起来,更适合风控实时跟踪。 已实现波动率用更细颗粒的收益平方和,理论上最贴近「真实」波动,但需要高频数据。 本书日频数据下,历史与 EWMA 最好对比。

可运行案例:三种波动率并排

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv('/data/spy_daily.csv', parse_dates=['date']).set_index('date')
r = np.log(df['close'] / df['close'].shift(1)).dropna()

# 1) 历史波动率(20日窗口年化)
hist_vol = r.rolling(20).std(ddof=0) * np.sqrt(252)

# 2) EWMA 波动率(λ=0.94) 年化
lam = 0.94
ewma_var = (r**2).ewm(alpha=1-lam, adjust=False).mean()
ewma_vol = np.sqrt(ewma_var) * np.sqrt(252)

# 3) 已实现波动率(20日内平方收益和开根, 年化)
realized = np.sqrt((r**2).rolling(20).sum()) * np.sqrt(252)

vol = pd.DataFrame({'历史': hist_vol, 'EWMA': ewma_vol, '已实现': realized})
print("波动率(年化)描述:"); print(vol.describe().round(3))

vol.plot(figsize=(9, 3.8))
plt.title("三种波动率估计对比"); plt.ylabel("年化波动率")
plt.tight_layout(); plt.show()

动手改一改

λ\lambda 从 0.94 调到 0.99(衰减更慢)——EWMA 曲线会变得更平滑、对冲击反应迟钝;调到 0.80 则极其敏感。这就是「记忆长度」。

小结

  • 历史波动率:固定窗口标准差,稳定但滞后;
  • EWMA:指数衰减,λ0.94\lambda\approx0.94,响应快,风控常用;
  • 已实现波动率:平方收益累加,贴近真实但需高频数据。