第二十六章:冲击成本前沿:机器学习模型、深度学习模型、图神经网络

各位,欢迎来到冲击成本建模的「前沿阵地」。

前面我们聊了那么多传统模型,从线性到非线性,从AC到Almgren-Chriss。说实话,这些模型在大多数场景下够用了。但如果你做高频交易,或者处理的是流动性极差的资产,你会发现传统模型开始「力不从心」。为什么?因为市场结构太复杂了,订单流之间的相互作用,远不是几条曲线能拟合的。

今天,我们就来聊聊怎么用机器学习、深度学习,甚至图神经网络来干这件事。我个人觉得,这是冲击成本建模未来三到五年的主要演进方向。

1. 为什么传统模型不够用了?

先说说痛点。传统模型假设市场是「均匀」的——订单流随机到达,价格变化与成交量成某种函数关系。但真实市场呢?

  • 订单流是「自相关」的:一个大单进来,后面往往跟着更多单子。
  • 微观结构噪声很大:买卖价差、订单簿厚度,这些细节传统模型很难捕捉。
  • 市场状态会切换:平静期和恐慌期,冲击成本完全不是一个量级。

说白了,传统模型是在「平均意义」上做预测。而机器学习模型,可以学到更精细的模式。

核心观点:机器学习不是要替代传统模型,而是在传统模型的基础上,加入更多特征,提升预测精度。我习惯把传统模型的结果作为「基准特征」,再让模型去学习残差。

2. 机器学习模型:从特征工程开始

我们先从最经典的机器学习模型说起。我个人在项目中用得最多的是梯度提升树(XGBoost、LightGBM)。为什么?因为它对特征工程的要求相对低,而且能处理非线性关系。

2.1 特征工程怎么做?

冲击成本预测的特征,我一般分成三类:

  1. 订单特征:订单大小(相对于平均成交量)、订单方向、订单类型(市价单/限价单)。
  2. 市场状态特征:当前买卖价差、订单簿深度(前5档的挂单量)、最近1分钟的成交量、波动率。
  3. 时序特征:过去N笔交易的成交价格序列、过去N笔订单的到达间隔。

嗯,这里要注意:特征不是越多越好。我曾经犯过一个错误,把过去100笔交易的价格都作为特征,结果模型过拟合得一塌糊涂。后来我改用了一些统计量,比如均值、标准差、偏度,效果反而更好。

2.2 模型训练与评估

训练时,我建议用滚动时间窗口来划分训练集和测试集。千万别随机打乱数据,时间序列数据一旦打乱,就相当于「偷看未来」了。

# 伪代码示例:滚动时间窗口划分
train_start = '2024-01-01'
train_end = '2024-06-30'
test_start = '2024-07-01'
test_end = '2024-07-31'

# 训练模型
model = xgb.XGBRegressor()
model.fit(X_train, y_train)

# 预测
y_pred = model.predict(X_test)

# 评估指标:除了MSE,我还会看方向准确率
# 即预测的冲击成本方向(正/负)与实际是否一致

小技巧:评估时,别只看R²。对于冲击成本,我更关注「极端值预测」的准确性。你可以把测试集按实际冲击成本大小分成10组,看每组预测误差的均值。如果模型在最大冲击成本那组误差很大,说明它没学到尾部风险。

3. 深度学习模型:捕捉时序依赖

机器学习模型有个缺点:它把每个样本当作独立的。但冲击成本有明显的时序依赖——前一秒的订单流会影响下一秒的冲击成本。这时候,深度学习就派上用场了。

3.1 LSTM与GRU

我最常用的是LSTM。为什么?因为它能记住长期依赖。比如,一个大单进来后,市场可能需要几分钟才能恢复流动性。LSTM可以捕捉这种「记忆效应」。

# 简单的LSTM模型结构
model = Sequential([
    LSTM(64, return_sequences=True, input_shape=(seq_len, n_features)),
    Dropout(0.2),
    LSTM(32),
    Dense(16, activation='relu'),
    Dense(1)  # 输出预测的冲击成本
])

这里有个坑:序列长度怎么选? 我建议用自相关函数来辅助判断。计算冲击成本序列的自相关,看它衰减到0需要多少步,那就是你的序列长度。我做过一个实验,对于A股市场,序列长度在20-50步(对应1-2.5秒)效果最好。

3.2 注意力机制

LSTM虽然好,但它有个问题:它对序列中所有位置「一视同仁」。但实际中,有些时刻更重要。比如,一个大单成交的瞬间,对后续冲击成本的影响远大于普通时刻。

这时候,注意力机制就很有用了。它让模型学会「关注」重要的时间步。

我的经验:在LSTM后面加一个简单的自注意力层,通常能提升2-5%的预测精度。而且,注意力权重本身可以可视化,帮你理解模型到底在关注哪些时刻——这对交易员来说很有说服力。

4. 图神经网络:建模订单流网络

好了,接下来是真正前沿的东西——图神经网络(GNN)

你想想看,市场中的订单不是孤立的。一个订单的成交,会影响其他订单的成交概率。这本质上是一个图结构

  • 节点:每个订单或每个交易者
  • :订单之间的时序关系或因果关系

4.1 为什么用图?

传统模型把订单流看作一个序列。但序列只能捕捉「前后」关系,捕捉不到「谁影响了谁」。比如,两个大单同时在不同交易所出现,它们之间没有时序关系,但会相互影响价格。图神经网络可以建模这种「非时序的相互作用」。

4.2 一个简单的图模型框架

我设计过一个实验,把过去N笔订单作为节点,用它们的时间间隔和价格差异作为边的权重。然后让GNN去预测下一笔订单的冲击成本。

# 伪代码:图神经网络建模冲击成本
# 1. 构建图
nodes = [order_1, order_2, ..., order_N]
edges = []
for i in range(N):
    for j in range(i+1, N):
        weight = 1 / (time_diff(i,j) + epsilon)  # 时间越近,权重越大
        edges.append((i, j, weight))

# 2. 定义GNN模型
class ImpactGNN(nn.Module):
    def __init__(self):
        self.conv1 = GCNConv(in_channels, 64)
        self.conv2 = GCNConv(64, 32)
        self.fc = nn.Linear(32, 1)
    
    def forward(self, x, edge_index):
        x = self.conv1(x, edge_index)
        x = F.relu(x)
        x = self.conv2(x, edge_index)
        x = global_mean_pool(x, batch)  # 聚合所有节点信息
        return self.fc(x)

注意:图神经网络的计算量很大。对于高频数据,每秒可能有上千笔订单,构建全连接图是不现实的。我建议只连接「时间窗口内」的订单,或者用K近邻算法只连接最相关的订单。

5. 三种模型的对比与选择

说了这么多,到底该用哪个?我整理了一个表格,方便你决策:

模型类型 优势 劣势 适用场景
机器学习(XGBoost等) 训练快,可解释性强,特征工程灵活 无法捕捉时序依赖 低频交易、日频调仓、特征维度高时
深度学习(LSTM等) 能捕捉长期时序依赖,自动特征提取 训练慢,需要大量数据,可解释性差 高频交易、订单流预测、需要记忆效应时
图神经网络(GNN) 能建模订单间相互作用,捕捉网络效应 计算量大,图构建复杂,落地难度高 多交易所联动、大单拆单策略、流动性危机预测

6. 实战中的避坑指南

最后,分享几个我在项目中踩过的坑:

  • 数据泄露:用未来数据预测当前,这是最常见的错误。比如,用「未来5分钟的成交量」作为特征。记住,所有特征在预测时刻必须是已知的。
  • 过拟合到市场微观结构:深度学习模型很容易学到订单簿的「噪声模式」。我建议在损失函数中加入正则项,或者用早停法。
  • 忽略交易成本:模型预测的冲击成本再准,如果交易成本(佣金、滑点)比它还高,那就没意义了。我习惯把交易成本也作为一个特征输入模型。

我的建议:不要一上来就上GNN。先从简单的机器学习模型开始,建立基线。然后逐步增加复杂度。如果XGBoost已经能解释80%的方差,那LSTM和GNN带来的提升可能只有5-10%。这5-10%值不值得你花一个月去调参?你自己权衡。

好了,关于前沿模型的内容就到这里。冲击成本建模这条路,越走越深,但也越走越有意思。希望今天的分享能给你一些启发。


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