18、机器学习应用:特征工程、标签构建、模型选择、LSTM/Transformer、强化学习做市
说实话,机器学习在量化交易里被吹得神乎其神。但真正落地的时候,你会发现——特征工程和标签构建才是那80%的苦活。模型反而是最后一步。
我早年踩过一个坑:花了两周调LSTM的超参数,结果发现标签定义错了。嗯,那种感觉就像你跑完马拉松才发现起跑线画歪了。所以这一章,咱们从最基础的活儿开始聊。
18.1 特征工程:从订单簿里挖金子
原始行情数据是不能直接喂给模型的。你得先把它变成特征。我个人习惯把特征分成三类:
- 价格类特征:比如买卖价差、中间价、加权平均价。这些能反映当前市场的定价中枢。
- 量能类特征:比如订单簿深度、成交量、委买委卖比例。说白了就是看谁在使劲。
- 时序类特征:比如价格变化率、波动率、自相关性。这些能捕捉趋势和反转信号。
举个例子,我曾在项目中用过这样一个特征:
def order_book_imbalance(bid_volumes, ask_volumes):
"""
计算订单簿不平衡度
正值表示买方压力大,负值表示卖方压力大
"""
total_bid = sum(bid_volumes[:5]) # 前5档买单量
total_ask = sum(ask_volumes[:5]) # 前5档卖单量
if total_bid + total_ask == 0:
return 0.0
return (total_bid - total_ask) / (total_bid + total_ask)
这个特征简单粗暴,但非常有效。你想想看,当买单深度突然大于卖单深度时,价格大概率要往上走。
18.2 标签构建:定义你要预测什么
标签构建是门艺术。你不能简单地说「预测未来价格」,因为价格是随机游走的。你需要定义一个可操作的目标。
我常用的几种标签:
- 方向标签:未来N笔交易的价格涨跌。比如+1表示涨,-1表示跌,0表示平。
- 回归标签:未来N秒的收益率。这个适合做回归模型。
- 做市标签:未来N笔交易中,最优买卖报价的价差变化。这个专门为做市策略设计。
我曾经犯过一个错误:用未来数据构建标签。比如用t+1时刻的价格减去t时刻的价格,但t+1时刻的价格在t时刻还没发生。这会导致严重的未来信息泄露。嗯,这个坑我替你们踩过了。
def build_label(df, lookahead=10):
"""
构建未来N笔交易的方向标签
注意:这里假设df已经按时间排序
"""
future_price = df['price'].shift(-lookahead)
current_price = df['price']
label = np.sign(future_price - current_price)
return label
18.3 模型选择:从传统到深度学习
模型选择这事儿,我个人的原则是:先简单,后复杂。别一上来就上Transformer,先试试逻辑回归或者XGBoost。
| 模型 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 逻辑回归 | 二分类(涨/跌) | 可解释性强,训练快 | 无法捕捉非线性关系 |
| 随机森林 | 多分类/回归 | 抗过拟合,特征重要性 | 对时序数据不敏感 |
| XGBoost | 回归/排序 | 精度高,支持自定义损失 | 调参复杂 |
| LSTM | 时序预测 | 捕捉长期依赖 | 训练慢,容易过拟合 |
| Transformer | 高频时序 | 并行计算,全局注意力 | 数据量大,计算资源高 |
我建议你从XGBoost开始。为什么?因为它对特征工程的要求没那么苛刻,而且自带正则化。我在一个实盘项目中,用XGBoost跑出来的夏普比率比LSTM还高0.3。你说气不气人?
18.4 LSTM与Transformer:时序建模的利器
LSTM和Transformer是目前时序预测的两大主流。咱们分别聊聊。
LSTM:长短期记忆网络
LSTM的核心是门控机制。它能记住哪些信息该保留,哪些该遗忘。说白了,就是给模型装了个「记忆橡皮擦」。
import torch.nn as nn
class LSTMModel(nn.Module):
def __init__(self, input_size, hidden_size, num_layers):
super().__init__()
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, 1) # 输出一个值(比如收益率)
def forward(self, x):
out, _ = self.lstm(x)
out = self.fc(out[:, -1, :]) # 取最后一个时间步
return out
我在项目中遇到过一个问题:LSTM对输入序列的长度非常敏感。序列太长,梯度消失;序列太短,捕捉不到信息。我一般用50-100个时间步,具体要看数据的采样频率。
Transformer:注意力机制的革命
Transformer的优势在于它能同时关注序列中所有位置的信息。不像LSTM那样一步步传递。你想想看,如果市场突然出现一个巨量订单,Transformer能立刻捕捉到,而LSTM可能需要几个时间步才能反应过来。
class TransformerModel(nn.Module):
def __init__(self, d_model, nhead, num_layers):
super().__init__()
self.encoder_layer = nn.TransformerEncoderLayer(d_model, nhead)
self.transformer = nn.TransformerEncoder(self.encoder_layer, num_layers)
self.fc = nn.Linear(d_model, 1)
def forward(self, x):
x = self.transformer(x)
x = self.fc(x[:, -1, :])
return x
18.5 强化学习做市:让AI自己学会赚钱
做市策略的核心是:在买卖报价之间赚取价差,同时控制库存风险。传统方法是用公式计算最优报价,但强化学习可以做得更灵活。
强化学习做市的框架是这样的:
- 状态(State):当前订单簿状态、库存、市场波动率等。
- 动作(Action):调整买卖报价的价差和位置。
- 奖励(Reward):赚到的价差收益减去库存风险惩罚。
我曾在模拟环境中跑过一个DQN做市模型。刚开始它只会乱报价,亏得一塌糊涂。但训练了10万步之后,它学会了在波动大的时候收窄价差,在波动小的时候放宽价差。嗯,这玩意儿确实有点东西。
class MarketMakingEnv:
def __init__(self, order_book):
self.order_book = order_book
self.inventory = 0
self.cash = 0
def step(self, action):
# action: [bid_spread, ask_spread]
bid_price = self.mid_price - action[0]
ask_price = self.mid_price + action[1]
# 模拟成交
# ...
reward = self.cash - self.inventory * self.mid_price
return next_state, reward, done
18.6 知识体系总览
下面这张图总结了本章的核心逻辑。你可以把它当作一个路线图,按顺序推进。
好了,这一章的内容就这些。特征工程、标签构建、模型选择、LSTM/Transformer、强化学习做市——每一步都有坑,但也都有解法。记住我的一句话:别让模型替你思考,你得先替模型思考。
- 特征工程要精不要多,先做筛选
- 标签构建要避免未来信息泄露
- 模型选择从简单开始,XGBoost是很好的起点
- LSTM适合中小规模数据,Transformer适合大规模数据
- 强化学习做市要特别注意交易成本和库存风险