一、订单簿基础:什么是订单簿?限价单与市价单的区别,订单簿的构成要素
各位同学,咱们今天聊聊订单簿。这东西说白了,就是交易所用来记录所有买卖挂单的「大账本」。我做了这么多年量化交易系统,可以负责任地告诉你——不理解订单簿,就别谈什么高频交易、做市策略。
你打开任何一个交易软件的深度图,看到的那两条曲线,其实就是订单簿的可视化呈现。但订单簿本身,远比一张图要复杂得多。
1.1 什么是订单簿?
订单簿(Order Book),是交易所维护的一个实时数据结构。它记录了所有尚未成交的限价单。买方挂单在左侧,卖方挂单在右侧。中间那个成交价,就是当前市场博弈的结果。
我个人习惯把订单簿想象成一个「排队系统」。买方想低价买,就排在前面;卖方想高价卖,也排在前面。价格优先、时间优先——这是订单簿最核心的撮合规则。
核心要点:订单簿不是静态的。每一秒都有新订单进来,也有订单被撤掉或成交。它是市场微观结构的实时快照。
我在项目中遇到过一件事:有个同事写策略时,直接拿订单簿的快照数据做决策,结果因为网络延迟,拿到的数据已经是500毫秒前的了。嗯,这500毫秒里,订单簿可能已经变了三回。所以,理解订单簿的「时效性」非常重要。
1.2 限价单 vs 市价单
这两种订单类型,是交易系统里最基础的概念。但很多人其实没搞明白它们的本质区别。
| 特性 | 限价单(Limit Order) | 市价单(Market Order) |
|---|---|---|
| 价格控制 | 你指定价格,不达到就不成交 | 你不指定价格,按当前最优价成交 |
| 成交确定性 | 低——可能永远不成交 | 高——几乎立即成交 |
| 对订单簿的影响 | 增加流动性(挂单) | 消耗流动性(吃单) |
| 滑点风险 | 无滑点(但可能不成交) | 有滑点(尤其大单时) |
| 典型使用场景 | 做市、挂单等待 | 追涨杀跌、快速建仓 |
你想想看,限价单就像你在菜市场喊「三块钱一斤我才买」,市价单就是「不管多少钱,给我来两斤」。前者你可能等一天都买不到,后者你瞬间就能拿到货,但可能多花点钱。
我的经验:做高频策略时,我几乎只用限价单。因为市价单的滑点会吃掉你所有的利润。但做趋势跟踪时,市价单反而更合适——你不想因为差一分钱而错过一波行情。
1.3 订单簿的构成要素
一个标准的订单簿,由三个核心维度构成:价格、数量、时间。缺一不可。
1.3.1 价格(Price)
价格是订单簿的「坐标轴」。所有挂单都按价格排列。买方从高到低排,卖方从低到高排。中间那个价差(Spread),就是买卖双方的心理差距。
我记得有一次调试一个做市策略,发现价差突然从0.01美元扩大到0.05美元。我第一反应是——市场出问题了?后来一查,原来是某个大机构撤掉了所有挂单。价差就是流动性的温度计,这一点都不夸张。
1.3.2 数量(Volume)
数量代表每个价格档位上的挂单量。它反映了市场深度。比如买一价上有1000股,买二价上有5000股——这说明买方的支撑力度在逐渐增强。
这里有个坑,我曾经踩过:只看「总挂单量」是不够的。你得看「挂单分布」。有些庄家会在某个价格挂大量假单,然后瞬间撤掉。这叫「幌骗」(Spoofing)。我当年写风控模块时,专门加了一个「挂单稳定性检测」——如果一个价格档位的挂单在1秒内变化超过50%,我就标记为可疑。
1.3.3 时间(Time)
时间决定了订单的优先级。同样价格的订单,先来的先成交。这就是「价格优先、时间优先」规则。
时间维度还有一个隐藏信息——订单的「年龄」。一个挂了10分钟还没成交的限价单,和刚挂上去的限价单,市场含义完全不同。前者可能说明这个价格不被市场认可,后者还在博弈中。
注意:在极速交易场景下,时间精度要到微秒甚至纳秒级。我见过一个系统,因为时间戳精度不够,导致两个订单的先后顺序判断错误,结果造成了十几万的损失。时间,在订单簿里就是金钱。
1.4 订单簿的层级结构
为了让你更直观地理解,我画了一张订单簿的结构图。它展示了买卖双方的挂单分布,以及中间那个成交价的位置。
这张图里,你能看到买卖双方的挂单分布。买一和卖一之间的那个空隙,就是价差。价差越小,说明市场流动性越好。我一般看一个品种好不好做,先看价差——价差超过0.1%的,我基本就不碰了。
1.5 订单簿的实时更新机制
订单簿不是画出来就完事了。它是实时变化的。每一次新订单进来、每一次成交、每一次撤单,都会触发订单簿的更新。
我写过一个简单的订单簿更新逻辑,大概长这样:
// 伪代码:订单簿更新核心逻辑
function updateOrderBook(orderBook, newOrder) {
if (newOrder.type === 'LIMIT') {
// 限价单:插入到对应价格档位
let priceLevel = orderBook.getLevel(newOrder.price);
if (priceLevel) {
priceLevel.addOrder(newOrder);
} else {
orderBook.createLevel(newOrder.price, newOrder);
}
} else if (newOrder.type === 'MARKET') {
// 市价单:从最优价格开始吃单
while (newOrder.remainingVolume > 0) {
let bestLevel = orderBook.getBestLevel(newOrder.side);
if (!bestLevel) break; // 没有对手盘了
let matched = Math.min(newOrder.remainingVolume, bestLevel.volume);
newOrder.remainingVolume -= matched;
bestLevel.volume -= matched;
if (bestLevel.volume === 0) {
orderBook.removeLevel(bestLevel);
}
}
}
// 触发事件通知
orderBook.emit('updated');
}
这段代码虽然简单,但已经涵盖了订单簿更新的核心逻辑。实际生产环境中,还要处理并发、锁、性能优化等问题。我当年用C++写订单簿引擎时,为了把单次更新延迟压到1微秒以下,折腾了整整两周。
避坑指南:我曾经犯过一个错误——在订单簿更新时直接修改原始数据,导致其他线程读取到了不一致的状态。后来我改用「写时复制」(Copy-on-Write)模式,每次更新都生成一个新版本的订单簿快照。虽然内存开销大了点,但保证了数据一致性。
1.6 订单簿与市场不确定性的关系
好了,聊了这么多订单簿的基础,你可能要问——这跟「市场不确定性度量」有什么关系?
关系大了去了。订单簿里藏着市场参与者的「真实意图」。每一笔挂单,都是一个人对价格的判断。当订单簿变得稀疏(挂单少、价差大),说明市场参与者意见分歧大,不确定性高。当订单簿变得厚实(挂单多、价差小),说明市场意见趋于一致,不确定性低。
后面几章我们会深入讲如何用信息熵来量化这种不确定性。但今天,你只需要记住一句话:订单簿是市场不确定性的「显微镜」。你越懂订单簿,就越能看清市场的真实面貌。
嗯,今天就先到这里。订单簿的基础概念,你消化一下。下一章我们开始讲「信息熵」——那个能把订单簿数据变成数字的神奇工具。
公众号:蓝海资料掘金营,微信deep3321