订单簿动态:限价单与市价单、订单簿重建、价格形成机制
订单簿这东西,说白了就是市场的「心跳」。我做了这么多年量化,最深的体会就是——谁读懂了订单簿的动态,谁就抓住了微观结构的命脉。今天咱们就聊聊限价单和市价单怎么博弈、订单簿怎么重建,以及价格到底是怎么形成的。
一、限价单 vs 市价单:两种力量的角力
先问个问题:你下单的时候,是愿意「等」还是「抢」?
限价单就是「等」。你挂一个价格,等着有人来成交。好处是你能控制成本,坏处是可能永远等不到。我见过不少新手,挂个限价单就去睡觉了,结果行情一飞冲天,单子根本没成交。
市价单就是「抢」。你不管价格,直接吃掉对手盘里最好的单子。成交快,但成本不可控。我记得有一次做高频策略,市价单滑点直接吃掉了我们一个月的利润——嗯,从那以后我再也不敢轻视流动性了。
核心区别一句话:限价单提供流动性,市价单消耗流动性。两者共同决定了订单簿的「厚度」和「深度」。
在实际交易中,这两类订单的博弈构成了订单簿的动态变化。你想想看,如果市场上全是限价单,那价格几乎不动;如果全是市价单,那价格会像过山车一样。真正的市场,是两者动态平衡的结果。
二、订单簿重建:从原始数据到可分析结构
交易所给我们的原始数据,通常是逐笔成交和逐笔委托的「快照流」。但要做分析,必须重建出完整的订单簿。我个人习惯用以下步骤:
- 初始化:从第一个快照开始,建立买一到买N、卖一到卖N的初始队列
- 增量更新:每来一条新委托或成交,更新对应价格档位的数量
- 价格档位合并:把相同价格的订单合并,按价格排序
- 深度计算:累加每个价格档位以上的总挂单量
这里有个坑,我曾经踩过——快照和增量流的时间戳可能不同步。如果你先处理了增量再加载快照,订单簿就全乱了。我的做法是:先缓存增量,等快照到位后再回放。
下面是一个简化的订单簿重建代码示例:
class OrderBook:
def __init__(self):
self.bids = {} # 价格 -> 数量
self.asks = {}
def apply_snapshot(self, snapshot):
# snapshot: {bids: [[price, qty], ...], asks: [[price, qty], ...]}
self.bids = {p: q for p, q in snapshot['bids']}
self.asks = {p: q for p, q in snapshot['asks']}
def apply_update(self, update):
# update: {side: 'bid'/'ask', price: float, qty: float}
book = self.bids if update['side'] == 'bid' else self.asks
if update['qty'] == 0:
book.pop(update['price'], None) # 撤单
else:
book[update['price']] = update['qty'] # 新增或修改
def get_top(self, level=5):
sorted_bids = sorted(self.bids.items(), reverse=True)[:level]
sorted_asks = sorted(self.asks.items())[:level]
return sorted_bids, sorted_asks
小技巧:在实际生产中,建议用红黑树或跳表来维护价格档位,这样插入和删除都是O(log n)的。Python里可以用sortedcontainers库,C++里直接用std::map。
三、价格形成机制:订单簿如何「挤出」价格
价格是怎么来的?不是上帝定的,是订单簿里一笔一笔「挤」出来的。
核心机制其实很简单:
- 当市价买单进入时,它从卖一、卖二、卖三……一路吃下去,直到买完为止
- 成交的加权平均价格,就是这笔交易的「成交价」
- 如果市价单把某一档全部吃掉,价格就会跳到下一档
举个例子:假设卖一挂10.00元有100股,卖二挂10.01元有200股。你来一个市价买单买150股——那么前100股以10.00元成交,后50股以10.01元成交。成交均价是(100*10.00 + 50*10.01)/150 ≈ 10.0033元。而卖一被吃掉后,新的卖一变成了10.01元。
这就是价格形成的微观过程。说白了,价格就是订单簿被「啃」出来的结果。
注意:在极端行情下,订单簿可能瞬间被「啃穿」好几档。我经历过一次闪崩,卖一到卖十在0.1秒内全部被吃掉,价格直接跌了3%。这种时候,你的限价单如果挂在中间档位,很可能以远低于预期的价格成交。
四、订单簿动态的量化指标
光看价格变化还不够,我们需要一些量化指标来捕捉订单簿的动态特征。我个人常用的有这几个:
| 指标 | 定义 | 用途 |
|---|---|---|
| 买卖价差 | 卖一价 - 买一价 | 衡量流动性成本 |
| 订单簿斜率 | 价格变化 / 深度变化 | 判断价格弹性 |
| 订单簿不平衡 | (买盘总量 - 卖盘总量) / (买盘总量 + 卖盘总量) | 预测短期方向 |
| 成交集中度 | 最近N笔成交在价格档位上的分布 | 识别关键价位 |
这些指标怎么用?我举个例子。订单簿不平衡如果突然从0.2跳到0.8,说明买盘急剧增加。这时候如果你做市,就应该提高卖价,或者减少卖单挂单。我曾经用这个指标做了一个简单的做市策略,年化收益能跑赢基准5%左右——当然,回撤也大,遇到大单冲击时容易翻车。
五、实战中的避坑指南
最后分享几个我踩过的坑:
- 数据延迟:订单簿重建依赖实时数据流,网络延迟会导致重建出来的订单簿和真实情况有偏差。我曾经因为机房网络抖动,订单簿重建慢了200毫秒,结果策略在错误的价格上成交了。
- 冰山订单:有些大单会隐藏真实数量,只显示一部分。如果你只看表面订单簿,会被误导。我的做法是结合逐笔成交数据,反推隐藏订单的存在。
- 订单簿的「幽灵」:有些高频做市商会挂单后立即撤单,制造虚假深度。这种订单在订单簿上存在时间极短,如果你用低频快照重建,根本看不到。建议用逐笔委托流来识别。
一句话总结:订单簿动态不是静态的快照,而是一个不断演化的生态系统。限价单和市价单的博弈、订单簿的实时重建、价格的形成机制,这三者构成了市场微观结构的核心。理解了它们,你才算真正「看见」了市场。
下面这张图展示了订单簿动态的核心逻辑:
嗯,以上就是订单簿动态的核心内容。记住,纸上得来终觉浅,建议你拿真实数据跑一遍订单簿重建的代码,感受一下数据流的节奏。你会发现,市场比你想象的更有「性格」。
公众号:蓝海资料掘金营,微信deep3321