25、订单流与机器学习:用订单流特征预测价格方向
说实话,做量化交易这些年,我越来越觉得纯价格分析有点「不够用」了。价格是结果,订单流才是原因。今天我们就聊聊怎么把订单流数据喂给机器学习模型,让它帮我们预测价格方向。
嗯,这章内容有点硬核,但我尽量讲得接地气。你想想看,如果我们能提前几秒知道大资金在干嘛,那胜率不就上来了吗?
为什么订单流特征适合做ML特征?
传统技术指标(比如MACD、RSI)都是价格和成交量的衍生品,说白了是「二手信息」。而订单流数据是「一手信息」——它直接告诉你谁在买、谁在卖、挂单深度如何。
我个人习惯把订单流特征分成三类:
- Delta类特征:主动买盘 vs 主动卖盘的差值
- 失衡率类特征:买卖力量的不平衡程度
- 深度变化类特征:盘口挂单的厚度变化
这三类特征组合起来,基本能覆盖市场微观结构的核心信息。我在实盘项目中测试过,加入这些特征后,模型准确率提升了大概6-8个百分点。
特征工程详解
1. Delta特征
Delta就是主动买成交量减去主动卖成交量。但直接拿原始Delta做特征,噪声太大。我一般会做几个处理:
- 累计Delta:过去N笔的Delta累加,比如过去100笔
- Delta斜率:Delta随时间的变化速率
- Delta标准差:衡量Delta的波动程度
举个例子,如果累计Delta持续为正且斜率在增大,说明买方在加速进场,价格大概率要涨。
核心经验:Delta特征对高频行情(tick级别)效果最好,对1分钟以上K线效果会衰减。我曾经试过用5分钟K线的Delta做预测,结果模型几乎失效——因为时间窗口太长,微观信号被抹平了。
2. 失衡率特征
失衡率(Imbalance Ratio)计算的是买卖力量的相对强弱。公式很简单:
失衡率 = (主动买量 - 主动卖量) / (主动买量 + 主动卖量)
这个值在-1到1之间。正值表示买方占优,负值表示卖方占优。
但我发现直接用这个值做特征,效果一般。为什么?因为市场在震荡时,失衡率会频繁正负切换,产生大量噪声。
我的改进方法是:
- 阈值化处理:只有失衡率绝对值超过0.3时才视为有效信号
- 加权移动平均:给近期数据更高权重,比如用EMA而不是SMA
- 多时间尺度:同时计算10笔、50笔、200笔的失衡率
避坑指南:我曾经把失衡率直接作为唯一特征训练模型,结果过拟合严重。后来发现,失衡率在趋势行情中很准,但在震荡行情中就是「噪音制造机」。所以一定要结合其他特征一起用。
3. 深度变化特征
盘口深度变化,说白了就是看买单和卖单的厚度变化。这里我关注三个维度:
| 特征名称 | 计算方式 | 含义 |
|---|---|---|
| 买一深度变化 | 当前买一量 - 前N笔买一量均值 | 最近买单是否在堆积 |
| 卖一深度变化 | 当前卖一量 - 前N笔卖一量均值 | 最近卖单是否在堆积 |
| 深度差 | 买一深度 - 卖一深度 | 买卖双方谁在「加厚」 |
| 深度斜率 | 深度差随时间的变化率 | 力量转换的速度 |
嗯,这里有个细节要注意:深度变化要结合价格位置来看。如果价格在高位,买一深度突然增加,可能是主力在「托单」出货,而不是真的想买。这个坑我踩过好几次。
Python实现ML模型
好了,理论说完了,我们直接上代码。我用的是LightGBM,因为它对表格数据效果好,训练速度快,而且能处理缺失值。
数据准备
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import lightgbm as lgb
# 假设我们已经有了订单流数据
# 字段:timestamp, price, volume, side(buy/sell), bid_depth, ask_depth
def create_orderflow_features(df):
"""生成订单流特征"""
features = pd.DataFrame(index=df.index)
# 1. Delta特征
df['delta'] = np.where(df['side'] == 'buy', df['volume'], -df['volume'])
features['cum_delta_100'] = df['delta'].rolling(100).sum()
features['delta_slope'] = features['cum_delta_100'].diff(10) / 10
features['delta_std'] = df['delta'].rolling(50).std()
# 2. 失衡率特征
buy_vol = np.where(df['side'] == 'buy', df['volume'], 0)
sell_vol = np.where(df['side'] == 'sell', df['volume'], 0)
features['imbalance_ratio'] = (buy_vol - sell_vol) / (buy_vol + sell_vol + 1e-8)
features['imbalance_ema'] = features['imbalance_ratio'].ewm(span=20).mean()
# 3. 深度变化特征
features['bid_depth_change'] = df['bid_depth'] - df['bid_depth'].rolling(50).mean()
features['ask_depth_change'] = df['ask_depth'] - df['ask_depth'].rolling(50).mean()
features['depth_diff'] = features['bid_depth_change'] - features['ask_depth_change']
features['depth_slope'] = features['depth_diff'].diff(10)
return features.dropna()
# 生成标签:未来N笔价格是否上涨
def create_labels(df, lookahead=20):
"""预测未来20笔的价格方向"""
future_price = df['price'].shift(-lookahead)
labels = (future_price > df['price']).astype(int)
return labels[:-lookahead] # 去掉最后无法预测的部分
模型训练
# 加载数据
df = pd.read_csv('orderflow_data.csv')
features = create_orderflow_features(df)
labels = create_labels(df)
# 对齐数据
common_idx = features.index.intersection(labels.index)
X = features.loc[common_idx]
y = labels.loc[common_idx]
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, shuffle=False
)
# 标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 训练LightGBM模型
model = lgb.LGBMClassifier(
n_estimators=200,
max_depth=5,
learning_rate=0.05,
class_weight='balanced',
random_state=42
)
model.fit(
X_train_scaled, y_train,
eval_set=[(X_test_scaled, y_test)],
eval_metric='auc',
early_stopping_rounds=20,
verbose=False
)
# 特征重要性
importance = pd.DataFrame({
'feature': X.columns,
'importance': model.feature_importances_
}).sort_values('importance', ascending=False)
print(importance.head(10))
重要提醒:这里我用了shuffle=False,因为时间序列数据不能随机打乱。如果你打乱了,模型会「偷看」未来数据,回测结果会虚高。这个错误我刚开始做的时候犯过,回测收益曲线漂亮得不行,实盘直接被打脸。
模型评估与调优
模型训练完了,怎么评估?我一般看三个指标:
- 准确率:整体预测正确的比例,但要注意类别平衡
- AUC:衡量模型区分正负样本的能力,0.6以上算可用
- 盈亏比:预测正确时的平均收益 / 预测错误时的平均亏损
我个人最看重盈亏比。为什么?因为准确率再高,如果赚的时候赚1块,亏的时候亏10块,那也没用。我在实盘中要求盈亏比至少达到1.5以上才敢上策略。
知识体系总览
下面这张图是我自己总结的订单流ML预测框架,你可以照着这个思路搭建自己的系统:
一些实战心得
最后分享几个我在实战中踩过的坑:
- 特征不要太多:我一开始搞了50多个特征,结果模型训练慢,还容易过拟合。后来精简到15个核心特征,效果反而更好。
- 注意数据频率:订单流数据通常是毫秒级的,但模型预测不需要那么高频。我一般用1秒或5秒聚合一次,既保留了微观信息,又减少了计算量。
- 模型要定期重训:市场微观结构会变,半年前有效的特征现在可能就失效了。我每周会重训一次模型,用最近一个月的数据。
核心总结:订单流+机器学习这条路走得通,但别指望一上来就赚钱。先做好特征工程,再选对模型,最后用实盘数据反复验证。记住,模型只是工具,对市场的理解才是核心。
交易系统化学习资料 微信Strategy888888