实战案例六:机器学习预测短期价格波动辅助做市

做市商最怕什么?

怕方向做反,怕库存被套,怕波动突然放大把单子全吃掉。

我做了这么多年做市,发现一个规律:短期价格波动其实是有迹可循的。不是那种玄学的预测,而是基于订单流、盘口深度、成交量这些微观结构特征,可以训练出一个模型,帮我们提前几秒判断价格要往哪边跑。

这一章,我们就来搞一个实战案例:用机器学习预测未来1秒的价格方向,辅助做市策略调整报价。

为什么是1秒?

做市商的时间窗口很短。你想想看,挂单在盘口上,可能几百毫秒就被吃了。预测太远没意义,预测太近来不及反应。我个人习惯用1秒窗口,既能捕捉到微观动量,又留够了调单的时间。

我曾经试过预测5秒后的价格,结果发现模型精度和随机猜差不多。后来才明白,高频环境下的价格序列,超过3秒基本就是随机游走了。

特征工程:从原始数据中挖金子

模型好不好,特征说了算。我见过太多人直接把价格序列扔进LSTM,结果一塌糊涂。做市场景下,真正有用的特征是那些反映买卖力量对比的指标。

核心特征列表(我常用的):

  • 买卖价差(Spread):当前最优买价和卖价的差值,越小说明流动性越好
  • 订单簿不平衡(Order Book Imbalance):买一到买五的总量 vs 卖一到卖五的总量,比值越大说明买方越强
  • 成交量变化率:过去1秒成交量 vs 过去10秒平均成交量,捕捉放量信号
  • 价格动量:过去3笔成交的价格变化方向,连续上涨还是下跌
  • 大单出现频率:超过某个阈值的单子出现的次数,大单往往预示方向

嗯,这里要注意:特征不是越多越好。我踩过一个坑,把50多个特征全塞进去,结果模型过拟合得一塌糊涂,回测漂亮,实盘直接崩。后来我学乖了,只保留5-8个最核心的特征,反而更稳定。

模型选择:LightGBM 就够了

很多人一上来就上深度学习,其实没必要。做市场景下,数据量通常不会特别大(一天几万条样本),而且我们需要模型可解释——你得知道它为什么这么预测,才能决定要不要信它。

我个人推荐 LightGBM,原因有三:

  1. 训练速度快,调参方便
  2. 自带特征重要性,能告诉你哪个指标最管用
  3. 对缺失值和异常值比较鲁棒,实盘数据脏一点也能扛

我曾经用XGBoost做过一版,效果差不多但训练慢了一倍。后来就全面切到LightGBM了。

代码实战:从数据到模型

下面这段代码,是我在实盘环境中跑过的简化版。数据用的是Level2行情,包含逐笔成交和盘口快照。

import pandas as pd
import numpy as np
import lightgbm as lgb
from sklearn.model_selection import train_test_split

# 假设我们已经有了原始数据
# 包含字段:timestamp, bid_price, ask_price, bid_vol, ask_vol, trade_price, trade_vol

def extract_features(df):
    """提取做市相关的特征"""
    features = pd.DataFrame()
    features['timestamp'] = df['timestamp']
    
    # 买卖价差
    features['spread'] = df['ask_price'] - df['bid_price']
    
    # 订单簿不平衡
    features['imbalance'] = df['bid_vol'] / (df['ask_vol'] + 1e-8)
    
    # 过去1秒成交量
    features['volume_1s'] = df['trade_vol'].rolling(10, min_periods=1).sum()
    
    # 过去10秒平均成交量
    features['volume_10s_avg'] = df['trade_vol'].rolling(100, min_periods=1).mean()
    
    # 成交量变化率
    features['vol_ratio'] = features['volume_1s'] / (features['volume_10s_avg'] + 1e-8)
    
    # 价格动量(过去3笔成交的方向)
    price_diff = df['trade_price'].diff(3)
    features['momentum'] = np.sign(price_diff)
    
    return features.dropna()

# 构造标签:未来1秒价格是否上涨
def create_labels(df, lookahead=10):
    """lookahead=10 对应100ms*10=1秒"""
    future_price = df['trade_price'].shift(-lookahead)
    label = (future_price > df['trade_price']).astype(int)
    return label

# 加载数据
df = pd.read_parquet('level2_data.parquet')
features = extract_features(df)
labels = create_labels(df)

# 训练集/测试集划分
X_train, X_test, y_train, y_test = train_test_split(
    features.drop('timestamp', axis=1), 
    labels, 
    test_size=0.2, 
    shuffle=False  # 时间序列不能乱序
)

# 训练LightGBM模型
model = lgb.LGBMClassifier(
    n_estimators=200,
    max_depth=5,
    learning_rate=0.05,
    class_weight='balanced'
)
model.fit(X_train, y_train)

# 查看特征重要性
importance = pd.DataFrame({
    'feature': X_train.columns,
    'importance': model.feature_importances_
}).sort_values('importance', ascending=False)

print(importance.head())

小技巧:训练时记得设置 shuffle=False。时间序列数据一旦打乱顺序,模型会学到未来信息,回测结果会虚高。我刚开始做的时候犯过这个错,回测准确率80%,实盘直接腰斩。

如何用预测结果辅助做市?

模型预测出未来1秒价格要上涨,我们该怎么做?

不是简单地把卖单撤掉或者追涨。做市的核心是调整报价的偏向性

我的策略逻辑:

  • 预测上涨概率 > 0.7:把卖单价格上调2个tick,买单价格上调1个tick。这样既能吃到上涨的利润,又不会完全放弃买单
  • 预测下跌概率 > 0.7:反过来,买单下调2个tick,卖单下调1个tick
  • 概率在0.4-0.6之间:保持中性报价,不调整
  • 概率 < 0.3:说明模型很确定方向,可以激进一点,单边调整3个tick

说白了,模型不是用来做方向性交易的,而是帮我们动态调整报价的偏移量。这样即使预测错了,损失也有限——因为我们的单子还在盘口上,只是位置差了几个tick。

避坑指南:实盘中的三个大坑

模型在回测里跑得再好,上了实盘都可能翻车。我总结三个最常见的坑:

坑一:特征延迟

你用的特征,在实盘里可能已经过时了。比如订单簿不平衡,从数据到达你的机器到模型输出预测,中间可能有几十毫秒的延迟。我曾经没注意这个,结果模型用的都是旧数据,预测准确率直接掉到50%以下。

解决办法:在回测时就要模拟延迟,给特征加上10-50ms的随机延迟再训练。

坑二:模型过拟合到微观结构

有些特征在特定市场环境下特别有效,比如大单出现频率。但换个品种或者换个时间段,这个特征可能就失效了。我见过一个模型,在BTC永续合约上跑得飞起,换到ETH上直接崩。

解决办法:多品种、多时间段交叉验证。如果模型只在某个品种上有效,那就要小心了。

坑三:预测准确率不等于赚钱

模型预测对了60%,但可能赚的钱还没手续费多。因为做市商的利润来自买卖价差,而不是方向性收益。如果模型让你频繁调整报价,交易成本会吃掉所有利润。

解决办法:在回测中一定要扣除手续费和滑点,用真实的PnL来评估模型,而不是准确率。

可视化:模型决策流程

下面这张图,展示了整个流程:从原始行情数据,到特征提取,再到模型预测,最后影响做市策略的报价调整。

机器学习预测辅助做市 - 决策流程 Level2 行情数据 逐笔成交 + 盘口快照 特征工程 价差 / 不平衡 / 动量 LightGBM 模型 预测未来1秒方向 报价 调整 反馈:调整后的报价影响后续行情 关键时间线: 1. 每100ms接收一次盘口快照(10Hz) 2. 特征计算 + 模型推理耗时约 5-15ms 3. 报价调整指令发出到交易所确认约 10-30ms 4. 总延迟控制在 50ms 以内,不影响做市效果 注:以上延迟为国内期货交易所实测数据,不同市场可能有差异

回测结果怎么看?

模型训练完了,回测跑完了,怎么判断它有没有用?

我一般看三个指标:

指标 说明 合格线 优秀线
预测准确率 模型判断方向是否正确 > 55% > 62%
夏普比率提升 加入模型后 vs 纯做市策略的夏普提升 > 0.3 > 0.8
最大回撤降低 模型是否帮助避开了大波动 降低 > 10% 降低 > 25%

说实话,准确率能到60%以上就已经很好了。毕竟预测的是未来1秒的价格方向,随机猜也有50%。关键是看夏普比率有没有提升,这才是赚钱的核心。

我的经验:模型最大的价值不是提高胜率,而是降低极端情况下的亏损。比如突然有大单砸盘,模型能提前半秒感知到,帮你把买单撤远一点。这半秒的差距,可能就是几千块的盈亏。

好了,这一章的内容就到这里。机器学习预测短期波动,说白了就是给做市策略加了一双「预判」的眼睛。它不会让你一夜暴富,但能让你在波动中活得更久。


交易系统化学习资料 微信Strategy888888