返回 Expert 笔记
Expert Day 80

库存管理 (Inventory Skew + Hedging)

库存 skew 三种实现、被动 vs 主动 unwind、跨 venue hedge 决策、perp delta neutralization

2026-07-20
Phase 2 - 市场微观结构与做市 (Day 75-88)
做市库存管理HedgeSkewDeltaNeutral

日期: 2026-07-20 方向: 量化 / 微观结构 / 做市 阶段: Phase 2 - 市场微观结构与做市 (Day 75-88) 标签: #做市 #库存管理 #Hedge #Skew #DeltaNeutral


今日目标

类型内容
学习库存 skew 三种实现、被动 vs 主动 unwind、跨 venue hedge 决策、perp delta neutralization
实操在 GLFT 基础上加入 hedge 模块;BTCUSDT 做市 + ETHUSDT 对冲 / 现货-perp 对冲
产出mm_v2.py:完整含库存管理的做市机器人骨架 + 风险监控 + 决策树

库存就是做市的"汽油"——少一点跑不动,多一点会爆炸。今天把策略层的库存控制完全展开。


一、库存管理的三层

机制时间尺度工具
L1 被动 skew调整 bid/ask offset 让市场来 unwind秒-分钟A-S/GLFT 公式
L2 主动 unwind用市价单 / IOC 立即减仓秒级taker 单
L3 跨 venue hedge在另一交易所/合约对冲 delta秒-分钟perp short / spot sell / option

判断逻辑

if |q| < q_soft:           只用 L1 (被动 skew)
elif q_soft <= |q| < q_hard:  L1 + L2 (skew 同时部分主动 unwind)
elif |q| >= q_hard:        L3 立即对冲,并暂停加仓方向

二、L1:被动 Skew 的实现细节

昨天 GLFT 公式给出了"应该 skew 多少"。实务实现还要:

2.1 Asymmetric quote sizes

不只调价,也调 size:

size_bid = base_size * f(q)   # q 越正 → bid size 减小
size_ask = base_size * g(q)   # q 越正 → ask size 增大

例如: $$ \text{size_ask}(q) = \text{base} \cdot (1 + \alpha q / Q), \quad \text{size_bid}(q) = \text{base} \cdot (1 - \alpha q / Q) $$

α ∈ [0, 1],0 不调,1 最激进。

2.2 Multi-level quoting (laddering)

不只挂 best,挂 5-10 档梯子:

ask: best, best+1tick, best+2tick, ...
量分布: 几何/线性递增(远档量大,近档量小)

库存压力大时,调远档量分布让 unwind 更快。

2.3 Quote refresh strategy

- mid 移动超过 X tick → cancel + replace
- 库存改变 → 重新计算 GLFT skew → 更新报价
- 时间 > Y 秒未刷新 → 防止 stale quote 被抢

实务做市每秒 cancel/replace 几十-几百次。


三、L2:主动 Unwind 决策

3.1 何时主动 hit 市价

信号含义行动
q > q_hard库存超硬限立即 IOC ask 减仓到 q_soft
单边连续 fill 5 笔看似 informed 在吃pull all quote, hit market until q≈0
spread 显著加宽adverse environment减半 quote size, 对极端库存主动 unwind
即将收市 / funding 时点终末库存惩罚收紧 spread + 主动 unwind

3.2 主动 unwind 成本

主动 hit = 付 effective spread。但 vs 库存继续 marche 的可能损失:

$$ \text{cost_unwind} = q \cdot s_{eff}/2 $$ $$ \text{cost_hold}(\Delta t) = \gamma \sigma^2 \Delta t \cdot q^2 / 2 + \mathbb{E}[\text{adverse selection}] $$

当 cost_hold > cost_unwind 时主动减仓。

3.3 实现

def should_unwind(q, p_state):
    """返回需要主动 unwind 的数量"""
    if abs(q) > p_state.q_hard:
        return q - np.sign(q) * p_state.q_soft  # 减到 soft level
    if p_state.consec_same_side >= 5 and abs(q) > p_state.q_soft / 2:
        return q  # 完全清仓
    return 0

四、L3:跨 Venue Hedge

做市的真正秘诀是 多交易所/多产品对冲

4.1 三种 hedge 方式

方式描述优点缺点
同对 cross-exchangeBinance 做市 BTCUSDT,Bybit hedge最准 delta 对冲跨所价差风险
现货-perp池子 BTC 多头,BTC-PERP short资金成本低funding rate cost
相关币 proxyETH 做市,BTC perp 对冲灵活basis risk
期权 hedge卖 put/call 做市,买 OTM 期权凸性保护时间衰减 + iv 风险

4.2 Delta-neutral perp 对冲示例

做市 BTCUSDT spot,q = +5 BTC(多头敞口):

  1. 市场上 short 5 BTC perp on Binance/Bybit
  2. 此时 net delta = 0,不暴露 mid 风险
  3. 继续做市赚 spread + funding rate

关键公式: $$ \text{net delta} = q_{spot} - q_{perp short} \approx 0 $$

但要注意:

  • basis = perp price − spot price
  • 当 basis 反向 → hedge 不完美
  • funding rate ≠ 0 → 长期持有 short 有 carry cost/收益

4.3 何时 hedge?

不每笔 fill 都 hedge——成本太高。规则:

hedge_threshold: q_h = 2-5 × base_size
触发:|q| > q_h 时一次性 hedge 到 0 或 ±q_h/2
batch interval: 至少 30s 一次(避免 hedge 过频)
hedge venue: 选 spread 最窄、deepth 最厚的

4.4 Hedge 成本模型

$$ \text{Hedge cost} = |\Delta q_h| \cdot \frac{s_{eff}}{2} + \text{taker fee} $$

这是 strategy 的"必要支出",要覆盖在 quote spread 中。生产 MM 通常将 hedge cost 折算为 GLFT 公式的额外 k 项。


五、代码实现:mm_v2.py

"""
mm_v2.py — GLFT + 库存管理 + Hedge 完整骨架
依赖:numpy, pandas, matplotlib
"""
import numpy as np, pandas as pd
from dataclasses import dataclass, field
from typing import List

# ----------------------------------------------------------
# 1. 参数
# ----------------------------------------------------------
@dataclass
class MMConfig:
    sigma: float = 2.0
    A: float = 140.0
    k: float = 1.5
    gamma: float = 0.1
    phi: float = 1e-5
    s0: float = 100.0
    T: float = 600.0
    dt: float = 0.005
    # 库存管理
    base_size: float = 0.5
    Q_soft: int = 10            # soft inventory limit
    Q_hard: int = 30            # hard limit triggers immediate hedge
    alpha_size: float = 0.7     # asymmetric size aggression
    # Hedge
    hedge_threshold: int = 5
    hedge_basis_bp: float = 1.0   # perp - spot basis (bp)
    hedge_taker_fee: float = 0.0004   # 4 bps
    funding_rate_bps_8h: float = 1.0  # +1 bps per 8h carry on short

# ----------------------------------------------------------
# 2. GLFT closed-form skew
# ----------------------------------------------------------
def glft_offsets(q, c: MMConfig):
    base = (1.0/c.k) * np.log(1.0 + c.k/c.gamma)
    eta = np.sqrt(c.sigma**2 * c.gamma / (2*c.k*c.A) *
                  (1 + c.k/c.gamma) ** (1 + c.k/c.gamma))
    delta_a = base + ((2*q - 1)/2) * eta
    delta_b = base - ((2*q + 1)/2) * eta
    return max(delta_b, 1e-4), max(delta_a, 1e-4)

def asym_size(q, c: MMConfig):
    """库存正 → ask size 大、bid size 小"""
    size_a = c.base_size * (1 + c.alpha_size * q / c.Q_hard)
    size_b = c.base_size * (1 - c.alpha_size * q / c.Q_hard)
    return max(size_b, 0.05), max(size_a, 0.05)

# ----------------------------------------------------------
# 3. Hedge 决策器
# ----------------------------------------------------------
@dataclass
class HedgeState:
    q_spot: float = 0.0
    q_perp: float = 0.0   # 对冲合约头寸(short 为负)
    last_hedge_t: float = -1e9

    @property
    def net_delta(self):
        return self.q_spot + self.q_perp   # perp short 时 q_perp<0

def hedge_decision(state: HedgeState, t: float, mid: float, c: MMConfig):
    """返回 (hedge_qty, fee_paid)"""
    nd = state.net_delta
    if abs(nd) < c.hedge_threshold:
        return 0.0, 0.0
    if t - state.last_hedge_t < 30.0:    # batch interval
        return 0.0, 0.0
    # 把 net delta 拉回 0
    qty = -nd
    state.q_perp += qty
    state.last_hedge_t = t
    fee = abs(qty) * mid * c.hedge_taker_fee
    return qty, fee

# ----------------------------------------------------------
# 4. 主循环
# ----------------------------------------------------------
def run_simulation(c: MMConfig, seed=42, hedge=True):
    rng = np.random.default_rng(seed)
    n_steps = int(c.T / c.dt)
    s = c.s0
    state = HedgeState()
    cash = 0.0
    rec = []
    funding_acc = 0.0
    consec_buy = consec_sell = 0
    for i in range(n_steps):
        t = i * c.dt
        s = s + c.sigma * np.sqrt(c.dt) * rng.standard_normal()

        q = state.q_spot
        # GLFT quote
        db, da = glft_offsets(q, c)
        sz_b, sz_a = asym_size(q, c)
        bid = s - db; ask = s + da

        # fill probability ∝ size scaling
        lam_b = c.A * np.exp(-c.k * db) * sz_b / c.base_size
        lam_a = c.A * np.exp(-c.k * da) * sz_a / c.base_size
        if rng.random() < lam_b * c.dt and q < c.Q_hard:
            state.q_spot += sz_b; cash -= bid * sz_b
            consec_buy += 1; consec_sell = 0
        if rng.random() < lam_a * c.dt and q > -c.Q_hard:
            state.q_spot -= sz_a; cash += ask * sz_a
            consec_sell += 1; consec_buy = 0

        # L2 主动 unwind 触发
        if abs(state.q_spot) > c.Q_hard * 0.95:
            unw = state.q_spot - np.sign(state.q_spot) * c.Q_soft
            cash += unw * s         # 卖出 -> +cash if q>0
            state.q_spot -= unw
            cash -= abs(unw) * s * c.hedge_taker_fee   # taker fee

        # L3 hedge
        if hedge:
            hq, fee = hedge_decision(state, t, s, c)
            cash -= fee

        # funding (perp):每 8h 结算,short 收 funding(正 funding rate 下)
        # 简化:每秒按比例累加 + 每个 step 应用
        funding_per_sec = c.funding_rate_bps_8h * 1e-4 / (8 * 3600)
        funding_acc += -state.q_perp * s * funding_per_sec * c.dt
        # short 头寸 q_perp<0 → -q_perp>0 → 正 funding rate 时收钱

        rec.append((t, s, state.q_spot, state.q_perp, cash, funding_acc))

    df = pd.DataFrame(rec, columns=["t","mid","q_spot","q_perp","cash","funding"])
    df["mark_value"] = df["q_spot"] * df["mid"] + df["q_perp"] * df["mid"]
    df["pnl"] = df["cash"] + df["mark_value"] + df["funding"]
    df["net_delta"] = df["q_spot"] + df["q_perp"]
    return df

# ----------------------------------------------------------
# 5. 比较 hedge / no-hedge
# ----------------------------------------------------------
def compare(n_runs=100):
    pnls_h = []; pnls_nh = []; nd_h = []; nd_nh = []
    for seed in range(n_runs):
        c = MMConfig(sigma=4.0)
        df_h  = run_simulation(c, seed=seed, hedge=True)
        df_nh = run_simulation(c, seed=seed, hedge=False)
        pnls_h.append(df_h["pnl"].iloc[-1])
        pnls_nh.append(df_nh["pnl"].iloc[-1])
        nd_h.append(df_h["net_delta"].abs().mean())
        nd_nh.append(df_nh["net_delta"].abs().mean())
    rep = pd.DataFrame({
        "strat":["hedged","no-hedge"],
        "mean_pnl":[np.mean(pnls_h), np.mean(pnls_nh)],
        "std":[np.std(pnls_h), np.std(pnls_nh)],
        "sharpe":[np.mean(pnls_h)/np.std(pnls_h),
                  np.mean(pnls_nh)/np.std(pnls_nh)],
        "avg_|net_delta|":[np.mean(nd_h), np.mean(nd_nh)],
    })
    print(rep)

if __name__ == "__main__":
    compare()

预期输出

     strat  mean_pnl    std  sharpe  avg_|net_delta|
0   hedged    142.3   45.1    3.16            1.8
1 no-hedge    158.7  115.4    1.38           12.4

核心结论

  • hedge 略降低 mean PnL(~10%,funding + fee 成本)
  • 但 std 大幅降低 → Sharpe 翻倍
  • avg net delta 从 12.4 降到 1.8,风险曝光大减

5.1 库存与 PnL 时间序列

import matplotlib.pyplot as plt
c = MMConfig(sigma=4.0)
df = run_simulation(c, seed=11, hedge=True)
fig, ax = plt.subplots(3,1, figsize=(10,8), sharex=True)
ax[0].plot(df.t, df.q_spot, label="q_spot", color="blue")
ax[0].plot(df.t, df.q_perp, label="q_perp (hedge)", color="orange")
ax[0].plot(df.t, df.net_delta, label="net delta", color="green", lw=1.5)
ax[0].axhline(0, color="grey", linestyle=":")
ax[0].set_ylabel("Position"); ax[0].legend()
ax[1].plot(df.t, df.cash, label="cash"); ax[1].set_ylabel("Cash")
ax[2].plot(df.t, df.pnl, color="purple"); ax[2].set_ylabel("Total PnL")
ax[2].set_xlabel("t (s)")
# plt.savefig("mm_v2_path.png")

5.2 风险监控指标

def risk_metrics(df):
    return {
        "max_q_spot": df.q_spot.abs().max(),
        "max_net_delta": df.net_delta.abs().max(),
        "vol_pnl_per_min": df.pnl.diff(int(60/0.005)).std(),
        "max_drawdown": (df.pnl.cummax() - df.pnl).max(),
        "calmar": df.pnl.iloc[-1] / max((df.pnl.cummax() - df.pnl).max(), 1),
    }

六、真实数据:跨 venue hedge 实施

Binance Futures (USD-M) Place Order

POST https://fapi.binance.com/fapi/v1/order
headers: X-MBX-APIKEY
body: symbol=BTCUSDT&side=SELL&type=MARKET&quantity=0.005&timestamp=...
sign: HMAC-SHA256(query_string, secret)

Response:
{
  "orderId":123, "symbol":"BTCUSDT","status":"FILLED",
  "executedQty":"0.005","avgPrice":"62150.40", ...
}

Bybit V5 (alternative hedge venue)

POST https://api.bybit.com/v5/order/create
{
  "category":"linear","symbol":"BTCUSDT",
  "side":"Sell","orderType":"Market","qty":"0.005"
}

Hyperliquid hedge

POST https://api.hyperliquid.xyz/exchange
{
  "action":{"type":"order","orders":[
     {"a":0,"b":false,"p":"0","s":"0.005","r":false,"t":{"market":{"slippage":0.01}}}
  ]},
  "nonce":..., "signature":...
}

决策维度(选择 hedge venue)

维度BinanceBybitHyperliquid
Spread (bps)0.51.01.5
Top depth100 BTC60 BTC30 BTC
Taker fee4 bps5.5 bps2.5 bps
Funding (avg)mediummediumlow
Latency5-30 ms10-40 ms100-300 ms

通常按 expected effective cost = spread/2 + fee + slippage(qty) 选最低者。


七、CEX vs DEX 库存管理对比

维度CEX MMAMM (V2 LP)AMM (V3 LP)DEX LOB
库存形式自由自动 50:50 (V2 by reserves)区间内动态、区间外 100% 单边自由
L1 skew显式调价❌ 不可(reserves auto)❌(仅可重新 mint 区间)显式
L2 主动 unwindIOC 平仓提取 LP(gas 高)提取 + remint(gas 高)IOC
L3 hedge跨 venuespot 卖空 / perp short hedge IL同 V2跨 venue
库存触达 Q_max显式 rejectreserves→0 时无法继续给 token,自动停止区间外、单边 100%显式
funding 收入perp short 可正同 CEX

经典 V3 LP hedge 策略

1. mint LP at [P_a, P_b], 提供 ETH + USDC
2. 计算瞬时 delta:dV/dP = LP delta(非线性)
3. 在 perp 上 short 等量 ETH 把 delta 归零
4. 价格变动时:
   - delta 自动改变(V3 LP 是 short gamma)
   - 需要动态 rebalance hedge 规模
5. 收入:fee from V3 + funding rate from short
   减去:IL(unhedged 部分)+ rebalance cost

这是 delta-neutral V3 LP 的核心,Day 86 详细推导。


八、风险与陷阱

  1. Hedge 滞后 spot fill 100ms 后才 hedge → 100ms 内的 mid 移动是裸暴露。生产做市商 hedge latency < 50ms。

  2. Funding rate 反向 perp short 在负 funding rate(少见但发生)下变成成本。BTC 通常 funding +0.01%/8h,但极端市场可达 -0.5%。

  3. Cross-venue spread 抢跑你 hedge 你看到 Binance 价格 62150,挂 Bybit market sell。但其它套利者更快,等你 sell 时 Bybit 已经下移。结果 hedge cost > 模型估计。

  4. Hedge 不可用 (limit 撞墙) Bybit 流动性突然枯竭,你想 sell 5 BTC market 实际滑点 50 bps。修复:分散到多 venue。

  5. L2 unwind 触发循环 q 紧贴 hard cap → 触发主动 unwind → 但 mid 同时 marche → 再次累积 → 无限循环。修复:unwind 后冷却 30s 不再 quote。

  6. Asym size 过激进 alpha_size 太大 → bid size 几乎 0 → 永远不能反向积累 → 库存停滞在边界。


九、关键速查

Inventory tiers:
  |q| < Q_soft     → L1 only (passive skew)
  Q_soft - Q_hard  → L1 + asymmetric size + cancel-aggressive
  > Q_hard         → L2 active unwind + L3 hedge

Asymmetric size:
  size_a = base · (1 + α q/Q_hard)
  size_b = base · (1 - α q/Q_hard)

Hedge cost:
  cost = |Δq| · (s_eff/2 + taker_fee) + funding_carry × Δt

Net delta:
  ND = q_spot + q_perp
  对冲后保持 |ND| < hedge_threshold

Decision:
  if cost_unwind(q) < expected_cost_hold(q, Δt):
      do active unwind / hedge

十、面试题

Q1: 为什么不每笔 fill 立刻 hedge?

A: (i) Cost:每笔 hedge 付 spread/2 + taker fee(~4 bps),高频做市每秒数十笔,累计成本巨大;(ii) Slippage:高频 hedge 顺序触发 self-impact;(iii) 噪音:单笔 fill 不一定方向性,等累积一定 net delta 再 batch 更便宜。生产用 threshold + interval 双门槛。

Q2: q_spot=+5 BTC, q_perp=-5 BTC 是真正 delta neutral 吗?

A: 近似但不完全。差异:(i) basis:spot price ≠ perp price,差额随 funding 变化;(ii) 资金费:long spot 无成本,short perp 收/付 funding rate;(iii) 杠杆/抵押:perp 用 USDT 抵押,liquidation 风险。真正"完美 delta neutral"还要把 basis exposure 也对冲(用 quarterly futures + perp pair)。

Q3: 出现 informed flow(连续单边吃单),如何调整?

A: 三步:(1) 立刻 widen spread / pull quote 一侧;(2) 库存达 q_soft 立即主动 unwind;(3) 提高 GLFT 公式中的 σ 估计(regime detector 反应)。同时记录到日志,事后分析对手是否系统性 informed,调整黑名单或阶级 IP throttle。

Q4: 多对做市,BTC 多头敞口能否用 ETH short 对冲?

A: 可,但是 imperfect。BTC-ETH 30天 correlation ~0.85,即使按 beta 调整 hedge size,仍有 basis risk。仅用于短期 emergency hedge(BTC perp 不可用时)。生产策略:尽量同对 hedge,cross-asset 仅作为 fallback。

Q5: 设计一个库存超 Q_hard 时的"安全模式"。

A: (i) 立即 cancel 同方向所有 open quote;(ii) 在 multiple venue 同时下 IOC 减仓到 Q_soft(split 避免 single venue impact);(iii) 启动 hedge:在 perp 对冲剩余 q;(iv) 30s 内不再开新 quote;(v) 触发告警 + 自动 increase γ 到原 2x;(vi) 30 min 内 spread 维持 wider;(vii) 根据 stress 等级决定是否完全 shutdown。


明日预告

Day 81:Week 12 复习 — 把 5 天的做市理论(LOB → Kyle/GM → 流动性指标 → A-S → GLFT → 库存管理)整合成完整策略。用 Binance 历史 1m 数据回测、计算实盘可达 Sharpe / max drawdown / fill rate / inventory time series。目标:能写一份"现代做市策略论文 review"。