1. 订单簿基础:什么是订单簿?
做高频交易的人,每天打交道最多的东西,就是订单簿。
说白了,订单簿就是一个实时更新的「买卖挂单账本」。交易所用它来记录所有交易者挂出来的限价单——谁想买、谁想卖、什么价格、多少数量,全都清清楚楚。
我刚开始接触这个领域时,觉得订单簿不就是个价格列表嘛,有啥好研究的?后来在实盘环境里被狠狠教育了一次,才发现这东西的深度远超想象。
1.1 限价单 vs 市价单
先搞清楚两个最基础的概念。你想想看,你下单的时候,交易所其实只给你两种选择:
- 限价单(Limit Order):你指定一个价格,只有市场达到这个价格时才会成交。比如「我挂100元买10股」,不到100元就不买。
- 市价单(Market Order):你不指定价格,直接说「我要买10股」,交易所按当前最优价格帮你成交。
嗯,这里要注意一个关键区别:限价单提供流动性,市价单消耗流动性。我在项目中遇到过不少新手,上来就狂发市价单,结果把盘口打穿,成交价格远不如预期。
核心区别总结:
| 特性 | 限价单 | 市价单 |
|---|---|---|
| 价格控制 | 完全控制 | 无控制 |
| 成交速度 | 可能等待 | 立即成交 |
| 流动性贡献 | 提供流动性 | 消耗流动性 |
| 滑点风险 | 无滑点 | 可能有滑点 |
1.2 订单簿的买卖盘口结构
订单簿长什么样?我画个图你就明白了。
这张图里,左侧是卖盘(也叫 Ask 或 Offer),右侧是买盘(Bid)。中间那条虚线是当前最新成交价。卖一价和买一价之间的差距,我们叫它「价差」(Spread)。
我个人习惯把订单簿想象成一个「价格阶梯」。每一档价格上,都堆着一定数量的挂单。价格越往中间靠,挂单越密集。
1.3 盘口的关键指标
做高频数据压缩时,我们最关心的几个盘口指标:
- 买一价(Bid1):最高的买入限价
- 卖一价(Ask1):最低的卖出限价
- 价差(Spread):Ask1 - Bid1,流动性越好的品种价差越小
- 盘口深度(Depth):各档位的挂单数量
- 买卖盘比(Bid/Ask Ratio):买盘总量 / 卖盘总量
实战小技巧: 我一般会同时监控前5档的累计深度。如果买一只有100手,但买二到买五有5000手,说明有大资金在下面托底。这种结构在数据压缩时,我会保留更多档位信息。
1.4 订单簿的更新机制
订单簿不是静态的。每一秒都有新订单进来,也有订单被撤掉。交易所会推送三种事件:
- 新增订单:有人挂了新的限价单
- 撤销订单:有人撤回了未成交的限价单
- 成交事件:限价单和市价单匹配成功
我曾经踩过一个坑:以为订单簿的更新是「全量快照」,每次推送都传全部数据。后来发现高频场景下,交易所发的是「增量更新」——只告诉你哪一档变了。如果不做增量压缩,带宽根本扛不住。
注意: 不同交易所的订单簿推送格式差异很大。有的用 JSON,有的用二进制。做数据压缩时,一定要先搞清楚原始数据的结构,否则压缩率会很难看。
1.5 一个简单的订单簿数据结构
用 Python 表示一个订单簿,我习惯这样写:
class OrderBook:
def __init__(self):
self.bids = {} # 买盘:{价格: 数量}
self.asks = {} # 卖盘:{价格: 数量}
self.last_price = 0.0
def update(self, side, price, quantity):
"""更新订单簿"""
if quantity == 0:
# 数量为0表示撤销该档位
if side == 'bid':
self.bids.pop(price, None)
else:
self.asks.pop(price, None)
else:
if side == 'bid':
self.bids[price] = quantity
else:
self.asks[price] = quantity
def get_spread(self):
"""计算当前价差"""
if not self.bids or not self.asks:
return None
best_bid = max(self.bids.keys())
best_ask = min(self.asks.keys())
return best_ask - best_bid
def get_depth(self, levels=5):
"""获取前N档深度"""
sorted_bids = sorted(self.bids.items(), reverse=True)[:levels]
sorted_asks = sorted(self.asks.items())[:levels]
return {
'bids': sorted_bids,
'asks': sorted_asks
}
这段代码看着简单,但实际生产环境里,订单簿的更新速度能达到每秒几千次。我建议你在做数据压缩时,重点关注 update 方法的效率——字典操作虽然快,但频繁的插入删除也会产生内存碎片。
1.6 为什么订单簿对数据压缩重要?
你想想看,高频交易的数据量有多大?一个交易所每秒可能产生几万条订单簿更新。如果每条都完整记录,一天下来就是几个 GB。
但订单簿有个特点:大部分时间只有少数档位在变化。比如价差附近的几档变动频繁,而远离中间价的档位可能几分钟都不动一次。这就是压缩的突破口。
我个人习惯的做法是:只记录变化的部分,然后用增量编码压缩。具体怎么实现,后面的章节会详细讲。
一句话总结: 订单簿是高频数据的「心脏」。不理解它的结构,后面的压缩算法全是空中楼阁。
公众号:蓝海资料掘金营,微信deep3321