halo 的技术博客

返回

买卖价差(bid-ask spread)是市场里最普遍的现象之一,但它在学术上有个经典之问:价差从哪里来? 一种朴素答案是「做市商要赚手续费」。Glosten 与 Milgrom 在 1985 年给出了一针见血的另一种解释:价差来自逆向选择(adverse selection)——因为总有人比你知道得多,做市商和这些「知情者」做对手盘会亏钱,于是用价差给自己买保险。

本文先用 Glosten-Milgrom(以下简称 G-M)的序贯交易模型,把「报价如何随每一笔订单的信息更新」讲清楚;再补上一层更贴近实盘的现实:库存风险——做市商不是无情的贝叶斯机器,它怕持仓太大,于是报价会随库存整体移动、价差随库存加宽。所有数字和配图都由文末代码真实生成。

一、模型设定:两类交易者 + 一个不知情的做市商#

资产真实价值 V 只有两个可能:V_H=110V_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

对称地可得看到卖单后的后验 π''做市商的报价就是条件期望

关键点: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(知情者因此永远买)的情形:

结果(真实 V=110):

  • 末后验 π = 1.000,信息中间价(后验均值 ν)收敛到 110.00,恰好等于真实价值;
  • 但做市商库存:均值 −67.2,标准差 34.3,min −128,max 0

序贯交易:中间价收敛到真实 V,做市商被逆向选择成净空头

两条线讲了一个完整的故事:上面,随着知情买盘持续涌入,做市商不断上调对 V 的信念,中间价平滑地爬向 110——价格发现发生了。下面,因为买多卖少,做市商一直在「卖」,库存滚成了深度净空头。这就是逆向选择的真实代价:你正确地更新了价格,却被知情者「跑在前面」,账户上留下一堆不想持有的头寸。

五、库存风险:报价随持仓整体下移、价差随库存加宽#

纯粹贝叶斯做市商有个不现实的假设:它对所有库存水平一视同仁。真实做市商有风险约束——持仓越大,越怕再来一笔同向单把它打爆。Avellaneda-Stoikov 式的处理是引入保留价格(reservation price)

r(I) = E[V] − γ·I
plaintext

γ 是库存厌恶系数。库存 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 - half
python

代入参数(γ=0.05, κ=0.01):

  • 库存 +20 时,中间价整体下移 1.00 点(不愿再加仓);
  • 库存 |I|=20 时,价差在 8.00 的基础上额外加宽 0.40 点(为库存风险收费)。

库存风险:价差随 |库存| 加宽、中间价随库存下移

这张图把「库存风险」量化了:左轴是价差,纯逆向选择部分(8.00)是水平的底线,往上翘的是库存风险溢价;右轴是中间价,随库存增大整体下沉。它解释了实盘里一个常见现象——做市商在积累了大量多仓后,会主动把报价压低来劝退买家、吸引卖家,从而自我去库存;反之亦然。

六、真实陷阱(模型与现实的鸿沟)#

  1. 两值假设太粗:真实价值是连续的,G-M 用两值只为闭式可解。连续值下要换成连续先验 + 似然,结论(价差=逆向选择)不变,但报价公式要重做。
  2. κ、γ 不是白来的:正文为演示取了常数。实盘里它们来自做市商的风险预算与库存约束,应随账户规模、波动率动态调整,而非写死。
  3. 「知情者永远正确」是理想:真实知情者也有信息误差、也有仓位限制。一旦知情者会错,做市商的贝叶斯更新会系统性偏误。
  4. 忽略了竞争:G-M 是单一垄断做市商。多做市商竞争会把价差压到接近零(只留手续费/库存成本),此时价差更多反映库存与执行成本,而非纯信息不对称。
  5. 订单流不是 i.i.d.:真实里买卖有自相关、有批量、有算法刷单。序贯独立假设下得出的「平稳价差」在闪崩/事件时会瞬间撕裂——这时 VPIN 之类的订单流毒性指标才是真正该看的。
  6. 库存会触发强平:模型里库存可以无限滚到 −128。实盘有保证金和止损,库存到阈值会被强制平仓,那时「平滑去库存」变成「踩踏平仓」。

七、结论#

Glosten-Milgrom 用最少的假设讲清了一件事:买卖价差首先是信息不对称的保险费,而不是做市商的暴利。一笔买单推高报价、一笔卖单压低报价,中间的裂口就是做市商为「可能正在和知情者对手交易」付的代价;随着订单流累积,中间价收敛到真实价值,价格发现完成。

但纯贝叶斯做市商不懂害怕。加上库存风险后,报价不再只是信息的函数,也是持仓的函数:库存越大,保留价格越低、价差越宽——做市商用这两条把手,一边定价信息、一边管理风险。理解这两层(逆向选择 + 库存),才算真正看懂了做市商屏幕上的那串买卖价。


完整可复现代码(含 G-M 贝叶斯报价、单步更新、序贯模拟、库存风险扩展、三张配图)已随本文生成脚本一并运行,所有统计数字均来自该脚本的真实输出。

做市商库存风险与 Glosten-Milgrom 模型:报价如何随信息调整
https://blog.halo26812.eu.org/blog/glosten-milgrom-mm
Author halo
Published at 2026年7月12日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨