halo 的技术博客

返回

在高频交易里,最容易被忽略、却最致命的一个变量,是你的限价单在订单簿里排在第几位

同样挂在买一档(best bid)的一笔买单:排在最前面(front of queue)的那位,下一个市价卖单砸下来就被他吃掉;排在队尾的,可能要等前面十几个人全成交了才轮到他——而价格很可能已经不在那个档位了。更反直觉的是:排第一未必最好。队首成交最快,但也最快暴露在知情交易者的抛压下,被「逆向选择」吃掉的风险最高。

结论先放这:队列位置价值是一个「先升后降」的非单调函数。在我们的离散时间队列模型里,买一档队首的成交概率是 83.0%,第 10 位只剩 15.4%,第 20 位仅 2.3%——成交概率随排队深度单调衰减。但把「成交后赚到的价差」减去「越快成交越高的逆向选择成本」后,价值最高的位置是第 3 位(0.449),而非队首(0.384)。换句话说,最前面那位虽然几乎必成,却因为成交太快、吃进了太多「别人急着甩给你」的货,净价值反而被腐蚀。


1. 队列位置是什么#

限价订单簿(LOB)里,每个价格档位都是一个 FIFO(先进先出)的队列。你在买一档挂了一笔买单,前面可能已经有人挂了更早的买单。你的「队列位置」r = 前面还有多少笔同价买单 + 1:

  • r = 1:你是队首,下一笔市价卖单直接吃你;
  • r = 10:前面还有 9 笔,得等它们全被吃掉你才轮到;
  • 一旦价格跌到买一档之下(你的报价变成「远离最优价」),或者你主动撤单,这笔单就再也不会成交。

成交概率随队列位置衰减

直觉上,r 越大,成交概率越低——这是对的。但「能不能成交」只是问题的一半;另一半是:成交了之后,这笔交易到底是赚钱还是接盘? 这正是队列位置价值的精妙之处。


2. 用离散时间队列模型量化成交概率#

我们把买一档的队列演化建模成一个离散时间的随机过程。每个时间步,以下四类事件之一以固定概率发生:

事件含义对队列位置 r 的影响
市价卖(sell)一笔市价卖单砸向买一档r ← r−1;若 r≤0 则你成交
限价买加入(join)新买单排在队尾r ← r+1
价格下跌(drop)报价劣化,你这单永远不成交直接判「未成交」
价格上涨(up)对成交逻辑无影响(只影响 PnL)不变

设 P_SELL=0.32、P_JOIN=0.28、P_DROP=0.018、P_UP=0.018,对某个起始位置 r 做 N_SIM=40000 次蒙特卡洛模拟,统计它最终成交的比例,就得到该位置的成交概率。代码:

模拟结果(与文首配图一致):

  • 队首 r=1:成交概率 83.0%
  • 第 10 位 r=10:15.4%
  • 第 20 位 r=20:2.3%

成交概率随 r 严格单调下降——这一点毫无意外。真正有趣的是下面这层。


3. 队列位置价值:为什么「第一」不一定是最好#

成交概率高 ≠ 价值高。因为你成交的那一刻,正是你「接住」了一笔市价卖单的那一刻。如果这笔卖单来自知情交易者(他们知道坏消息,急着在价格崩之前甩货),你成交得越快,就越是精准地接下了他们的盘——这就是做市商文献里的逆向选择成本(adverse selection cost)

我们做一个最简单的建模:成交后你赚到半个价差 S(假设 S=2.0 个 tick 的预期 PnL),但要付出逆向选择成本 A。关键点在于,A 随成交速度上升——成交越快,越可能是被催着甩货的卖方推着你成交:

A(r)=A0+A1fill_prob(r)A(r) = A_0 + A_1 \cdot \text{fill\_prob}(r)

令 A0=0.5、A1=1.25,则队列位置价值为:

value(r)=fill_prob(r)(SA(r))\text{value}(r) = \text{fill\_prob}(r) \cdot \big(S - A(r)\big)

队列位置价值:非单调的甜点

代入我们的模拟数字:

  • 队首 r=1:fill_prob=0.830,逆向成本 A=1.538,value = 0.830 × (2.0 − 1.538) = 0.384
  • 第 3 位 r=3:fill_prob 略低,但 A 也大幅下降,value 冲到峰值 0.449
  • 第 10 位 r=10:fill_prob=0.154,A=0.693,value = 0.154 × 1.307 = 0.201
  • 第 20 位 r=20:fill_prob=0.023,value 趋近 0

value 在 r=3 处达到最大,而非 r=1。 这就是队列位置的「甜点效应」:队首虽然几乎必成,但被逆向选择啃掉太多;稍微靠后一点,既还保持着不错的成交概率,又避开了最凶的知情抛压,净价值反而最高。

S, A0, A1 = 2.0, 0.5, 1.25
adv_cost = A0 + A1 * fill_prob
value = fill_prob * (S - adv_cost)

best = positions[np.argmax(value)]
print(best, value.max(), value[0])
# -> 3   0.449   0.384
python

4. 用订单流失衡 OFI 调制「有效成交率」#

上面的模型把 P_SELL 当成常数。实战中它显然不是——当**订单流失衡(OFI)**偏向买方时,市价卖单变少,你的有效成交率下降;OFI 偏向卖方时,市价卖单汹涌,你排队前进得飞快。

这正是队列位置建模和既有 OFI 框架的衔接点。我们令有效市价卖率 λ_eff 随 OFI 调制:

λeff=λ0(1βOFI),OFI[1,1]\lambda_{eff} = \lambda_0 \cdot (1 - \beta \cdot OFI), \quad OFI \in [-1, 1]

当 OFI=+0.5(买方强势),λ_eff 下降约一半,同样排在第 5 位的单子,成交耗时近乎翻倍。这个耦合告诉我们一个朴素的执行直觉:在买方失衡、价格可能上行时,别把大单挂在买一档当队首——你大概率排很久,且一旦成交就踏空了上涨。


5. 五类实战陷阱(高频)#

  1. 逆向选择成本被低估:本文用线性 A(r) 近似,真实市场里 A 随成交速度可能是凸的——队首被啃得更狠。把 A 当成常数会系统性高估队首价值,让你误以为「永远排第一最好」。
  2. 队列位置的「幽灵」:很多撮合系统不公开你的精确队列位置(只给档位总量),你只能估算 r。估算误差直接翻译成成交概率误差,且对尾部位置(r 大)尤其敏感。
  3. 撤单重挂的跳动:高频里撤单重挂会让你回到队尾(r 重置)。模型假设「一旦挂入就静止」,没算重挂导致的有效位置退化——实盘中这是最大的隐藏损耗。
  4. drop 概率随波动率时变:P_DROP 在崩盘时飙升,本文用常数 0.018。真实市场里崩盘时你的买一档报价会瞬间劣化,成交概率被进一步压低,模型给出的是「平静市」乐观上界。
  5. 跨档迁移:价格小幅波动时,你的单可能从买一档掉到买二档再回来,队列逻辑要重算。单档模型忽略了跨档迁移带来的位置重置。

6. 完整 Python 代码#

下面是本文全部数字与配图的端到端复现脚本:


一句话总结:队列位置价值不是「越靠前越好」,而是「成交概率」与「逆向选择成本」的权衡。建模它,你才真正理解——为什么高频做市商愿意花工程代价去争那零点几个 tick 的排队优势,又为什么它们从不在最凶的知情抛压下站队首。

限价订单簿队列位置价值:你的挂单排在买一档第几位,决定了它值多少钱
https://blog.halo26812.eu.org/blog/lob-queue-position-value
Author halo
Published at 2026年7月21日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨