波动率参数估计:日内波动率模式与U型曲线

做量化交易的朋友都知道,波动率这东西,看着简单,实则门道很深。Almgren-Chriss模型里,波动率参数直接决定了你的交易成本曲线长什么样。我刚开始用这个模型时,就吃过波动率估计不准的亏——明明算好的最优交易路径,实盘跑起来却完全不是那么回事。

今天咱们就聊聊,怎么把波动率这个参数给整明白。

日内波动率的U型曲线

你有没有观察过,A股市场开盘和收盘那会儿,价格波动特别剧烈?中间时段反而相对平稳。这不是错觉,这是全球金融市场普遍存在的现象——日内波动率的U型曲线。

为什么会这样?说白了,开盘时信息集中释放,隔夜消息、外围市场变化全堆在一起;收盘前呢,机构调仓、做市商平风险,交易量猛增。中间时段,大家该交易的都交易完了,市场进入相对均衡状态。

核心发现:日内波动率呈现明显的U型或J型模式,开盘和收盘时段波动率是午间时段的2-3倍。

我在项目中遇到过这样的情况:用全天平均波动率去跑AC模型,结果开盘时段下单太激进,冲击成本飙升;收盘时段又太保守,错过了流动性最好的窗口。后来我改成按时间段分别估计波动率,效果立竿见影。

基于已实现波动率的估计方法

传统的历史波动率,用日间收盘价算,太粗糙了。日内交易需要更精细的度量。我个人习惯用已实现波动率(Realized Volatility),它利用高频数据,把一天切成N个等长区间,每个区间算一个收益率,然后加总。

公式长这样:

RV = sqrt( Σ (r_i)^2 )

其中 r_i 是第 i 个区间的对数收益率。采样频率一般选5分钟或10分钟。太短了容易引入微观结构噪声,太长了又丢失日内细节。

我的经验:对于A股,5分钟采样是个不错的起点。如果是美股,流动性更好,可以试试1分钟。但要注意,采样频率不是越高越好——你想想看,买卖价差、订单簿跳动这些微观噪声,高频采样下会被放大。

具体实现上,我一般这样处理:

import numpy as np
import pandas as pd

def realized_volatility(price_series, freq='5T'):
    """
    计算已实现波动率
    price_series: 价格序列,时间索引
    freq: 重采样频率
    """
    # 重采样到指定频率,取最后一个价格
    resampled = price_series.resample(freq).last()
    # 计算对数收益率
    log_returns = np.log(resampled / resampled.shift(1))
    # 去掉NaN
    log_returns = log_returns.dropna()
    # 计算已实现波动率
    rv = np.sqrt(np.sum(log_returns ** 2))
    return rv

嗯,这里要注意:数据清洗很重要。我曾经因为没处理停牌时段的数据,算出来的波动率直接翻倍。建议先剔除非交易时段的数据,再对异常值做截断处理。

波动率预测模型:EWMA与GARCH

已实现波动率是历史数据,但AC模型需要的是未来一段时间的波动率预期。这就涉及到预测了。

我个人最常用的两个模型:EWMA和GARCH。

EWMA(指数加权移动平均)

EWMA的核心思想很简单:越近的数据权重越大。公式:

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

λ 是衰减因子,一般取0.94(日频数据)或0.97(高频数据)。这个参数怎么选?我建议用历史数据做滚动回测,选让预测误差最小的那个λ。

避坑指南:我曾经直接用RiskMetrics推荐的λ=0.94,结果在2015年股灾期间,模型完全跟不上波动率的变化。后来我改成自适应λ——市场波动大时降低λ,让模型反应更快。效果好了不少。

GARCH(1,1)模型

GARCH比EWMA多了一个长期均值回归的特性。公式:

σ²_t = ω + α * r²_{t-1} + β * σ²_{t-1}

参数估计一般用最大似然法。Python里用arch库就能搞定:

from arch import arch_model

def fit_garch(returns):
    """
    拟合GARCH(1,1)模型
    """
    model = arch_model(returns, vol='Garch', p=1, q=1)
    result = model.fit(disp='off')
    return result.params

# 使用示例
params = fit_garch(log_returns)
omega, alpha, beta = params['omega'], params['alpha[1]'], params['beta[1]']
print(f"ω={omega:.6f}, α={alpha:.4f}, β={beta:.4f}")

GARCH的好处是能捕捉波动率的聚集效应——大波动后面往往跟着大波动。但坏处是参数估计不稳定,尤其是样本量不够时。我建议至少用500个以上的数据点来拟合。

在AC模型中的应用

好了,波动率估计出来了,怎么用到Almgren-Chriss模型里?

AC模型的永久冲击成本公式里,波动率σ是核心输入:

永久冲击 = γ * σ * (交易量 / 总成交量)^δ

其中γ和δ是待估参数。我个人习惯把日内波动率分段处理:

  1. 把交易日分成开盘、上午、午间、下午、收盘五个时段
  2. 每个时段分别估计已实现波动率
  3. 用EWMA或GARCH预测下一交易日的时段波动率
  4. 代入AC模型,生成该时段的最优交易路径

实战建议:别用全天平均波动率去跑AC模型。我做过回测,分段波动率策略比平均波动率策略,冲击成本降低了约15%。

下面这张图展示了日内波动率的分段处理流程:

日内波动率分段处理流程 高频价格数据 按时间段分割(开盘/上午/午间/下午/收盘) 各时段已实现波动率(RV)计算 EWMA/GARCH预测下一交易日各时段波动率

最后说一句,波动率估计没有银弹。EWMA简单实用,GARCH理论更完备,但实盘中我经常两个模型都跑,取个加权平均。你想想看,模型再漂亮,不如实盘赚钱来得实在。

我的小技巧:每天收盘后,我会把当天的已实现波动率和模型预测值做个对比。如果偏差超过20%,第二天就手动调整参数。这种人工干预虽然不"量化",但确实能避免模型在极端行情下翻车。

好了,波动率这块就聊到这儿。记住一句话:波动率估计的精度,直接决定了AC模型的上限。别在这个环节偷懒。


公众号:蓝海资料掘金营,微信deep3321