4. 波动率特征:历史波动率、指数加权波动率(EWMA)、已实现波动率、波动率锥
波动率是金融风险管理的核心变量,它直接度量资产收益率的离散程度。在组合风险归因训练集中,波动率特征不仅用于刻画资产自身的风险水平,更是构建协方差矩阵、计算风险贡献和压力测试的基础输入。本节将系统讲解四种最常用的波动率特征:历史波动率、指数加权波动率(EWMA)、已实现波动率以及波动率锥,并给出它们在特征工程中的具体实现与适用场景。
核心要点:波动率特征的选择直接影响风险模型的时效性与准确性。历史波动率适合长期稳定估计,EWMA 擅长捕捉近期变化,已实现波动率利用高频数据提升精度,波动率锥则提供多时间尺度下的波动率分布视角。
4.1 历史波动率(Historical Volatility, HV)
历史波动率是最基础的波动率估计方法,它基于过去一段固定窗口内的收益率标准差,并通常进行年化处理。其计算公式为:
# 历史波动率计算示例(Python)
import numpy as np
import pandas as pd
def historical_volatility(returns, window=21, annualize_factor=252):
"""
计算历史波动率(年化)
:param returns: 日收益率序列(Series)
:param window: 滚动窗口长度(交易日)
:param annualize_factor: 年化因子(日数据用252)
:return: 年化历史波动率序列
"""
rolling_std = returns.rolling(window=window).std()
hv = rolling_std * np.sqrt(annualize_factor)
return hv
# 示例:使用过去21个交易日计算年化波动率
hv_series = historical_volatility(returns, window=21)
| 参数 | 典型值 | 说明 |
|---|---|---|
| 窗口长度 | 21 / 63 / 252 | 分别对应1个月、1个季度、1年 |
| 年化因子 | 252(日) / 52(周) / 12(月) | 将日波动率转换为年化波动率 |
| 去均值方式 | 样本标准差 / 总体标准差 | 样本标准差(ddof=1)更常用 |
特征工程建议:在训练集中,可以同时生成多个窗口的历史波动率(如 HV_21、HV_63、HV_252),作为不同时间尺度下的风险特征输入模型。窗口越短,波动率对近期市场变化的反应越快,但噪声也越大。
4.2 指数加权波动率(EWMA)
EWMA 通过衰减因子 λ 赋予近期收益率更高的权重,从而更灵敏地捕捉波动率的动态变化。其递推公式为:
σ²t = λ · σ²t-1 + (1 - λ) · r²t-1
其中 λ 通常取 0.94(日数据)或 0.97(周数据),这是 RiskMetrics 框架的经典参数。
def ewma_volatility(returns, lambda_=0.94, annualize_factor=252):
"""
计算 EWMA 波动率(年化)
:param returns: 日收益率序列
:param lambda_: 衰减因子(0 < lambda_ < 1)
:return: 年化 EWMA 波动率序列
"""
variance = np.zeros_like(returns)
variance[0] = returns.iloc[0] ** 2
for t in range(1, len(returns)):
variance[t] = lambda_ * variance[t-1] + (1 - lambda_) * (returns.iloc[t-1] ** 2)
ewma_vol = np.sqrt(variance) * np.sqrt(annualize_factor)
return pd.Series(ewma_vol, index=returns.index)
ewma_series = ewma_volatility(returns, lambda_=0.94)
| λ 取值 | 半衰期(交易日) | 适用场景 |
|---|---|---|
| 0.94 | 约 11 天 | 日频风险监控(RiskMetrics 标准) |
| 0.97 | 约 23 天 | 周频或更平滑的波动率估计 |
| 0.99 | 约 69 天 | 接近等权历史波动率,长期趋势 |
注意:EWMA 对初始值敏感,建议使用前 20-30 个交易日的方差作为初始方差估计,或直接丢弃前期的预热期数据。在特征工程中,EWMA 通常作为“短期波动率”特征与历史波动率并列使用。
4.3 已实现波动率(Realized Volatility, RV)
已实现波动率利用日内高频收益率数据,通过求和平方日内收益率来估计当日波动率,相比日间波动率具有更高的精度。其标准形式为:
RVt = √( Σi=1M r²t,i )
其中 M 为日内采样次数,rt,i 为第 t 天第 i 个区间内的对数收益率。
def realized_volatility(intraday_prices, sampling_freq='5min'):
"""
计算已实现波动率(日频)
:param intraday_prices: 日内价格序列(DatetimeIndex)
:param sampling_freq: 采样频率,如 '5min', '15min', '30min'
:return: 日度已实现波动率
"""
# 重采样到指定频率,取最后一个价格
sampled = intraday_prices.resample(sampling_freq).last()
# 计算对数收益率
log_returns = np.log(sampled / sampled.shift(1)).dropna()
# 每日求和平方收益率
daily_rv = (log_returns ** 2).resample('D').sum()
# 开方得到波动率
rv = np.sqrt(daily_rv)
return rv
# 假设有5分钟频率的日内价格数据
rv_daily = realized_volatility(intraday_prices, sampling_freq='5min')
| 采样频率 | 日内样本数(M) | 优缺点 |
|---|---|---|
| 1 分钟 | 约 390 | 精度高,但易受微观结构噪声影响 |
| 5 分钟 | 约 78 | 平衡精度与噪声,最常用 |
| 15 分钟 | 约 26 | 噪声更小,但可能丢失日内波动细节 |
| 30 分钟 | 约 13 | 适合流动性较差的资产 |
特征工程价值:已实现波动率是高频数据特征的代表,在训练集中可以作为“真实波动率代理变量”用于监督学习中的标签构造,或作为强预测特征输入模型。对于无法获取高频数据的资产,可以使用已实现波动率的低频近似(如使用 30 分钟线)。
4.4 波动率锥(Volatility Cone)
波动率锥是一种可视化工具,它展示同一资产在不同时间尺度(如 5 天、21 天、63 天、252 天)下的波动率分布特征(通常包括中位数、分位数)。通过波动率锥,可以直观判断当前波动率在历史分布中的相对位置,识别波动率是否处于极端水平。
def volatility_cone(returns, windows=[5, 21, 63, 126, 252], percentiles=[0.05, 0.25, 0.50, 0.75, 0.95]):
"""
计算波动率锥数据
:param returns: 日收益率序列
:param windows: 滚动窗口列表
:param percentiles: 分位数列表
:return: DataFrame,行=窗口,列=分位数
"""
cone_data = {}
for w in windows:
hv = returns.rolling(window=w).std() * np.sqrt(252)
cone_data[w] = np.percentile(hv.dropna(), q=[p*100 for p in percentiles])
cone_df = pd.DataFrame(cone_data, index=[f'{p*100:.0f}%' for p in percentiles]).T
cone_df.index.name = 'Window'
return cone_df
cone_df = volatility_cone(returns)
print(cone_df)
训练集构造技巧:波动率锥本身不直接作为特征,但可以从中衍生出“当前波动率在锥中的分位数位置”作为特征。例如,计算当前 21 天波动率在历史 21 天波动率分布中的百分位排名,作为“波动率相对水平”指标。
4.5 特征工程综合对比
下表从多个维度对比四种波动率特征,帮助你在训练集中做出合理选择:
| 特征类型 | 数据频率 | 时效性 | 噪声水平 | 计算复杂度 | 典型特征名称 |
|---|---|---|---|---|---|
| 历史波动率 | 日频 | 低(等权滞后) | 中等 | 低 | hv_21, hv_63, hv_252 |
| EWMA 波动率 | 日频 | 高(指数衰减) | 中等 | 低 | ewma_94, ewma_97 |
| 已实现波动率 | 日内高频 | 最高(当日估计) | 较低(采样适当) | 中 | rv_5min, rv_15min |
| 波动率锥分位数 | 日频(衍生) | 中等 | 低(分布统计量) | 中 | hv_21_pctile, hv_63_pctile |
训练集特征组合建议:
- 基础组合:hv_21 + ewma_94 + rv_5min(覆盖短期、中期、高频三个维度)
- 增强组合:在上述基础上加入 hv_63、hv_252 以及波动率锥分位数特征(hv_21_pctile、hv_63_pctile)
- 衍生特征:波动率斜率(hv_21 / hv_63)、波动率冲击(rv_5min / ewma_94)等比值特征
4.6 实现注意事项
- 数据对齐:所有波动率特征在时间轴上必须严格对齐,避免未来信息泄露。使用
.shift(1)确保特征基于历史数据计算。 - 缺失值处理:滚动窗口初期会产生 NaN,建议使用前向填充或直接丢弃预热期数据。
- 年化一致性:不同时间尺度的波动率必须统一年化,才能在同一尺度下比较。
- 极端值处理:波动率序列可能出现极端值(如市场崩盘日),建议进行 winsorize 或对数变换后再输入模型。
- 多资产并行:对于组合风险归因,需要对组合内所有资产同时计算上述波动率特征,并保持时间索引一致。
常见陷阱:不要将未来波动率信息泄露到训练集中。例如,计算已实现波动率时,必须使用当天的日内数据,但作为特征时只能使用 前一天的已实现波动率 来预测当天的风险。始终牢记特征工程的时间顺序约束。