2、订单簿基础:订单簿数据结构、限价单与市价单、买卖盘口与深度
好,咱们直接进入正题。订单簿这东西,说白了就是交易所用来记录所有挂单的「大账本」。你想想看,一个市场里有人想买、有人想卖,总得有个地方把这些意愿记下来吧?订单簿就是干这个的。
我个人习惯把订单簿理解成一个「双向排队系统」。左边是买单队列,右边是卖单队列,中间是成交价。谁出价高谁排前面,谁出价低谁先成交——就这么简单。
订单簿的数据结构
先看底层实现。订单簿的核心数据结构,其实就是一个价格优先、时间优先的排序容器。
我见过不少新手问:「为什么不用数组存订单?」嗯,你想想看,一个活跃的币对可能有几万甚至几十万笔挂单,用数组遍历排序?那性能直接爆炸。
实际生产中,我们通常用红黑树或跳表来实现。C++ 用 std::map,Java 用 TreeMap,Go 的话我习惯用 github.com/emirpasic/gods/trees/redblacktree。
这里给个简化版的订单簿结构:
// 订单簿核心结构(伪代码)
struct OrderBook {
// 买单:价格降序排列(最高价在前)
map<Price, OrderQueue, greater<Price>> bids;
// 卖单:价格升序排列(最低价在前)
map<Price, OrderQueue, less<Price>> asks;
// 每个价格档位对应一个订单队列
struct OrderQueue {
queue<Order> orders; // 先进先出
Volume totalVolume; // 该价格总挂单量
};
};
注意看,每个价格档位内部还有一个队列。为什么?因为同一价格可能有多个订单,得按时间顺序排队。这就是「价格优先、时间优先」的完整含义。
核心要点:订单簿的查询和修改必须在微秒级完成。做市商每秒可能要更新几百次订单簿,如果数据结构选错了,延迟直接爆炸。
限价单与市价单
这两种订单类型,是交易系统里最基础、也最重要的概念。
限价单(Limit Order):你指定一个价格,只有市场价达到这个价格时才成交。说白了就是「我只接受这个价,高了我不买,低了我不卖」。
我在项目中遇到过一个问题:有个做市策略同时挂了500个限价单,结果行情剧烈波动时,系统处理撤单和改单的速度跟不上,导致大量订单以不利价格成交。后来我们加了批量撤单和价格档位合并的逻辑才解决。
市价单(Market Order):不指定价格,直接按当前最优价成交。你想想看,这就像你去菜市场说「给我来10斤土豆,多少钱都行」——成交快,但价格不可控。
市价单的坑在哪里?我举个例子:
// 市价单买入的执行过程
function executeMarketBuy(volume) {
let remaining = volume;
let totalCost = 0;
// 从最优卖单开始吃
for (let [price, queue] of asks) {
let matchVolume = min(remaining, queue.totalVolume);
totalCost += matchVolume * price;
remaining -= matchVolume;
if (remaining == 0) break;
}
// 如果卖单不够,订单部分成交或失败
if (remaining > 0) {
// 处理部分成交逻辑
}
}
看到问题了吗?如果卖单深度不够,市价单会「吃掉」所有可用的卖单,然后剩下的部分要么取消,要么变成限价单继续挂着。这就是所谓的滑点——你本来想花100块买,结果因为深度不够,实际花了105块。
避坑指南:我曾经见过一个新手写的做市策略,市价单没有设置最大滑点保护。结果有一次流动性骤降,一笔市价单直接打穿了5个价格档位,亏损了十几个BP。从那以后,我所有的市价单都强制加上 maxSlippage 参数。
买卖盘口与深度
盘口(Order Book Depth)就是订单簿的可视化呈现。通常我们看到的是这样的结构:
| 卖5 | 100.50 | 2,000 |
|---|---|---|
| 卖4 | 100.40 | 1,500 |
| 卖3 | 100.30 | 3,000 |
| 卖2 | 100.20 | 2,500 |
| 卖1 | 100.10 | 1,000 |
| —— | —— | —— |
| 买1 | 100.00 | 800 |
| 买2 | 99.90 | 1,200 |
| 买3 | 99.80 | 2,000 |
| 买4 | 99.70 | 1,800 |
| 买5 | 99.60 | 3,500 |
这里有个关键概念叫价差(Spread)——就是卖1价和买1价的差值。价差越小,说明市场流动性越好。做市商赚的就是这个价差。
深度(Depth)则是指某个价格区间内的总挂单量。深度越厚,大额订单对价格的冲击就越小。
下面这张图展示了订单簿的深度结构:
你看这个图,买单深度在低价区更厚,卖单深度在高价区更厚。这符合直觉——价格越低,愿意买的人越多;价格越高,愿意卖的人越多。
实战技巧:我个人习惯用「深度斜率」来判断市场情绪。如果买单深度斜率比卖单陡,说明买方力量强,价格可能上涨。反之亦然。这个指标比单纯看价格涨跌更稳定。
订单簿的更新机制
订单簿不是静态的,它每时每刻都在变化。常见的更新事件有四种:
- 新增订单:新限价单进入队列,按价格插入对应位置
- 撤单:从队列中移除指定订单
- 成交:市价单吃掉限价单,减少对应档位的挂单量
- 改单:本质上是撤单+重新下单,但有些交易所支持原子操作
这里有个细节:改单操作如果只是改数量不改价格,很多交易所允许原地修改。但如果改了价格,就必须先撤单再重新排队。我见过有人利用这个机制做「插队」操作——先下一个低价买单,然后改单到高价,变相实现价格优先。嗯,这种骚操作一般会被交易所的风控系统拦截。
好了,订单簿的基础就这些。记住一句话:订单簿是市场的微观结构,读懂它,你就能读懂市场的每一次呼吸。