一、订单簿基础:限价单与市价单、买卖盘口、深度图、订单簿快照与增量更新

大家好,我是你们的量化交易工程师朋友。今天咱们来聊聊订单簿——这个所有订单驱动市场的核心引擎。说实话,我刚开始接触这个领域时,觉得订单簿不就是个买卖挂单列表吗?后来在实盘中被狠狠教育了几次,才明白这里面门道深着呢。

1.1 限价单与市价单:交易世界的两种基本指令

先说说最基础的两个概念。限价单和市价单,说白了就是「我想用多少钱买」和「我不管多少钱,立刻给我成交」的区别。

限价单(Limit Order):你指定一个价格,只有市场达到这个价格时才会成交。比如你想在100元买入某股票,那就挂一个限价买单。价格不到100,单子就一直在订单簿里挂着,等着被吃掉。

市价单(Market Order):你只说要买多少数量,系统按当前最优价格立刻成交。比如你下了一个市价买单,系统会先吃掉卖一价位的单子,不够再吃卖二,直到满足你的数量为止。

我个人习惯把限价单叫做「耐心单」,市价单叫做「急迫单」。为什么?你想想看,限价单提供了流动性,市价单消耗了流动性。这个区别在后面的做市策略中非常关键。

核心区别速览:
  • 限价单:指定价格,不保证成交,提供流动性
  • 市价单:不指定价格,保证成交,消耗流动性

我在项目中遇到过这样一个坑:某个高频策略同时使用了限价单和市价单,结果因为限价单的成交延迟,导致市价单在价格剧烈波动时吃到了极差的价位。嗯,这里要注意——两种订单的配合时机非常重要。

1.2 买卖盘口:订单簿的骨架

买卖盘口(Order Book)就是所有限价单的集合。买盘(Bid)在左边,卖盘(Ask)在右边。每个价位上挂着多少数量,一目了然。

举个例子,假设某股票的订单簿长这样:

买价(Bid) 买量 卖价(Ask) 卖量
99.80 200 100.20 150
99.70 500 100.30 300
99.60 800 100.40 600

这里有个关键指标叫「买卖价差」(Bid-Ask Spread),就是最优买价和最优卖价的差值。上面这个例子,价差是100.20 - 99.80 = 0.40元。价差越小,说明市场流动性越好。

我曾经在某个流动性极差的币种上吃过亏——价差大到1%以上,一个市价单下去直接滑点吃掉所有利润。所以我现在看任何交易品种,第一件事就是看价差。

1.3 深度图:把订单簿画出来

深度图(Depth Chart)就是把订单簿可视化。横轴是价格,纵轴是累计数量。买盘从最优买价往左延伸,卖盘从最优卖价往右延伸。

为什么要看深度图?因为数字列表不够直观。深度图能让你一眼看出:

  • 哪个价位有大量挂单(支撑位/阻力位)
  • 市场深度够不够(大单会不会造成剧烈滑点)
  • 买卖力量是否均衡

下面是我用SVG画的一个典型深度图结构,展示买盘和卖盘的累积深度:

订单簿深度图示例 最优价格 买盘深度 卖盘深度 低价 高价 累计数量

你看,买盘深度曲线越陡峭,说明在低价位有大量买单支撑;卖盘曲线越平缓,说明卖压相对分散。这个图形对判断市场情绪很有帮助。

1.4 订单簿快照与增量更新

这是实盘交易中非常关键的技术细节。订单簿数据有两种获取方式:

快照(Snapshot):某一时刻订单簿的完整状态。包含所有价位的买卖挂单。通常在你订阅行情时,交易所会先推送一个快照给你。

增量更新(Incremental Update):订单簿发生变化的部分。比如有人挂了一个新单、撤单、或者成交了,交易所只推送变化的数据。

为什么要区分这两种?说白了,快照数据量大,不适合高频推送;增量更新数据量小,适合实时同步。但增量更新有个前提——你必须基于正确的快照来应用增量,否则数据会越偏越远。

⚠️ 我曾经踩过的坑: 某个策略在断线重连后,只接收了增量更新,没有重新获取快照。结果订单簿数据完全错位,导致策略在错误的价格上挂单。后来我强制要求:每次重连必须先拿快照,再应用增量。

下面是一个典型的增量更新数据结构:

// 增量更新示例(JSON格式)
{
  "type": "incremental",
  "timestamp": 1699000000123,
  "bids": [
    [99.80, 200],   // 价格99.80,数量200(新增或更新)
    [99.70, 0]      // 价格99.70,数量0(表示撤单)
  ],
  "asks": [
    [100.20, 150],
    [100.30, 0]
  ]
}

注意看,数量为0表示该价位的单子被撤掉了。这是增量更新的标准做法——用数量0来标记删除操作。

1.5 实战中的订单簿管理

在实盘系统中,我通常这样管理订单簿:

  1. 初始化:订阅行情后,先请求一次快照,建立完整的订单簿
  2. 实时更新:每收到一条增量消息,更新本地订单簿的对应价位
  3. 校验机制:每隔一段时间(比如5分钟),主动请求一次快照做对比,防止数据漂移
  4. 异常处理:如果发现增量序号不连续,立即丢弃本地数据,重新获取快照
💡 小技巧: 我个人习惯用红黑树或跳表来存储订单簿,因为需要频繁的插入、删除和范围查询。Python的话可以用sortedcontainers库,C++直接用std::map。别用数组硬撸,性能会差很多。

最后说一句,订单簿是交易系统的地基。地基不稳,上面的策略再牛也是空中楼阁。我见过太多人一上来就研究各种复杂策略,结果连订单簿数据都没处理好,实盘一跑就崩。嗯,先把基础打牢,后面的事情会顺利很多。


公众号:蓝海资料掘金营,微信deep3321