2. 限价订单簿详解:限价单与市价单、订单簿的构建与更新、价格优先与时间优先原则
大家好,我是你们的讲师。今天咱们来聊聊订单簿——这个所有量化交易者每天都要打交道的核心数据结构。说白了,它就是交易所用来记录所有挂单的电子账本。
我个人习惯把订单簿比作一个菜市场。买家喊价,卖家要价,中间那个撮合的过程,就是订单簿在做的事。你想想看,没有这个簿子,市场得多混乱?
2.1 两种基础订单类型
先搞清楚两个最基本的工具:限价单和市价单。这俩是构建订单簿的砖瓦。
2.1.1 限价单(Limit Order)
限价单,就是你指定一个价格,告诉交易所:「低于这个价我不卖,高于这个价我不买。」
举个例子:
- 你想买BTC,当前卖一价是50000 USDT。你挂一个49900的买单,这就是限价单。
- 只有价格跌到49900或更低,你的单子才会成交。
限价单的特点:
- 提供流动性——你挂的单子会出现在订单簿上,供别人吃单
- 价格可控——不会出现滑点,但可能无法成交
- 挂单者(Maker)——通常享受手续费优惠
2.1.2 市价单(Market Order)
市价单就简单粗暴了——「不管什么价,我现在就要成交!」
系统会帮你吃掉订单簿上最优的对手单,直到你的数量全部成交。
市价单的特点:
- 消耗流动性——吃掉订单簿上的挂单
- 成交速度快——几乎瞬间成交
- 价格不确定——可能产生滑点,尤其在流动性不足时
- 吃单者(Taker)——手续费通常更高
2.2 订单簿的构建与更新
订单簿本质上是一个价格-数量的映射。买盘(Bid)和卖盘(Ask)各维护一个有序列表。
2.2.1 数据结构
我一般用红黑树或跳表来实现订单簿。为什么?因为需要快速插入、删除和查询。
// 伪代码示例:订单簿核心结构
struct OrderBook {
// 买盘:价格降序排列(最高价在前)
map<Price, Volume, greater<Price>> bids;
// 卖盘:价格升序排列(最低价在前)
map<Price, Volume> asks;
// 每个价格档位上的订单队列
map<Price, queue<Order>> bidOrders;
map<Price, queue<Order>> askOrders;
};
每个价格档位上,可能有多笔订单。这些订单按到达时间排队。
2.2.2 订单簿的更新事件
订单簿不是静态的,它每时每刻都在变。主要更新事件有四种:
| 事件类型 | 触发条件 | 对订单簿的影响 |
|---|---|---|
| 新订单到达 | 交易者挂单 | 在对应价格档位增加数量 |
| 订单成交 | 市价单吃掉限价单 | 减少或移除对应档位的数量 |
| 订单撤单 | 交易者取消挂单 | 移除对应档位的数量 |
| 订单修改 | 交易者改价或改量 | 先撤单,再重新挂单 |
嗯,这里要注意:修改订单在底层其实是「撤单+新单」两个操作。我见过不少新手以为修改是原子操作,结果在回测时算错了延迟。
2.3 价格优先与时间优先原则
这是订单簿撮合的核心规则。说白了就两句话:
- 价格优先:出价高的买单优先成交,要价低的卖单优先成交
- 时间优先:价格相同时,先挂单的先成交
2.3.1 价格优先怎么理解?
假设当前订单簿是这样的:
卖盘(Ask):
价格 100.10 数量 200
价格 100.05 数量 150
价格 100.00 数量 300 ← 最优卖价
买盘(Bid):
价格 99.90 数量 250
价格 99.85 数量 100
价格 99.80 数量 400 ← 最优买价
如果你下了一个市价买单,系统会先吃掉最优卖价100.00上的300股。如果还不够,再吃100.05上的150股,以此类推。
反过来,市价卖单会先打掉最优买价99.90上的250股。
2.3.2 时间优先怎么理解?
同一个价格上,谁先挂单谁先成交。举个例子:
- 9:00:00 张三挂100.00卖单,数量100
- 9:00:01 李四挂100.00卖单,数量100
- 9:00:02 王五下市价买单,数量150
成交结果:张三的100股全部成交,李四的100股只成交了50股。因为张三先挂单,优先成交。
2.4 订单簿的微观结构图
下面我用一张SVG图来展示订单簿的核心逻辑。这张图我画了很多遍,每次讲课都会拿出来用。
2.5 实战中的注意事项
讲完理论,说点实际的。我在实盘交易中踩过不少坑,分享几个关键点:
2.5.1 订单簿的深度不等于流动性
很多人看到订单簿上挂单很多,就觉得流动性好。其实不一定。有些挂单是「幽灵单」——挂上去又撤掉,根本不是为了成交。
我曾经在某个交易所做套利,看到买盘深度很厚,结果一吃单,价格直接滑了三个档位。后来才发现,那些挂单都是做市商用来误导人的。
2.5.2 时间优先的陷阱
同一个价格上,你的单子排在后面怎么办?
我的做法是:如果判断行情马上要动,我会用市价单直接吃掉对手盘,不跟别人排队。如果时间充裕,就挂限价单等着。
2.5.3 订单簿的更新频率
高频交易中,订单簿每秒可能更新上千次。如果你用轮询的方式去拉数据,延迟会很大。
我建议用WebSocket订阅增量数据流,只接收变化的部分,而不是每次都拉全量快照。
公众号:蓝海资料掘金营,微信deep3321