3. 市场微观结构:订单簿与盘口数据
做高频交易回测,有个东西绕不开——市场微观结构。
说白了,就是市场在极短时间内是怎么运作的。你想想看,我们平时看到的K线图,一分钟一根,里面其实藏了成千上万笔交易。这些交易的细节,才是高频交易真正要啃的骨头。
我个人习惯,把这块内容分成三个层次来讲:订单簿原理、盘口数据级别、以及Tick和快照的区别。咱们一个一个来。
3.1 订单簿(Order Book)原理
订单簿是什么?你可以把它想象成一个实时更新的“买卖挂单大列表”。
买方想低价买,挂个买单。卖方想高价卖,挂个卖单。这些单子按价格排队,就形成了订单簿。
我在项目中遇到过一个问题:刚开始做回测时,我只用了成交数据,忽略了订单簿。结果策略在模拟里赚得飞起,实盘一跑就亏。为什么?因为订单簿里的挂单深度,直接影响你的成交速度和滑点。
- 买盘(Bid):最高买入价,价格从高到低排列
- 卖盘(Ask):最低卖出价,价格从低到高排列
- 价差(Spread):卖一价 - 买一价,流动性越好的品种价差越小
- 深度(Depth):每个价位上的挂单数量
嗯,这里要注意:订单簿是动态的。每一秒都有新单进来,也有旧单撤掉。你的策略如果只看最后成交价,等于闭着眼睛开车。
下面这张图,是我自己画的一个简化版订单簿结构。你可以直观感受一下买卖双方是怎么“对峙”的。
3.2 买卖盘口数据:Level 1 / 2 / 3
盘口数据分三个级别。很多新手搞不清,我简单说一下。
Level 1(最基础)
只包含最优买卖价和对应的数量。也就是买一和卖一。
大多数免费行情接口给的就是这个。做简单策略够用,但做高频?差得远。
Level 2(常用)
包含多个价位的买卖挂单。一般是前5档或前10档。
比如上面那张图里,买一到买五、卖一到卖五,就是典型的 Level 2 数据。
有了这个,你才能判断市场的真实深度。举个例子:
// 一个简单的 Level 2 数据结构示例
struct Level2Data {
double bid_prices[10]; // 买价,从高到低
int bid_sizes[10]; // 对应数量
double ask_prices[10]; // 卖价,从低到高
int ask_sizes[10]; // 对应数量
int64_t timestamp; // 时间戳,纳秒级
};
Level 3(最详细)
这个级别能看到每个订单的详细信息。包括订单ID、下单时间、隐藏数量等。
说实话,Level 3 数据一般只有交易所内部或者做市商才能拿到。我做高频交易这么多年,真正用到 Level 3 的场景其实不多。除非你在做订单流分析或者抢单策略。
3.3 Tick级数据与快照数据
这块容易混淆。我分开讲。
Tick级数据
每一笔成交或每一次订单簿变化,都算一个Tick。
说白了,Tick数据就是“发生了什么就记录什么”。比如:
- 有人以100.10买了100股 → 记录一条Tick
- 有人撤单了 → 记录一条Tick
- 有人挂了新单 → 记录一条Tick
我在项目中遇到过一个问题:用Tick数据做回测,数据量太大,回测跑不动。后来我改用快照数据,速度上去了,但精度下降了。这是个取舍问题。
快照数据
每隔固定时间(比如100毫秒)拍一张订单簿的照片。
快照里包含当前时刻的完整订单簿状态。它不记录中间发生了什么,只记录最终结果。
| 对比维度 | Tick数据 | 快照数据 |
|---|---|---|
| 数据量 | 极大(每笔事件都记录) | 较小(固定间隔采样) |
| 精度 | 高(无信息丢失) | 低(可能错过中间变化) |
| 回测速度 | 慢 | 快 |
| 适用场景 | 高频策略、订单流分析 | 中低频策略、趋势跟踪 |
| 存储成本 | 高 | 低 |
做高频回测,优先用Tick数据。但如果你只是验证策略逻辑,快照数据也够用。
我曾经犯过一个错:用1秒快照数据回测一个高频做市策略,结果回测曲线漂亮得不行。实盘一跑,直接亏了5%。为什么?因为快照错过了中间几百次订单簿变化,策略的成交逻辑完全不对。
3.4 实际应用中的注意事项
最后说几个实战中容易踩的坑。
- 时间同步问题:不同数据源的时间戳可能不一致。我建议统一用交易所的纳秒级时间戳。
- 数据清洗:原始数据里经常有错误。比如卖价低于买价,这种数据要过滤掉。
- 回放速度:Tick数据回放时,要控制速度。我一般用事件驱动的方式,而不是按时间轴硬跑。
- 内存管理:一天的Tick数据可能占几个G。用内存映射文件或者数据库来管理。
嗯,关于市场微观结构这块,今天就先聊这么多。记住一句话:你的回测精度,取决于你对订单簿的理解深度。别想着跳过基础直接上策略,那是在给自己挖坑。
公众号:蓝海资料掘金营,微信deep3321