第二十三章:订单流与量化交易进阶
说实话,走到这一步,你已经不是普通交易员了。
能看懂订单流,能手动分析失衡和吸收,这已经很厉害了。但你想过没有——如果把这些经验写成代码,让机器帮你盯盘、帮你回测、帮你筛选信号,那会是什么效果?
我做了五年量化,前三年都在跟传统指标较劲。后来把订单流塞进策略里,才发现之前的路走偏了。今天这章,我就把压箱底的东西掏出来——回测框架怎么搭、订单流因子怎么检验、机器学习怎么用。嗯,内容有点干,但你啃下来,绝对不亏。
23.1 订单流策略的回测框架搭建
回测框架,说白了就是一台时光机。你把策略扔进去,它告诉你:这玩意儿在过去十年能不能赚钱。
但订单流策略的回测,跟普通策略不一样。普通策略看K线就够了,订单流策略需要逐笔成交数据、挂单数据、甚至Level2快照。数据量大了几个数量级。
我个人习惯用这样的框架结构:
class OrderFlowBacktest:
def __init__(self, tick_data, l2_data):
self.tick_data = tick_data # 逐笔成交
self.l2_data = l2_data # Level2快照
self.portfolio = Portfolio()
self.signal_engine = SignalEngine()
def run(self):
for timestamp, snapshot in self.l2_data.iterrows():
# 1. 计算订单流指标
delta = self.calc_delta(snapshot)
imbalance = self.calc_imbalance(snapshot)
# 2. 生成信号
signal = self.signal_engine.generate(delta, imbalance)
# 3. 执行交易
if signal != 0:
self.portfolio.execute(signal, timestamp)
return self.portfolio.get_performance()
这个框架看着简单,但有几个坑你得注意:
- 数据对齐:逐笔数据和快照数据的时间戳要对齐,差一毫秒都不行。我踩过这个坑,回测出来年化50%,实盘直接亏成狗——因为信号延迟了。
- 滑点模拟:订单流策略通常做高频,滑点影响巨大。我建议用「成交价+买卖价差的一半」作为模拟滑点,别用固定值。
- 手续费:按实际费率来,别偷懒。很多订单流策略胜率高但盈亏比低,手续费一扣就没了。
23.2 订单流因子的有效性检验
因子有效性检验,就是给你的指标做体检。看看它到底是真本事,还是运气好。
我见过太多人,拿着一个Delta指标跑回测,曲线漂亮得不行,结果一上实盘就完蛋。为什么?因为没做因子检验,不知道这个因子在什么条件下有效、什么条件下失效。
常用的检验方法有这些:
| 检验方法 | 说明 | 我常用的阈值 |
|---|---|---|
| IC值检验 | 因子值与未来收益的相关性 | IC均值 > 0.05,IR > 0.5 |
| 分组回测 | 按因子值分成5组或10组,看单调性 | 多空收益年化 > 10% |
| 换手率分析 | 因子信号的稳定性 | 月换手 < 200% |
| 压力测试 | 在极端行情下的表现 | 最大回撤 < 15% |
举个例子。我曾经检验过一个叫「累积Delta背离」的因子。分组回测的结果是这样的:
分组结果(按因子值从低到高):
Group 1(最低):年化收益 -3.2%
Group 2:年化收益 2.1%
Group 3:年化收益 5.8%
Group 4:年化收益 8.3%
Group 5(最高):年化收益 12.7%
多空收益:15.9%
IC均值:0.072
IR:0.63
这个结果说明什么?因子有效,而且单调性很好。但注意,Group 1是负收益,说明做空这个因子也能赚钱——这就是多空策略的基础。
23.3 机器学习在订单流信号识别中的应用初探
说到机器学习,很多人觉得高大上。其实说白了,就是让机器帮你找规律。
订单流数据有个特点:维度高、噪声大、非线性关系多。传统方法很难处理,但机器学习正好擅长这个。
我常用的流程是这样的:
- 特征工程:把原始订单流数据变成特征。比如Delta的滚动均值、标准差、偏度,买卖压力的比值,大单占比等等。
- 标签定义:未来N根K线的涨跌。我一般用未来5根1分钟K线的收益作为标签。
- 模型选择:XGBoost或者LightGBM,这两个对表格数据效果最好。
- 训练与验证:时间序列交叉验证,别用随机划分。
给你看个简单的特征构造代码:
def build_orderflow_features(df):
features = pd.DataFrame(index=df.index)
# Delta相关
features['delta_ma5'] = df['delta'].rolling(5).mean()
features['delta_std5'] = df['delta'].rolling(5).std()
features['delta_skew5'] = df['delta'].rolling(5).skew()
# 买卖压力比
features['bid_ask_ratio'] = df['bid_volume'] / (df['ask_volume'] + 1e-8)
# 大单占比
features['large_trade_ratio'] = df['large_trade_volume'] / df['total_volume']
# 累积Delta背离
features['cum_delta'] = df['delta'].cumsum()
features['price_ma5'] = df['close'].rolling(5).mean()
features['divergence'] = features['cum_delta'] - features['price_ma5']
return features
模型训练完之后,怎么用?我一般这样:
- 模型输出一个「信号强度」值,范围0到1
- 设定阈值,比如大于0.7做多,小于0.3做空
- 结合订单流过滤,比如只有Delta也支持的时候才开仓
这样做的好处是:机器负责找规律,人负责把关。机器说「这里有信号」,人看订单流确认「嗯,确实有资金在进场」,这才开仓。双重验证,胜率能提高不少。
最后说一句。订单流和量化结合,这条路我走了五年。踩过的坑比走过的路还多。但说实话,一旦你把这个体系搭起来,你会发现——市场在你眼里,不再是红红绿绿的K线,而是一幅清晰的资金流动图。哪里在吸筹,哪里在出货,一目了然。
嗯,这就是订单流量化的魅力。