13、订单簿预测模型:使用 LSTM/Transformer 预测未来价格、模型评估
好,咱们终于聊到预测模型了。
前面几章我们把订单簿的数据结构、特征工程、微观结构信号都捋了一遍。说白了,那些都是在为这一步做准备——用深度学习模型去预测未来的价格走势。
我个人习惯把这件事分成两个阶段:特征序列化和模型建模。今天重点讲后者,但前者同样关键。
13.1 为什么是 LSTM 和 Transformer?
订单簿数据本质上是一个多变量时间序列。每一时刻,我们有买一价、卖一价、买一量、卖一量、深度斜率、订单不平衡度……几十个特征。
传统的时间序列模型(ARIMA、GARCH)处理不了这么复杂的非线性关系。而 LSTM 和 Transformer 正好擅长这个。
- LSTM:擅长捕捉长短期依赖,对序列顺序敏感。适合订单簿这种“先有挂单、后有成交”的因果结构。
- Transformer:通过自注意力机制,能同时关注序列中任意两个位置的关系。适合捕捉订单簿中“远距离的挂单变化对当前价格的影响”。
13.2 数据准备:滑动窗口与标签构造
模型不能直接吃原始订单簿。我们需要构造样本。
具体做法是:
- 取过去 T 个时间步的特征序列,作为输入 X。
- 取未来 K 个时间步的价格变化方向或幅度,作为标签 y。
- 用滑动窗口在时间轴上滚动,生成大量样本。
举个例子:
# 假设 features 是形状为 (N, F) 的 numpy 数组
# N 是时间步数,F 是特征数
# T = 60(用过去 60 步预测)
# K = 5(预测未来 5 步的价格变化)
def create_samples(features, prices, T=60, K=5):
X, y = [], []
for i in range(T, len(features) - K):
X.append(features[i-T:i])
# 标签:未来 K 步的平均价格变化
future_return = (prices[i+K] - prices[i]) / prices[i]
y.append(future_return)
return np.array(X), np.array(y)
13.3 LSTM 模型搭建
LSTM 的结构其实不复杂。我一般用两层 LSTM + 一层全连接输出。
import torch
import torch.nn as nn
class OrderBookLSTM(nn.Module):
def __init__(self, input_dim, hidden_dim=64, num_layers=2):
super().__init__()
self.lstm = nn.LSTM(
input_size=input_dim,
hidden_size=hidden_dim,
num_layers=num_layers,
batch_first=True,
dropout=0.2
)
self.fc = nn.Linear(hidden_dim, 1) # 输出未来价格变化
def forward(self, x):
# x shape: (batch, T, input_dim)
out, (h_n, c_n) = self.lstm(x)
# 取最后一个时间步的输出
last_out = out[:, -1, :]
pred = self.fc(last_out)
return pred
这里有几个关键点:
- batch_first=True:让输入形状为 (batch, seq_len, features),更符合直觉。
- dropout=0.2:防止过拟合。订单簿数据噪声大,不加 dropout 很容易学偏。
- 取最后一个时间步:因为我们只关心“看完所有历史后”的预测。
13.4 Transformer 模型搭建
Transformer 的核心是自注意力。对于订单簿数据,我习惯用编码器部分,把序列编码成一个向量,然后接一个全连接层输出。
class OrderBookTransformer(nn.Module):
def __init__(self, input_dim, d_model=64, nhead=4, num_layers=2):
super().__init__()
self.embedding = nn.Linear(input_dim, d_model)
self.pos_encoder = PositionalEncoding(d_model) # 需要自己实现
encoder_layer = nn.TransformerEncoderLayer(
d_model=d_model,
nhead=nhead,
dim_feedforward=256,
dropout=0.1,
batch_first=True
)
self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=num_layers)
self.fc = nn.Linear(d_model, 1)
def forward(self, x):
x = self.embedding(x)
x = self.pos_encoder(x)
x = self.transformer(x)
# 取全局平均池化或最后一个位置
x = x.mean(dim=1) # 全局平均池化
return self.fc(x)
13.5 模型评估:不只是看 Loss
很多人训练完模型只看训练集和验证集的 loss,觉得 loss 降下来就万事大吉。嗯,这里要注意——对于交易模型,loss 低不代表能赚钱。
我一般会做以下几项评估:
| 评估指标 | 说明 | 我的经验阈值 |
|---|---|---|
| MSE / MAE | 预测值与真实值的误差 | 相对 MSE < 0.001 算不错 |
| 方向准确率 | 预测涨跌方向是否正确 | > 55% 就有交易价值 |
| 夏普比率(模拟交易) | 用预测信号做简单策略的回测 | > 1.5 才考虑实盘 |
| 最大回撤 | 模拟交易中的最大亏损幅度 | < 10% 才安全 |
我曾经有一个 LSTM 模型,MSE 低得惊人,但方向准确率只有 51%。说白了,它只是学会了预测“价格不变”,因为大部分时间价格确实没怎么动。这种模型毫无意义。
13.6 避坑指南
做订单簿预测模型,有几个坑我踩过,分享给你:
- 数据泄露:前面提过,不要用未来信息。还有一个常见错误——用整个数据集做归一化。应该用滑动窗口的方式,只基于历史数据做归一化。
- 标签选择:预测未来 1 步还是 10 步?我建议从短周期开始(1-3 步),模型更容易学到信号。长周期预测噪声太大。
- 过拟合:订单簿数据特征多、样本相对少,很容易过拟合。我习惯用早停法(early stopping)和权重衰减(weight decay)。
- 交易成本:模型预测准确率 60% 看起来很牛,但扣除手续费和滑点后可能还是亏的。评估时一定要把交易成本算进去。
13.7 核心逻辑框架图
下面这张图总结了订单簿预测模型的完整流程:
这张图把整个流程串起来了。从原始数据到特征工程,再到模型选择(LSTM 或 Transformer),最后输出预测并进行评估。你想想看,每一步都有坑,但每一步也都有优化空间。
13.8 小结
订单簿预测模型不是银弹。它只是一个工具,帮你从历史数据中提取统计规律。真正赚钱的,是你如何利用这些预测信号去构建交易策略。
我个人建议:先用 LSTM 跑通全流程,再尝试 Transformer。不要一上来就追求最复杂的模型。简单模型跑通了,你才知道问题出在数据上还是模型上。