在高频交易里,最容易被忽略、却最致命的一个变量,是你的限价单在订单簿里排在第几位。
同样挂在买一档(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 次蒙特卡洛模拟,统计它最终成交的比例,就得到该位置的成交概率。代码:
import numpy as np
P_SELL, P_JOIN, P_DROP, P_UP = 0.32, 0.28, 0.018, 0.018
N_SIM = 40000
MAX_STEPS = 5000
def simulate(position):
"""返回 (filled: bool, steps_to_fill: int)。"""
r = position # 1 = 队首
for _ in range(MAX_STEPS):
u = np.random.random()
if u < P_SELL: # 市价卖砸向买一档
r -= 1
if r <= 0:
return True, _ + 1
elif u < P_SELL + P_JOIN: # 新限价买加入队尾
r += 1
elif u < P_SELL + P_JOIN + P_DROP:
return False, -1 # 报价劣化,永不成交
# P_UP:价格上涨,不影响成交逻辑
return False, -1 # 超时未成交
positions = np.arange(1, 21)
fill_prob = []
for r in positions:
filled = sum(simulate(r)[0] for _ in range(N_SIM))
fill_prob.append(filled / N_SIM)
fill_prob = np.array(fill_prob)python模拟结果(与文首配图一致):
- 队首 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 随成交速度上升——成交越快,越可能是被催着甩货的卖方推着你成交:
令 A0=0.5、A1=1.25,则队列位置价值为:

代入我们的模拟数字:
- 队首 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.384python4. 用订单流失衡 OFI 调制「有效成交率」#
上面的模型把 P_SELL 当成常数。实战中它显然不是——当**订单流失衡(OFI)**偏向买方时,市价卖单变少,你的有效成交率下降;OFI 偏向卖方时,市价卖单汹涌,你排队前进得飞快。
这正是队列位置建模和既有 OFI 框架的衔接点。我们令有效市价卖率 λ_eff 随 OFI 调制:
当 OFI=+0.5(买方强势),λ_eff 下降约一半,同样排在第 5 位的单子,成交耗时近乎翻倍。这个耦合告诉我们一个朴素的执行直觉:在买方失衡、价格可能上行时,别把大单挂在买一档当队首——你大概率排很久,且一旦成交就踏空了上涨。
5. 五类实战陷阱(高频)#
- 逆向选择成本被低估:本文用线性 A(r) 近似,真实市场里 A 随成交速度可能是凸的——队首被啃得更狠。把 A 当成常数会系统性高估队首价值,让你误以为「永远排第一最好」。
- 队列位置的「幽灵」:很多撮合系统不公开你的精确队列位置(只给档位总量),你只能估算 r。估算误差直接翻译成成交概率误差,且对尾部位置(r 大)尤其敏感。
- 撤单重挂的跳动:高频里撤单重挂会让你回到队尾(r 重置)。模型假设「一旦挂入就静止」,没算重挂导致的有效位置退化——实盘中这是最大的隐藏损耗。
- drop 概率随波动率时变:P_DROP 在崩盘时飙升,本文用常数 0.018。真实市场里崩盘时你的买一档报价会瞬间劣化,成交概率被进一步压低,模型给出的是「平静市」乐观上界。
- 跨档迁移:价格小幅波动时,你的单可能从买一档掉到买二档再回来,队列逻辑要重算。单档模型忽略了跨档迁移带来的位置重置。
6. 完整 Python 代码#
下面是本文全部数字与配图的端到端复现脚本:
import numpy as np
import matplotlib.pyplot as plt
P_SELL, P_JOIN, P_DROP, P_UP = 0.32, 0.28, 0.018, 0.018
N_SIM, MAX_STEPS = 40000, 5000
rng = np.random.default_rng(20260721)
def simulate(position):
r = position
for _ in range(MAX_STEPS):
u = rng.random()
if u < P_SELL:
r -= 1
if r <= 0:
return True, _ + 1
elif u < P_SELL + P_JOIN:
r += 1
elif u < P_SELL + P_JOIN + P_DROP:
return False, -1
return False, -1
positions = np.arange(1, 21)
fill_prob = np.array([sum(simulate(r)[0] for _ in range(N_SIM)) / N_SIM
for r in positions])
S, A0, A1 = 2.0, 0.5, 1.25
adv_cost = A0 + A1 * fill_prob
value = fill_prob * (S - adv_cost)
print("队首成交概率:", round(fill_prob[0], 3)) # 0.830
print("第10位成交概率:", round(fill_prob[9], 3)) # 0.154
print("第20位成交概率:", round(fill_prob[19], 3)) # 0.023
print("最佳位置:", positions[np.argmax(value)],
"价值:", round(value.max(), 3)) # 3, 0.449
print("队首价值:", round(value[0], 3)) # 0.384
plt.figure(); plt.plot(positions, fill_prob, "-o")
plt.xlabel("Queue position"); plt.ylabel("Fill probability")
plt.title("Fill probability vs queue position"); plt.grid(alpha=0.3)
plt.savefig("fill_prob_vs_position.png", dpi=130)
plt.figure(); plt.plot(positions, value, "-o")
plt.axhline(0, color="k", ls="--")
plt.xlabel("Queue position"); plt.ylabel("Expected value")
plt.title("Queue position value (non-monotonic sweet spot)")
plt.grid(alpha=0.3); plt.savefig("queue_value_by_position.png", dpi=130)python一句话总结:队列位置价值不是「越靠前越好」,而是「成交概率」与「逆向选择成本」的权衡。建模它,你才真正理解——为什么高频做市商愿意花工程代价去争那零点几个 tick 的排队优势,又为什么它们从不在最凶的知情抛压下站队首。