波动率建模:已实现波动率、跳跃波动率、日内波动率模型、波动率预测
波动率这东西,做量化的人天天挂在嘴边。但说实话,很多人对它的理解还停留在「标准差」那个层面。我刚开始做高频交易那会儿,也以为波动率就是算个方差完事。直到有一次,我拿日线数据算出来的波动率去回测策略,结果实盘亏得我头皮发麻——后来才发现,日内那些剧烈的价格跳动,全被日线数据给「平均」掉了。
所以今天咱们聊的,是真正能用在实战里的波动率建模。不是教科书上那种理论推导,而是你写代码时能直接调用的方法。
核心观点:波动率不是一成不变的,它分「已实现」和「隐含」,分「连续」和「跳跃」。搞不清楚这些,你的风控模型就是纸糊的。
一、已实现波动率:高频数据的基石
已实现波动率(Realized Volatility, RV)说白了,就是把一天内所有收益率的平方加起来。公式很简单:
RV = Σ (r_i)^2 (i = 1 to N)
其中 r_i 是第 i 个时间间隔的收益率,N 是日内采样点数。
我习惯用 5 分钟频率来计算 RV。为什么是 5 分钟?太短了有微观结构噪声,太长了又丢失日内信息。这个平衡点,是我在回测了十几只股票后找到的。
来个 Python 代码示例:
import pandas as pd
import numpy as np
def realized_volatility(price_series, freq='5T'):
"""
计算已实现波动率
price_series: 价格序列(带时间戳)
freq: 重采样频率,默认5分钟
"""
# 重采样到指定频率
resampled = price_series.resample(freq).last()
# 计算对数收益率
log_returns = np.log(resampled / resampled.shift(1))
# 计算已实现波动率
rv = np.sum(log_returns ** 2)
return np.sqrt(rv * 252) # 年化
实战技巧:我建议你同时计算多个频率的RV(1分钟、5分钟、15分钟),然后取中位数。这样能有效避免单个频率的噪声干扰。
二、跳跃波动率:别被「假波动」骗了
你有没有遇到过这种情况?某只股票突然暴跌,你以为是重大利空,结果两分钟后价格又拉回来了。这种「闪崩」就是典型的跳跃波动。
跳跃波动率(Jump Volatility)和连续波动率(Continuous Volatility)的区别在于:连续波动是市场正常交易产生的,跳跃波动是突发事件导致的。
怎么分离它们?我常用的方法是「双幂次变差」(Bipower Variation):
def bipower_variation(returns):
"""
计算双幂次变差(连续波动部分)
"""
n = len(returns)
mu1 = np.sqrt(2 / np.pi) # 标准正态分布的一阶绝对矩
bpv = (np.pi / 2) * np.sum(np.abs(returns[1:]) * np.abs(returns[:-1])) / (n - 1)
return bpv
然后跳跃波动率就是:
jump_variation = max(0, rv - bipower_variation(returns))
我曾经在分析某只妖股时,发现它的跳跃波动率占比高达 40%。这意味着什么?意味着如果你用普通波动率模型去定价期权,会严重高估它的价值。
避坑指南:跳跃波动率不能为负。如果计算出来是负数,说明你的数据频率有问题,或者采样间隔太短。我建议把负值直接截断为0。
三、日内波动率模型:U型曲线的秘密
日内波动率有个很有意思的规律——它通常呈 U 型。开盘和收盘时波动大,中午休息时波动小。这个现象在 A 股尤其明显。
我常用的日内波动率模型是「周期条件异方差模型」(Periodic GARCH):
def intraday_volatility_pattern(intraday_returns, n_periods=48):
"""
计算日内波动率模式
n_periods: 日内分段数(5分钟一段,一天48段)
"""
# 计算每个时间段的平均波动率
pattern = np.zeros(n_periods)
for i in range(n_periods):
period_returns = intraday_returns[i::n_periods]
pattern[i] = np.std(period_returns)
# 归一化
pattern = pattern / np.mean(pattern)
return pattern
这个模式有什么用?举个例子:如果你在做高频做市策略,中午时段波动率低,你的买卖价差就应该收窄。否则你会被高频套利者反复收割。
我记得有一次帮一家私募优化算法交易,他们发现下午 2:30 之后滑点特别大。我一看日内波动率曲线,好家伙,那个时段正好是波动率飙升的拐点。后来我们调整了订单切片策略,把大单拆得更细,滑点直接降了 30%。
四、波动率预测:HAR-RV 模型
预测波动率,我个人最推荐的是 HAR-RV 模型(Heterogeneous Autoregressive model for Realized Volatility)。它简单、有效、可解释性强。
核心思想:不同时间频率的投资者行为不同。日频交易者看 1 天,周频交易者看 5 天,月频交易者看 22 天。把这些因素都考虑进去:
def har_rv_forecast(rv_daily, rv_weekly, rv_monthly, params):
"""
HAR-RV 模型预测
params: [beta0, beta1, beta2, beta3]
"""
beta0, beta1, beta2, beta3 = params
forecast = beta0 + beta1 * rv_daily + beta2 * rv_weekly + beta3 * rv_monthly
return forecast
参数估计用 OLS 就行。我习惯用过去 252 个交易日的数据滚动估计,每天更新一次参数。
经验之谈:HAR-RV 模型在预测 1-5 天的波动率时效果最好。超过 10 天,它的预测能力会急剧下降。如果你想预测更长期,建议改用 GARCH 族模型。
五、知识体系总览
说了这么多,咱们用一张图来梳理一下整个波动率建模的知识体系:
六、实战中的注意事项
最后,分享几个我在实战中踩过的坑:
- 数据清洗比模型更重要。 我曾经用了一周时间调 HAR-RV 的参数,结果发现是数据里有几个异常值。清洗之后,模型效果直接翻倍。
- 不要迷信复杂的模型。 我见过有人用深度学习预测波动率,效果还不如简单的 HAR-RV。为什么?因为波动率本身有很强的自相关性,线性模型已经能捕捉大部分信息。
- 注意市场微观结构噪声。 高频数据里充满了买卖价差、订单簿不平衡等噪声。如果你不做预处理,算出来的 RV 会严重偏大。
我的建议:刚开始做波动率建模,先跑通 RV 和 HAR-RV 这两个基础模型。等你对数据有了感觉,再慢慢加入跳跃波动、日内模式这些高级内容。别一上来就想搞个大新闻,稳扎稳打才是正道。
好了,波动率建模这块就聊到这儿。代码都给你了,回去跑一跑,看看你的股票池里,哪些是「老实人」(连续波动为主),哪些是「戏精」(跳跃波动占比高)。