halo 的技术博客

返回

做市商(market maker)赚的是买卖价差,但真正能把它做破产的,几乎从来不是价差太小,而是库存。一笔接一笔的成交之后,做市商手里堆起了一整筐股票——涨了是浮盈,跌了是实亏,而中间价的下一跳他控制不了。这就是「库存风险(inventory risk)」:做市商永远站在流动性需求的对手盘上,承接了别人不想扛的方向,于是天然成了有偏的、单向的持仓者。

Avellaneda 与 Stoikov 在 2008 年给出了一套极其干净的框架,把这件事说透了:做市商在每一刻都应该按自己当前的库存,主动把报价「偏斜」——库存为正(多头)就整体压低报价、更愿意卖出;库存为负就整体抬高、更愿意买入。报价偏斜本身就是一种「库存—对冲」机制,不需要单独下对冲单,就能把持仓拉回零附近。

结论先放这:在 1000 条蒙特卡洛路径的模拟里(中间价零漂移、σ=0.5、一个交易时段 600 步),用 AS 库存偏斜报价的终端库存波动 |q| 标准差从对称报价的 6.17 降到 4.14,极端持仓上限 max|q| 从 36 压到 24,而平均 PnL 只从 68.4 微降到 68.6(几乎不丢收益)。也就是说,库存风险是能被「报价偏斜」系统性压下来的,而且代价极小。

单条典型路径:中间价、保留价与买卖报价(库存偏斜可见)

图上这条典型路径里,红色卖价(ask)和蓝色买价(bid)始终夹着中间价(蓝线),而橙色虚线——保留价 r(s,q,t)——明显在库存累积时落在中间价下方。报价不是对称地挂在中间价两边,而是随库存整体漂移,这正是 AS 框架的核心动作。

一、库存风险的本质:做市商是被迫的持仓者#

做市商挂双边报价,本质是承诺「无论你来买还是来卖,我都接」。结果就是:

  • 来一波买盘,做市商一直在,库存变负(空头);
  • 来一波卖盘,做市商一直在,库存变正(多头)。

中间价的每一次随机游走,都会让这个被动库存产生浮盈或浮亏。如果库存和中间价同方向漂移(比如做市商持有多头,中间价却开始跌),那就是库存风险暴露。教科书里常说「做市商赚价差」,但价差收益是确定的、库存盈亏是不确定的——不做库存控制,做市商就退化成一个带杠杆的方向投机者。

关键直觉:库存本身没有对错,错的是「库存 + 市场方向」的耦合。理想状态是库存始终贴近 0,这样无论中间价怎么跳,净值波动都最小。AS 框架解决的正是「如何设计报价,让库存被自然吸回 0」。

二、Avellaneda-Stoikov 模型:从效用最大化推出报价#

AS 的设定很克制:中间价 S_t 走算术布朗运动(零漂移,纯鞅)

dS_t = σ · dW_t
plaintext

做市商有一个指数效用函数 U(x) = −exp(−γx)γ风险厌恶系数。他在剩余时间 T−t 内,要选择最优的买卖报价,最大化「期末财富的期望效用」。AS 用控制论(HJB 方程)解出来两个漂亮结论。

2.1 保留价(reservation price)#

r(s, q, t) = s − q · γ · σ² · (T − t)
plaintext

「保留价」是做市商愿意成交的中间基准。它等于中间价减去一个库存惩罚项 q·γ·σ²·(T−t)

  • 库存 q>0(多头):惩罚项为正,保留价被压低 —— 做市商此刻不太想再买,反而愿意便宜点卖;
  • 库存 q<0(空头):惩罚项为负,保留价被抬高 —— 做市商愿意贵点买回来平空。

而且惩罚项里乘了 (T−t)越接近收盘,库存越「来不及」被市场自然消化,所以报价的偏斜越剧烈。这就是「临近收盘、报价越不对称」的来源。

2.2 最优买卖价差(full spread)#

δ(t) = γ·σ²·(T−t) + (2/γ)·ln(1 + γ/k)
plaintext

价差由两部分构成:

  • γ·σ²·(T−t)库存越久、波动越大,价差越宽(给承担风险收的保费);
  • (2/γ)·ln(1+γ/k)成交强度参数 k 越小(订单越「粘」、对手越不积极),价差越宽;γ 越大(越厌恶风险),这项越小,但第一项会放大。

2.3 最终报价#

ask = r + δ/2     bid = r − δ/2
plaintext

把保留价当作中心,再向两边各挂 δ/2。由于 r 已经随 q 偏斜,ask 与 bid 是一起随库存平移的——这就是下一节要讲的「库存偏斜报价」。

三、对称报价 vs 库存偏斜报价#

「对称报价」指固定以中间价为中心、向两边各挂 δ/2

ask_sym = S + δ/2      bid_sym = S − δ/2
plaintext

完全无视库存。结果是:库存无论正负,买卖两边被击中的概率始终对称,库存像随机游走一样自由累积,没人把它拉回 0。

「库存偏斜报价」用保留价 r = S − q·γ·σ²·(T−t) 当中心:

  • q>0:保留价下移 → ask 更贴近中间价、bid 离得更远 → ask 被击中的概率高于 bid → 做市商净卖出q 回落;
  • q<0:保留价上移 → bid 更贴近中间价 → 做市商净买入q 回升。

这是一个负反馈:库存偏离越大,报价偏斜越狠,把库存推回零的力量越强。这就是 AS 框架「用报价做库存对冲」的全部秘密——它不需要任何独立的对冲交易,光靠报价形状就完成了 inventory control。

做市商库存随时间演化:AS 偏斜报价把库存拉回零附近

图上这条典型路径的库存始终在 0 上下小幅波动,终端收在 −5。对比对称报价:同样一个时段,库存能随机漂到 ±30 以上而无人收敛。

四、成交的泊松强度:报价偏斜如何变成真实成交#

AS 假设对手方(流动性需求者)按泊松过程来单,且越远离中间价,被击中的强度越低

λ_a = A · exp(−k · (ask − S))      # 买盘击中 ask 的强度(做市商卖出)
λ_b = A · exp(−k · (S − bid))      # 卖盘击中 bid 的强度(做市商买入)
plaintext

q>0ask − S = δ/2 − q·γ·σ²(T−t) 变小(ask 更贴近中间价),于是 λ_a 变大、λ_b 变小 → 净卖出 → 库存回落。这里 A 是总体成交活跃度,k 控制「价格敏感度」(k 越大,对手越只在报价贴着中间价时才来)。这套泊松机制把第 2 节里「报价偏斜」的静态设计,落地成了动态的真实成交流,让库存真的被推回 0。

五、蒙特卡洛模拟:AS 到底省了多少库存风险#

我把上面的逻辑完整实现(代码见文末),跑 1000 条路径,每条 600 步一个交易时段,参数 S0=100, σ=0.5, T=1, A=140, k=1.5, γ=0.10。对比两种策略:AS 库存偏斜报价 vs 对称报价(同样价差日程,但 r≡S,无库存控制)。

结果(终端财富 = 现金 + 库存 × 中间价):

指标AS 库存偏斜对称报价
平均 PnL68.668.4
PnL 标准差6.827.62
终端库存 |q| 标准差4.146.17
最大 |q|2436
PnL 的 5% / 95%57.2 / 80.056.3 / 81.1

终端 PnL 分布:AS 库存偏斜 vs 对称报价(蒙特卡洛 1000 条路径)

终端库存分布:AS 显著收窄库存尾巴(蒙特卡洛)

读这张表要诚实:平均 PnL 两者几乎一样——因为中间价是零漂移鞅,无论你怎么报价,长期从价差里赚的钱总量差不多。AS 真正的价值不在「多赚」,而在「少扛风险」:

  1. 库存波动砍掉约 1/3(|q| 标准差 6.17 → 4.14),极端持仓从 36 压到 24——意味着遭遇大幅中间价跳空时,你不会因为持有过量库存而爆亏;
  2. PnL 波动也略降(7.62 → 6.82),因为库存—市场耦合被削弱了;
  3. 代价几乎为零:平均收益没丢。这是「免费午餐」吗?不是——它把「方向暴露」换成了「更窄的价差收益」,是用更稳的风险结构换来的,不是凭空多赚。

六、参数作用:γ / k / A 各自在干什么#

  • γ(风险厌恶):越大越怕库存。γ 上升 → 库存惩罚 q·γ·σ²(T−t) 更重 → 报价偏斜更狠、库存被吸回 0 更快;同时价差第一项 γσ²(T−t) 变宽,单笔收益更厚但成交更少。模拟里 γ 从 0.02 提到 0.80,终端库存 |q| 标准差从 5.46 降到 2.30,但平均 PnL 也从 69.0 滑到 64.4——γ 是「库存安全」与「价差收入」的旋钮,拧太大收益会漏。

风险厌恶 γ 的敏感性:库存波动与 PnL 波动随 γ 下降

  • k(价格敏感度 / 订单粘性):出现在 (2/γ)ln(1+γ/k) 里。k 越小,对手越不挑价格、越「粘」,做市商可以挂更宽的价差多收钱;k 越大,对手只在报价贴中间价时才来,价差被迫收窄。
  • A(成交活跃度):整体缩放两边的泊松强度。A 越大成交越密、库存调整越快、价差收益积累越快,但每一次库存冲击也越频繁。

七、真实陷阱:模型很美,实盘很骨感#

AS 是个干净的理想模型。把它搬进实盘,至少有六类陷阱会咬人:

  1. 离散 tick 与最小价格单位:AS 的报价是连续实数,但交易所报价是 tick 的整数倍。保留价偏斜 q·γ·σ²(T−t) 经常小于一个 tick,导致「想偏斜却偏不动」,库存控制被量化误差糊掉。实务里要按 tick 取整,并设最小偏斜步长。
  2. 逆向选择(adverse selection):AS 假设成交是「不知情流动性需求」的泊松流。但真实市场里,主动来打你 ask 的更可能是知情买家(要涨),打你 bid 的更可能是知情卖家(要跌)。这意味着成交本身携带信息,库存累积方向往往是「坏方向」,ASS 的对称泊松假设会系统性低估库存风险。
  3. 成交强度校准(A、k)λ=A·exp(−k·δ) 把一切押在 A、k 的准确校准上。盘口流动性随时段、事件、波动率 regime 剧烈变化,用历史值硬套会让实际成交强度与假设差一个数量级,报价偏斜的力度完全错位。
  4. 库存限额与强平:AS 是软约束(用效用惩罚库存),但实盘有硬性库存上限和风控强平线。当 max|q| 逼近限额,模型没考虑的「被迫市价平仓冲击成本」会直接吃掉价差利润。必须叠加硬限额 + 临近限额的加速偏斜。
  5. 延迟与异步:报价从计算到真正挂到盘口有时间差,市场已移动。AS 用「当前中间价 S」算保留价,但你的报价到达时 S 可能已经跳了,库存偏斜的基准失效,尤其在跳空/新闻时刻。
  6. 日内非平稳:模型里 σ、A 都是常数,真实市场开盘、午盘、收盘的波动与流动性天差地别,波动率 clustering 让 σ²(T−t) 这一项远非恒定。固定参数会在高波动时段严重低估风险、低波动时段过度偏斜。

这些陷阱的共同点是:AS 给你的是「结构正确」的报价形状,但每个落地环节都需要用真实盘口数据校准、用硬风控兜底。它是指南针,不是自动驾驶。

八、完整可运行 Python(numpy/pandas 风格)#

下面这段代码就是正文所有数字和配图的来源。它实现了 AS 做市器、对称报价基线、泊松成交、库存演化,并跑蒙特卡洛。直接复制可运行(只需 numpy + matplotlib)。

跑出来就是正文表格那组数字:AS 把库存波动从 6.17 压到 4.14、极端持仓从 36 压到 24,平均 PnL 几乎不变。库存风险不是靠「不接单」回避的,而是靠把报价主动偏斜、让市场替你做对冲。

九、一句话收尾#

Avellaneda-Stoikov 的美,在于它把「做市商怕库存」这件事,翻译成了一个可计算的报价公式:保留价随库存偏移、价差随剩余时间和风险厌恶加宽、成交按指数强度自然发生。它告诉你——好的做市不是对称地挂在中间价两边等被吃,而是带着库存偏见、用报价本身完成对冲。但别忘了第七节那六类陷阱:模型给你方向,落地要靠盘口数据校准和硬风控兜底。

做市库存风险:Avellaneda-Stoikov 框架下的库存-对冲博弈
https://blog.halo26812.eu.org/blog/market-making-inventory-avellaneda
Author halo
Published at 2026年7月15日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨