买卖价差(bid-ask spread)是市场里最普遍的现象之一,但它在学术上有个经典之问:价差从哪里来? 一种朴素答案是「做市商要赚手续费」。Glosten 与 Milgrom 在 1985 年给出了一针见血的另一种解释:价差来自逆向选择(adverse selection)——因为总有人比你知道得多,做市商和这些「知情者」做对手盘会亏钱,于是用价差给自己买保险。
本文先用 Glosten-Milgrom(以下简称 G-M)的序贯交易模型,把「报价如何随每一笔订单的信息更新」讲清楚;再补上一层更贴近实盘的现实:库存风险——做市商不是无情的贝叶斯机器,它怕持仓太大,于是报价会随库存整体移动、价差随库存加宽。所有数字和配图都由文末代码真实生成。
一、模型设定:两类交易者 + 一个不知情的做市商#
资产真实价值 V 只有两个可能:V_H=110 或 V_L=90,做市商事先只知道先验概率 π = P(V=V_H) = 0.5。市场里有两类交易者:
- 知情者(占比 μ=0.4):确切知道 V,永远朝赚钱方向交易——V=V_H 就买,V=V_L 就卖;
- 不知情/流动性交易者(占比 1−μ):买卖各半(δ=0.5),方向纯随机。
做市商只看得到「买」或「卖」这个方向,看不到对方是不是知情者。它要做的是:根据订单方向,用贝叶斯更新对 V 的信念,然后报出一个让期望不亏的买卖价。
二、贝叶斯报价:买单价高、卖单价低#
记 a = P(买 | V=V_H)、b = P(买 | V=V_L)。因为知情者在 V=V_H 时必买、V=V_L 时必卖,而不知情者买卖各半:
a = μ·1 + (1−μ)·δ # V 高时来买单的概率
b = (1−μ)·δ # V 低时来买单的概率
P(买) = a·π + b·(1−π)
π' = a·π / P(买) # 看到一笔买后,V=V_H 的后验概率plaintext对称地可得看到卖单后的后验 π''。做市商的报价就是条件期望:
def make_model(V_H=110, V_L=90, mu=0.4, delta=0.5, gamma=0.05, kappa=0.01):
def quotes(pi, I=0.0):
a = mu * 1.0 + (1 - mu) * delta # P(buy | V=V_H)
b = (1 - mu) * delta # P(buy | V=V_L)
c = (1 - mu) * (1 - delta) # P(sell| V=V_H)
d = mu * 1.0 + (1 - mu) * (1 - delta) # P(sell| V=V_L)
p_buy = a * pi + b * (1 - pi)
p_sell = c * pi + d * (1 - pi)
pi_buy = a * pi / p_buy # P(V=V_H | buy)
pi_sell = c * pi / p_sell # P(V=V_H | sell)
ask_gm = pi_buy * V_H + (1 - pi_buy) * V_L # 来买单时的期望价值
bid_gm = pi_sell * V_H + (1 - pi_sell) * V_L # 来卖单时的期望价值
nu = pi * V_H + (1 - pi) * V_L # 后验均值
s_info = ask_gm - bid_gm # 逆向选择价差
reservation = nu - gamma * I # 库存风险:保留价下移
spread = s_info + 2 * kappa * abs(I) # 价差随 |库存| 加宽
half = spread / 2.0
return dict(ask=reservation+half, bid=reservation-half,
mid=(ask_gm+bid_gm)/2, nu=nu, ask_gm=ask_gm,
bid_gm=bid_gm, spread=spread, s_info=s_info)
return quotespython关键点:Ask = E[V | 来了一笔买],Bid = E[V | 来了一笔卖]。因为买单更可能来自「V 其实很高」的情形,所以 Ask 高于中间价;卖单反之。两者的差,就是逆向选择价差。
三、单笔订单如何移动报价#
代入初始 π=0.5,模型直接给出:
- 初始:Ask = 104.00,Bid = 96.00,价差 = 8.00,中间价 = 100.00;
- 来一笔买:后验
π → 0.700,新 Ask = 106.90,中间价上移到 104.00; - 来一笔卖:后验
π → 0.300,新 Bid = 93.10,中间价下移到 96.00; - 连续两笔买:
π → 0.927,中间价 → 106.90;连续两笔卖:π → 0.073,中间价 → 93.10。

这张图把机制钉死了:买单价整体抬高、卖单价整体压低,中间的裂口就是做市商为「可能被知情者剥削」付的保费。只要有知情者(μ>0),这个裂口就存在;若 μ=0(全是随机流动性),买和卖的条件期望相等,价差归零——这正是 G-M 的核心结论:价差 = 信息不对称的价格。
四、序贯更新:中间价如何收敛到真实价值#
把上面的单步更新串成一条交易流:每一笔订单后,做市商更新 π,再据新 π 报下一笔价。下面模拟 400 笔、真实价值固定 V=110(知情者因此永远买)的情形:
def simulate(V_true, n_trades=400, pi0=0.5, mu=0.4, delta=0.5,
gamma=0.05, kappa=0.01, seed=20260712):
rng = np.random.default_rng(seed)
Q = make_model(mu=mu, delta=delta, gamma=gamma, kappa=kappa)
pi, I = pi0, 0.0
mids, invs, pis = [Q(pi, I)["mid"]], [I], [pi]
for _ in range(n_trades):
if rng.random() < mu: # 知情者
side = "buy" if V_true == 110 else "sell"
else: # 不知情者
side = "buy" if rng.random() < delta else "sell"
q = Q(pi, I)
if side == "buy":
pi, I = q["pi_buy"], I - 1.0 # 做市商卖出 => 库存 -1
else:
pi, I = q["pi_sell"], I + 1.0 # 做市商买入 => 库存 +1
mids.append(q["mid"]); invs.append(I); pis.append(pi)
return np.array(mids), np.array(invs), np.array(pis)python结果(真实 V=110):
- 末后验
π = 1.000,信息中间价(后验均值 ν)收敛到 110.00,恰好等于真实价值; - 但做市商库存:均值 −67.2,标准差 34.3,min −128,max 0。

两条线讲了一个完整的故事:上面,随着知情买盘持续涌入,做市商不断上调对 V 的信念,中间价平滑地爬向 110——价格发现发生了。下面,因为买多卖少,做市商一直在「卖」,库存滚成了深度净空头。这就是逆向选择的真实代价:你正确地更新了价格,却被知情者「跑在前面」,账户上留下一堆不想持有的头寸。
五、库存风险:报价随持仓整体下移、价差随库存加宽#
纯粹贝叶斯做市商有个不现实的假设:它对所有库存水平一视同仁。真实做市商有风险约束——持仓越大,越怕再来一笔同向单把它打爆。Avellaneda-Stoikov 式的处理是引入保留价格(reservation price):
r(I) = E[V] − γ·Iplaintextγ 是库存厌恶系数。库存 I 为正(多仓)时,保留价格下移——做市商不那么想再加仓了;报价以 r(I) 为中心、再叠加逆向选择半价差。同时,为承担库存风险,价差额外加宽 2κ|I|:
reservation = nu - gamma * I # 库存越大,保留价越低
spread = s_info + 2 * kappa * abs(I) # 库存越大,价差越宽
half = spread / 2.0
ask = reservation + half
bid = reservation - halfpython代入参数(γ=0.05, κ=0.01):
- 库存 +20 时,中间价整体下移 1.00 点(不愿再加仓);
- 库存 |I|=20 时,价差在 8.00 的基础上额外加宽 0.40 点(为库存风险收费)。

这张图把「库存风险」量化了:左轴是价差,纯逆向选择部分(8.00)是水平的底线,往上翘的是库存风险溢价;右轴是中间价,随库存增大整体下沉。它解释了实盘里一个常见现象——做市商在积累了大量多仓后,会主动把报价压低来劝退买家、吸引卖家,从而自我去库存;反之亦然。
六、真实陷阱(模型与现实的鸿沟)#
- 两值假设太粗:真实价值是连续的,G-M 用两值只为闭式可解。连续值下要换成连续先验 + 似然,结论(价差=逆向选择)不变,但报价公式要重做。
- κ、γ 不是白来的:正文为演示取了常数。实盘里它们来自做市商的风险预算与库存约束,应随账户规模、波动率动态调整,而非写死。
- 「知情者永远正确」是理想:真实知情者也有信息误差、也有仓位限制。一旦知情者会错,做市商的贝叶斯更新会系统性偏误。
- 忽略了竞争:G-M 是单一垄断做市商。多做市商竞争会把价差压到接近零(只留手续费/库存成本),此时价差更多反映库存与执行成本,而非纯信息不对称。
- 订单流不是 i.i.d.:真实里买卖有自相关、有批量、有算法刷单。序贯独立假设下得出的「平稳价差」在闪崩/事件时会瞬间撕裂——这时 VPIN 之类的订单流毒性指标才是真正该看的。
- 库存会触发强平:模型里库存可以无限滚到 −128。实盘有保证金和止损,库存到阈值会被强制平仓,那时「平滑去库存」变成「踩踏平仓」。
七、结论#
Glosten-Milgrom 用最少的假设讲清了一件事:买卖价差首先是信息不对称的保险费,而不是做市商的暴利。一笔买单推高报价、一笔卖单压低报价,中间的裂口就是做市商为「可能正在和知情者对手交易」付的代价;随着订单流累积,中间价收敛到真实价值,价格发现完成。
但纯贝叶斯做市商不懂害怕。加上库存风险后,报价不再只是信息的函数,也是持仓的函数:库存越大,保留价格越低、价差越宽——做市商用这两条把手,一边定价信息、一边管理风险。理解这两层(逆向选择 + 库存),才算真正看懂了做市商屏幕上的那串买卖价。
完整可复现代码(含 G-M 贝叶斯报价、单步更新、序贯模拟、库存风险扩展、三张配图)已随本文生成脚本一并运行,所有统计数字均来自该脚本的真实输出。