报价斜率流动性:用限价簿弹性度量瞬时深度
价差只告诉你第一股的成本,深度只告诉你第一档的数量——真正决定一笔像样规模订单成本的,是限价簿的形状。报价斜率把这个形状压缩成一个数:累计可成交量对价格偏移的回归斜率 S,越大盘口越有弹性。本文用模拟限价簿讲清定义与计算(含穿过原点的最小二乘),在 120 只股票的横截面上验证「固定订单的即时冲击 ∝ 1/S」的双对数线性关系,并演示斜率的日内 U 形与压力坍缩:负面消息瞬间撤单能让斜率蒸发 55%——流动性是被撤单速度定义的,不是被价差定义的。与 Kyle λ 的关系一句话讲清:S 是 λ 的簿本侧倒数近似。诚实边界:可见深度被冰山单低估、斜率对档位截断敏感、快照频率不够时压力坍缩根本看不见(中阶)。
问题:价差一样、深度一样,成本可以差三倍#
两只股票,买卖价差都是 1 分钱,买一卖一挂单量都是 2000 股。它们的流动性一样好吗?
对一笔 500 股的小单来说,一样。但你要买 2 万股,答案取决于卖二、卖三、卖五、卖十挂了多少:
- 股票 A 的挂单量沿价格档位缓慢衰减,卖十档还有几千股——2 万股吃进去,价格只推高 3 分钱;
- 股票 B 的挂单集中在前两档,往后骤减——同样 2 万股要扫到十几档开外,价格推高 1 毛。
价差度量的是第一股的成本,最优档深度度量的是第一档的数量,而一笔像样规模的订单真正面对的是整个簿本的形状。把这个形状压缩成一个数,就是报价斜率(quote slope)——这个思路可以追溯到 Engle-Lange 的市场深度研究和 Kyle (1985) 的 λ:市场的流动性本质上是一条供给曲线的斜率。

左图是深盘口:累计深度曲线平缓上升,价格每偏移一分钱能多吃到大量挂单。右图是浅盘口:曲线贴着地板走,想多买就得大幅让价。两图的价差完全相同——这就是为什么只看价差会把 B 误判成和 A 一样流动。
定义:累计深度对价格偏移的回归斜率#
操作化定义非常直接。取一个盘口快照,对卖侧(买侧同理):
- 计算每一档距中间价的偏移 ;
- 计算到第 档为止的累计挂单量 ;
- 对 做穿过原点的最小二乘:
的单位是”股/元”:价格每让一元,市场愿意多给你多少股。S 越大,簿本越有弹性,同样规模的订单造成的位移越小。
import numpy as np
def quote_slope(ask_px, ask_qty, mid):
"""报价斜率:累计深度对价格偏移的过原点回归斜率(股/元)"""
dp = np.asarray(ask_px) - mid # 各档距中间价的偏移
cq = np.cumsum(ask_qty) # 累计可成交量
return np.sum(dp * cq) / np.sum(dp ** 2)
# ---- 两个盘口:价差相同,形状不同 ----
mid, tick = 10.00, 0.01
levels = np.arange(1, 11)
ask_px = mid + tick * levels
rng = np.random.default_rng(7)
deep_ask = 7800 * np.exp(-0.07 * levels) + rng.normal(0, 200, 10) # 深盘口
shal_ask = 1400 * np.exp(-0.22 * levels) + rng.normal(0, 60, 10) # 浅盘口
S_deep = quote_slope(ask_px, deep_ask, mid)
S_shal = quote_slope(ask_px, shal_ask, mid)
print(f"深盘口 S = {S_deep:,.0f} 股/元, 浅盘口 S = {S_shal:,.0f} 股/元")
# 深盘口约为浅盘口的 6-8 倍python
为什么用回归而不是直接拿”总深度除以总价格范围”?因为回归对近端档位加权更合理——过原点最小二乘天然给远离中间价的点更大权重是个特性而非缺陷:远端档位才是大单真正要触碰的区域,近端一两档的数字游戏(后面会讲)对 S 的影响被稀释。
与 Kyle λ 的关系:一枚硬币的两面#
熟悉 Kyle 模型的读者会立刻认出来:λ 是”每单位订单流推动多少价格”(元/股),S 是”每单位价格让步换来多少量”(股/元)。S 就是 λ 的簿本侧倒数近似:
区别在测量来源:λ 从成交后的价格回归里估计(事后的、已实现的冲击),S 从盘口快照里直接读出(事前的、承诺中的流动性)。两者的差值本身有信息——如果实际成交的 λ 系统性大于 1/S,说明可见挂单在你到达之前撤掉了,簿本承诺的流动性是幻觉。这个”承诺 vs 兑现”的差距,正是高频做市环境里 fleeting liquidity(闪现流动性)的度量思路。
横截面验证:冲击成本 ∝ 1/S#
如果 S 真是流动性的标尺,那么固定规模订单的即时冲击应该和 S 成反比。模拟 120 只斜率横跨两个数量级的股票,每只吃一笔 2 万股市价单:
n_stk = 120
true_slope = 10 ** rng.uniform(4.2, 6.3, n_stk) # 股/元,跨两个数量级
order = 20_000 # 固定 2 万股
# 即时冲击(bp):走完簿本所需价格位移 / 中间价,叠加 25% 实现噪声
impact_bp = order / true_slope / mid * 1e4 * (1 + rng.normal(0, 0.25, n_stk))python
双对数坐标下 120 个点整齐地贴着”冲击 ∝ 1/S”的理论线。这意味着 S 可以直接进成本预估模型:交易前用当前盘口算出 S,除一下就是这笔单子的即时冲击预算——不需要历史回归,不需要等成交回报,一个快照就够。这是 S 相对 Amihud、Kyle λ 这类”事后估计量”的最大实用优势:它是实时的。
动态:日内 U 形与压力坍缩#
斜率不是股票的常数,它随时间剧烈变化——而且变化本身就是信号。
n_min = 240
t = np.arange(n_min)
# 价差的日内 U 形 → 斜率的倒 U 形(开收盘弹性最差)
inv_spread = 1.0 + 0.5 * np.exp(-t / 30) + 0.4 * np.exp(-(n_min - 1 - t) / 25)
slope_norm = (1 / inv_spread) / (1 / inv_spread).max()
# 第 150 分钟负面消息:流动性提供者瞬间撤单,斜率坍缩 55% 后缓慢恢复
stress = slope_norm.copy()
shock = t >= 150
stress[shock] *= 1 - 0.55 * np.exp(-(t[shock] - 150) / 20)python
正常日的斜率呈倒 U 形:开盘后信息不确定性高、做市商挂单谨慎,斜率低;午盘最厚;尾盘再度变薄。这和价差的 U 形是同一枚硬币——执行算法把子单堆在午盘的理由,用斜率语言重新讲了一遍。
更重要的是红线:负面消息落地的瞬间,挂单是被撤掉的,不是被吃掉的。斜率在一两分钟内蒸发过半,然后随着做市商重新评估、试探性挂回而缓慢恢复。这揭示了流动性最阴暗的性质:它在你最需要的时候消失。价差在消息瞬间可能只扩大一点(最优档还挂着象征性的 100 股),但斜率已经坍缩——用价差做流动性风控会在最关键的时刻给出假安全信号,用斜率不会。
对风控的直接含义:把 S 的滚动 z-score 接进执行系统,斜率突然跌破近期分布的下沿时暂停子单发送——这是比价差更早、比成交量更干净的流动性枯竭预警。
已知边界#
三个必须说清的坑:
- 可见深度 ≠ 真实深度。冰山单只显示一小片,暗池流动性完全不在簿本上——S 系统性低估真实弹性,且低估程度在股票之间不均匀(机构重仓股冰山单更多)。反方向的污染同样存在:幌骗(spoofing)挂单会让 S 虚高,那些挂单在你的市价单到达前就撤了。S 度量的是”簿本声称的弹性”,与真实弹性之间隔着一层博弈。
- 对档位截断敏感。用 5 档算和用 10 档算,S 可以差几十个百分点,因为远端累计深度的贡献在回归里权重不小。横截面比较必须固定同一档位口径;只有 Level-1 数据时退化成”最优档深度/半价差”的粗糙版本,噪声大得多。
- 快照频率决定你能看到什么。压力坍缩发生在秒级。用 3 秒快照(A 股 Level-2 的常见频率)能抓到;用分钟快照,坍缩-恢复可能整个发生在两个观测点之间,你看到的斜率序列平滑得虚假。研究结论对快照频率的依赖,必须在使用前测试。
小结#
报价斜率把限价簿的形状压缩成一个实时可算的数:累计可成交量对价格偏移的回归斜率,单位是股/元,本质是 Kyle λ 的簿本侧倒数。它相对价差的增量信息在于弹性——价差相同的两个盘口,S 可以差几倍,而 S 才决定像样规模订单的真实成本。横截面上固定订单的冲击 ∝ 1/S 的关系干净到可以直接进成本预估模型;时间序列上 S 的坍缩比价差更早暴露流动性枯竭。它的原罪是只能看见簿本愿意展示的东西:冰山单让它低估、幌骗让它虚高。把 S 当作”承诺的流动性”,把成交后实测的冲击当作”兑现的流动性”,两者的裂缝里住着高频市场的全部秘密。