4、成交量预测模型:历史均值法、时间序列模型(ARIMA)、机器学习预测(XGBoost)、实时修正机制

成交量预测,说白了就是猜未来几分钟或几小时能成交多少股。你想想看,VWAP 的核心是「价格×成交量」的累计加权平均,如果连成交量都猜不准,那后面的执行方案全是空中楼阁。

我在做自营团队的时候,一开始也踩过坑——直接用历史均值去算,结果遇到财报发布日,预测偏差能到 40% 以上。后来慢慢摸索出这套组合拳:简单方法兜底、复杂模型提精度、实时修正保命。今天我把这套东西拆开讲给你听。

4.1 历史均值法:最朴素的基线模型

历史均值法,就是拿过去 N 天的同一时段成交量取平均。比如你想预测明天 10:00-10:05 这 5 分钟的成交量,就把过去 20 个交易日同一 5 分钟窗口的成交量加起来除以 20。

代码实现很简单:

import pandas as pd

def historical_mean_volume(volume_df, window_minutes=5, lookback_days=20):
    """
    volume_df: DataFrame, 包含 datetime 和 volume 两列
    window_minutes: 预测窗口长度(分钟)
    lookback_days: 回溯天数
    """
    # 将时间对齐到分钟级别
    volume_df['minute'] = volume_df['datetime'].dt.floor('T')
    
    # 按分钟和日期分组
    volume_df['date'] = volume_df['datetime'].dt.date
    minute_vol = volume_df.groupby(['date', 'minute'])['volume'].sum().reset_index()
    
    # 取最近 lookback_days 天的数据
    recent_dates = minute_vol['date'].unique()[-lookback_days:]
    recent_data = minute_vol[minute_vol['date'].isin(recent_dates)]
    
    # 按分钟聚合求均值
    mean_vol = recent_data.groupby('minute')['volume'].mean()
    
    return mean_vol

这个方法的好处是:快、稳、不挑数据。我在做回测框架的 MVP 版本时,就用它做基线。但你要记住——它假设市场行为是重复的,遇到异常行情直接崩。

避坑指南:我曾经用纯历史均值法跑一个 ETF 的 VWAP 策略,结果那天突然有大量期权到期,成交量瞬间放大 3 倍。我的预测值还停留在过去 20 天的平均水平,导致算法下单节奏完全跟不上。从那以后,我给自己定了个规矩:历史均值只能做兜底,不能做唯一依赖

4.2 时间序列模型(ARIMA):捕捉趋势与周期性

ARIMA 比历史均值聪明一点。它能捕捉到成交量的自相关性——比如今天 10:00 的成交量高,明天同一时间大概率也高。它还能处理趋势(比如成交量逐渐放大)和季节性(比如午盘成交量萎缩)。

ARIMA 有三个参数:p(自回归阶数)、d(差分阶数)、q(移动平均阶数)。我个人习惯用 AIC 准则自动选参:

from statsmodels.tsa.arima.model import ARIMA
import itertools

def auto_arima_volume(series, max_p=5, max_d=2, max_q=5):
    """
    series: 时间序列,按分钟对齐的成交量
    返回最优 (p,d,q) 和模型
    """
    best_aic = float('inf')
    best_order = None
    best_model = None
    
    for p, d, q in itertools.product(range(max_p+1), range(max_d+1), range(max_q+1)):
        try:
            model = ARIMA(series, order=(p, d, q))
            fitted = model.fit()
            if fitted.aic < best_aic:
                best_aic = fitted.aic
                best_order = (p, d, q)
                best_model = fitted
        except:
            continue
    
    return best_order, best_model

实际项目中,ARIMA 对 5-15 分钟的短窗口预测效果不错。但有个问题——它本质上是线性模型,遇到成交量突变(比如大单砸盘)就傻眼了。

我的经验:ARIMA 适合用在流动性好的股票上,比如沪深 300 成分股。对于小盘股,成交量经常出现「零成交」的断层,ARIMA 的差分运算会出 NaN,这时候我一般会先做插值处理。

4.3 机器学习预测(XGBoost):非线性建模利器

XGBoost 是我目前在实盘中最常用的模型。它能吃进大量特征:历史成交量、价格波动率、买卖盘口深度、行业板块热度、甚至隔夜美股涨跌幅。说白了,它把能想到的因子全塞进去,让树模型自己学。

特征工程是关键。我一般会构造这几类特征:

特征类别 具体特征 说明
历史成交量 过去 1/5/10/20 分钟成交量 短期和中期记忆
价格衍生 收益率、波动率、VWAP 偏离度 反映市场情绪
盘口数据 买卖 1-5 档挂单量差、委比 微观结构信号
时间特征 分钟序号、是否开盘/收盘、星期几 周期性模式
外部因子 股指期货升贴水、行业 ETF 资金流 宏观联动

训练代码示例:

import xgboost as xgb
from sklearn.model_selection import train_test_split

def train_volume_xgb(features_df, target_col='volume_next_5min'):
    """
    features_df: 包含所有特征和目标的 DataFrame
    """
    X = features_df.drop(columns=[target_col, 'datetime'])
    y = features_df[target_col]
    
    X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, shuffle=False)
    
    model = xgb.XGBRegressor(
        n_estimators=200,
        max_depth=6,
        learning_rate=0.05,
        subsample=0.8,
        colsample_bytree=0.8,
        early_stopping_rounds=20,
        eval_metric='mae'
    )
    
    model.fit(
        X_train, y_train,
        eval_set=[(X_val, y_val)],
        verbose=False
    )
    
    return model
核心要点:XGBoost 的预测精度通常比 ARIMA 高 15-30%,但代价是计算开销大。我在实盘中会每 5 分钟重新训练一次(增量训练),而不是每次从头训练。另外,特征要定期做重要性排序,把没用的特征剔除,否则模型会过拟合。

4.4 实时修正机制:让预测跟上市场节奏

模型再准,也架不住市场突变。实时修正机制就是给预测模型装一个「反馈回路」——用最近几分钟的实际成交量去修正未来的预测值。

我常用的修正方法有两种:

  1. 误差反馈修正:计算过去 5 分钟的实际成交量与预测值的偏差比例,然后用这个比例去调整未来 5 分钟的预测。比如实际比预测高了 10%,就把未来预测也上调 10%。
  2. 卡尔曼滤波融合:把模型预测作为先验值,把实时观测到的成交量作为观测值,用卡尔曼滤波做最优融合。这个方法更平滑,适合高频场景。

误差反馈修正的代码实现:

def realtime_correction(predicted_vol, actual_vol, correction_window=5, alpha=0.3):
    """
    predicted_vol: 模型预测的成交量序列
    actual_vol: 实际观测到的成交量序列
    correction_window: 用于计算误差的窗口长度
    alpha: 平滑系数,0-1 之间
    """
    if len(actual_vol) < correction_window:
        return predicted_vol  # 数据不足,不修正
    
    # 计算最近 correction_window 的平均误差比例
    recent_errors = []
    for i in range(-correction_window, 0):
        if predicted_vol[i] != 0:
            error = (actual_vol[i] - predicted_vol[i]) / predicted_vol[i]
            recent_errors.append(error)
    
    if not recent_errors:
        return predicted_vol
    
    # 指数加权平均,越近的误差权重越大
    weights = [alpha * (1-alpha)**k for k in range(len(recent_errors)-1, -1, -1)]
    weights = [w/sum(weights) for w in weights]
    
    correction_factor = 1 + sum(e * w for e, w in zip(recent_errors, weights))
    
    # 限制修正幅度,防止过度修正
    correction_factor = max(0.5, min(2.0, correction_factor))
    
    return predicted_vol * correction_factor
注意:修正幅度一定要加限幅器。我见过有人把修正因子设到 3 倍,结果遇到一次异常大单,预测值直接飞了,导致算法疯狂追单。后来我加了 max(0.5, min(2.0, correction_factor)) 这个限制,再也没出过问题。

4.5 四种方法的对比与选择

我把这四种方法放在一起做了个对比表,方便你根据场景选择:

方法 精度 计算开销 适用场景 缺点
历史均值法 低(MAE 15-25%) 极低 流动性好的大盘股、平稳行情 无法应对突变
ARIMA 中(MAE 10-18%) 短窗口预测、有周期性的品种 线性假设、零成交断层
XGBoost 高(MAE 5-12%) 中高 多因子场景、需要高精度的策略 特征工程复杂、过拟合风险
实时修正 提升 10-30% 极低 所有场景的补充 不能单独使用

我个人在实盘中的组合是:XGBoost 做主模型 + 实时修正做后处理。历史均值法和 ARIMA 作为备用模型,当 XGBoost 的特征数据缺失或模型训练失败时自动切换。

一个小技巧:你可以把四种方法的预测结果做一个加权集成。权重根据最近 1 小时各模型的预测误差动态调整。我试过,集成后的 MAE 比最好的单模型还能再降 3-5%。

4.6 本章知识体系总览

下面这张图把成交量预测的完整流程串起来了。从数据输入到模型选择,再到实时修正,最后输出给 VWAP 执行引擎:

成交量预测模型知识体系 历史成交量数据 历史均值法 基线模型 ARIMA 时间序列 XGBoost 机器学习 实时修正机制 反馈回路 模型集成与加权 预测成交量输出 → 输入 VWAP 执行引擎

嗯,到这里成交量预测的四种方法就讲完了。记住一个原则:没有最好的模型,只有最合适的组合。下一章我们会把这些预测值喂给 VWAP 执行算法,看看怎么把「预测」变成「交易」。


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