第一章:订单簿数据结构——做市系统的“心脏”
做市系统里什么最重要?我个人觉得,订单簿排第一。你想想看,所有策略、所有算法,最终都要落到订单簿上。它就像心脏,把买卖双方的血液泵到整个市场里。今天我们就来拆解这个核心部件。
1.1 订单簿的构成:限价单 vs 市价单
订单簿里就两种订单,说白了就是“我想多少钱买/卖”和“我不管多少钱,现在就要成交”。
限价单(Limit Order)
限价单就是指定价格。比如“我出100块买1个BTC”,那只有价格≤100的卖单才能跟你成交。我在做高频做市时,90%以上的订单都是限价单。为什么?因为我们要控制成本,不能随便吃单。
市价单(Market Order)
市价单不指定价格,直接按当前最优价成交。比如“我现在就要买1个BTC”,系统会吃掉卖一、卖二、卖三...直到数量凑够。这种订单对做市商来说是“对手盘”,我们赚的就是它的价差。
1.2 订单簿的存储结构:红黑树 vs 跳表
订单簿每秒可能有几万次更新,怎么存才能快?这里有两个主流方案。
红黑树(Red-Black Tree)
红黑树是一种自平衡二叉搜索树。它的特点是:插入、删除、查找都是O(log n)。很多交易所底层都用它,比如早期的Bitcoin交易所。
// 伪代码:红黑树节点
struct RBNode {
double price; // 价格
uint64_t volume; // 数量
bool is_buy; // 买卖方向
RBNode *left, *right, *parent;
bool color; // 红或黑
};
跳表(Skip List)
跳表是另一种有序数据结构,用概率平衡代替了严格平衡。它的实现比红黑树简单得多,而且支持范围查询(比如查价格在100-105之间的所有订单)。
// 伪代码:跳表节点
struct SkipNode {
double price;
uint64_t volume;
bool is_buy;
vector<SkipNode*> forward; // 不同层级的指针
};
| 特性 | 红黑树 | 跳表 |
|---|---|---|
| 实现难度 | 高 | 低 |
| 查询性能 | O(log n) | O(log n) 期望 |
| 范围查询 | 一般 | 优秀 |
| 内存占用 | 低 | 较高(多层指针) |
| 并发友好度 | 差 | 好(容易分段加锁) |
我个人习惯用跳表。为什么?因为做市系统里经常要查“买一到买十”这种范围数据,跳表天然支持。而且并发场景下,跳表可以分段加锁,红黑树就麻烦多了。
1.3 订单簿的深度与流动性
深度和流动性,这两个词经常被混用,但其实是两码事。
深度(Depth)
深度指的是订单簿上每个价格档位的挂单量。比如买一挂了100个,买二挂了200个...把这些数据画成图,就是深度图。
流动性(Liquidity)
流动性是更深层的概念。它衡量的是“你吃单时价格会滑多少”。深度大不一定流动性好——如果所有挂单都在同一个价格档位,那深度再大也没用。真正的流动性,是各个价格档位都有足够的挂单,形成平滑的深度曲线。
我记得有一次,一个币对深度看起来很大,但90%的挂单都在买一和卖一。结果一个100BTC的市价单进来,直接打穿了5个档位。这就是典型的“假深度”。
1.4 实战中的订单簿设计
说了这么多理论,来点实际的。我在做系统时,订单簿一般这样设计:
- 分层存储: 价格档位用跳表,每个档位下的订单用链表。这样既能快速定位价格,又能处理同价订单的FIFO顺序。
- 增量更新: 不每次全量推送,只推送变化的部分。比如“买一从100变成101”,而不是把整个买盘都发一遍。
- 快照+增量: 每10秒发一次全量快照,中间只发增量。这样新连接的客户端能快速同步,老客户端也能保持实时。
// 订单簿核心数据结构(简化版)
struct OrderBook {
SkipList<double, PriceLevel> bids; // 买盘,按价格降序
SkipList<double, PriceLevel> asks; // 卖盘,按价格升序
unordered_map<uint64_t, Order> orders; // 订单ID到订单的映射
void add_order(const Order& order);
void cancel_order(uint64_t order_id);
void match(); // 撮合逻辑
};
struct PriceLevel {
double price;
uint64_t total_volume;
list<Order> orders; // 同价订单队列
};
好了,订单簿的数据结构就讲到这里。记住一句话:订单簿是做市系统的地基,地基不稳,上面盖什么楼都得塌。下一章我们聊聊订单簿的更新与撮合逻辑,那才是真正考验性能的地方。