第29章 机器学习应用:订单流预测、最优执行与异常检测
做市商系统做到一定阶段,你会发现一个瓶颈——规则写死了。你想想看,市场是活的,订单流是动态的,光靠if-else很难捕捉到那些微妙的模式。这时候,机器学习就该上场了。
我个人习惯把机器学习在衍生品做市中的应用分成三大块:预测未来(订单流预测)、优化当下(最优执行算法)、揪出异常(异常交易检测)。今天我们就一个一个来拆解。
29.1 订单流预测:LSTM与Transformer的实战选择
订单流预测,说白了就是猜下一秒谁会买、谁会卖。我在项目中遇到过最头疼的问题——预测结果总是滞后。后来发现,问题出在特征工程上。
29.1.1 特征构建:别只盯着价格
很多新手做订单流预测,上来就把价格序列丢进模型。嗯,这里要注意——价格只是冰山一角。真正有价值的信息藏在订单簿的微观结构里。
我常用的特征集包括:
- 订单簿不平衡度:(买一量 - 卖一量) / (买一量 + 卖一量)
- 价差变化率:当前价差 / 过去N笔平均价差 - 1
- 成交速度:过去1秒内的成交笔数
- 大单占比:超过阈值的大单成交量 / 总成交量
- 订单撤销率:撤销订单数 / 总挂单数
这些特征组合起来,比单纯的价格序列信息量大了不止一个量级。
29.1.2 LSTM实现:经典但够用
LSTM做时序预测,优点是稳定、好调参。我一般用三层堆叠,每层128个单元。给你看个核心代码片段:
import torch.nn as nn
class OrderFlowLSTM(nn.Module):
def __init__(self, input_dim=10, hidden_dim=128, num_layers=3):
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.Sequential(
nn.Linear(hidden_dim, 64),
nn.ReLU(),
nn.Dropout(0.1),
nn.Linear(64, 3) # 预测:买入、卖出、无动作
)
def forward(self, x):
# x shape: (batch, seq_len, features)
out, (h_n, c_n) = self.lstm(x)
# 取最后一个时间步的输出
last_out = out[:, -1, :]
return self.fc(last_out)
我曾经用这个结构在比特币永续合约上做订单流预测,准确率大概在62%左右。别小看这个数字——在随机水平33%的基础上,62%已经能带来显著的alpha了。
29.1.3 Transformer:更远、更准、更贵
Transformer的优势在于能捕捉长距离依赖。订单流里有些模式是跨分钟的,LSTM容易遗忘,Transformer不会。
但代价是什么?计算量。我建议只在以下场景用Transformer:
- 预测窗口超过50步
- 特征维度超过20
- 你有GPU资源,且延迟要求不高(>100ms)
29.2 最优执行算法:从理论到代码
预测完订单流,下一步就是怎么执行。最优执行算法解决的核心问题是:如何在最小化市场冲击的同时,完成指定数量的交易。
29.2.1 TWAP与VWAP:基础但实用
TWAP(时间加权平均价格)和VWAP(成交量加权平均价格)是最经典的两种算法。我一般把它们作为基准线——如果连TWAP都跑不赢,那别谈什么机器学习优化了。
TWAP的实现很简单:
def twap_schedule(total_qty, total_time, interval=1.0):
"""
生成TWAP执行计划
total_qty: 总交易量
total_time: 总执行时间(秒)
interval: 切片间隔(秒)
"""
n_slices = int(total_time / interval)
qty_per_slice = total_qty / n_slices
schedule = []
for i in range(n_slices):
schedule.append({
'time': i * interval,
'qty': qty_per_slice,
'side': 'buy' if total_qty > 0 else 'sell'
})
return schedule
但TWAP有个致命问题——它不关心市场状态。市场在剧烈波动时,你还按固定节奏下单,那就是在给对手送钱。
29.2.2 自适应执行:让模型决定节奏
我更喜欢用强化学习来做执行优化。状态空间包括:当前持仓、剩余时间、订单簿状态、波动率。动作空间就是:下一笔下多少、下多快。
核心思路是这样的:
- 用LSTM预测未来N步的订单簿状态
- 用强化学习Agent决定当前最优下单量
- 实时监控执行成本,动态调整策略
避坑指南:我曾经在回测里跑出漂亮的曲线,一上实盘就崩。后来发现是模拟器太理想化了——真实市场的订单簿变化比模拟快得多。解决方案:在模拟器中加入随机延迟和部分成交的模拟。
29.3 异常交易检测:守护你的系统
做市商最怕什么?不是亏钱,是亏得不明不白。异常交易检测就是帮你揪出那些「不明不白」的。
29.3.1 基于统计的检测方法
最基础的方法是用Z-score。我一般对以下指标做实时监控:
| 指标 | 正常范围 | 异常阈值 |
|---|---|---|
| 成交频率(笔/秒) | 5-50 | >200 或 <1 |
| 单笔成交量 | 均值±2σ | >均值+5σ |
| 价差(bps) | 1-10 | >50 或 <0.1 |
| 订单撤销率 | 10%-40% | >80% |
这些阈值不是拍脑袋定的。我习惯用过去7天的数据滚动计算,每4小时更新一次。
29.3.2 基于自编码器的无监督检测
统计方法只能抓到「明显」的异常。对于那些微妙的、从未见过的异常模式,我推荐用自编码器。
训练过程很简单:
- 收集正常交易数据(比如过去30天)
- 训练一个自编码器,输入输出都是特征向量
- 计算重建误差(MSE)
- 设定阈值:超过阈值的就是异常
class AnomalyDetector:
def __init__(self, input_dim=20):
self.encoder = nn.Sequential(
nn.Linear(input_dim, 64),
nn.ReLU(),
nn.Linear(64, 32),
nn.ReLU(),
nn.Linear(32, 16)
)
self.decoder = nn.Sequential(
nn.Linear(16, 32),
nn.ReLU(),
nn.Linear(32, 64),
nn.ReLU(),
nn.Linear(64, input_dim)
)
self.threshold = None
def train(self, normal_data):
# 训练自编码器
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(
list(self.encoder.parameters()) +
list(self.decoder.parameters()),
lr=1e-3
)
# ... 训练循环 ...
# 计算阈值(95分位数)
errors = self.compute_errors(normal_data)
self.threshold = np.percentile(errors, 95)
def detect(self, sample):
error = self.compute_error(sample)
return error > self.threshold
29.4 知识体系总览
说了这么多,我画了张图帮你理清思路。这张图展示了本章三个核心模块之间的关系:
从这张图你可以看到,三个模块不是孤立的。订单流预测的结果可以喂给最优执行算法,异常检测的结果可以用来调整预测模型的置信度。它们共同构成了一个完整的决策闭环。
最后说一句——机器学习在交易系统里不是银弹。它解决的是「模式识别」和「优化决策」的问题,但解决不了「市场逻辑」的问题。我见过太多人把模型搞得很复杂,结果连基本的市场微观结构都没搞懂。先理解市场,再谈模型,这个顺序不能乱。
交易系统化学习资料 微信Strategy888888