2010 年 5 月 6 日,美股在几分钟内崩掉近 1000 点又部分拉回——“闪崩”。事后复盘最诡异的不是跌得多快,而是流动性在自己眼皮底下蒸发了:做市商发现无论怎么挂单都被”吃掉”,于是干脆撤单,市场瞬间没了对手方。这种风险在传统风控里完全看不见,因为它不在价格里,而在订单流的性质里。
结论先放这:VPIN(Volume-Synchronized Probability of Informed Trading,Easley–López de Prado–O’Hara 2011)把 Easley 经典的 PIN 模型从”逐笔极大似然”改造成”成交量柱上的买卖失衡”,可以近乎实时地度量订单流毒性——也就是知情交易者正在单边扫货、做市商被逆向选择的概率。在我们的模拟里,毒性事件区间 VPIN 均值 0.50,而正常区只有 0.12;用”VPIN 升破 0.40 就空仓”的朴素规则,样本内回撤从 −21.8% 砍到 −11.3%,夏普从 0.05 拉到 0.45。

一、从 PIN 到 VPIN:为什么需要”成交量同步”#
PIN(Probability of Informed Trading)衡量一个很朴素的事:一笔交易有多大概率来自知情者。Easley 的原始模型要先把每笔成交分成”买”或”卖”,再用极大似然估计四个参数(无信息日概率 α、知情日概率 δ、知情者到达率 μ、噪声到达率 ε)。问题有三个:
- 必须逐笔分类,而真实市场的买卖标识常常缺失或不可靠;
- 极大似然很慢,无法在盘中实时更新;
- 参数对经济周期敏感,估计窗口一长就过时。
VPIN 的聪明之处在于绕开了参数估计:它不猜”这是不是知情单”,而是直接看成交量结构——如果买盘和卖盘的成交量在一段时间里严重不对称,那大概率有人在”有方向地”交易。而为了不依赖时间(闪崩时成交可能几秒蜂拥而至),它用**成交量柱(volume bar)**而不是时间柱来切分数据:每根柱固定包含约 V 的成交量,于是每根柱天然可比。
二、成交量柱与买卖分类#
成交量柱:顺序累加逐笔成交量,当累计达到目标量 V_bar 就收一根柱。这和 K 线按时间切完全不同——活跃时段柱子密、冷清时段柱子疏,但每根柱的”信息量”(成交量)一致。
买卖方向分类有两条主流路:
- Tick Rule:比较本笔成交价与上笔成交价,涨记为买、跌记为卖、平则沿用上笔方向。简单、无需盘口数据。
- Lee-Ready:先判断这笔成交相对于买卖盘中间价是”主动吃单”还是”被动挂单”,再定方向。更准,但需要 Quote 数据。
我们的实现用 Tick Rule 思路,在成交量柱层面直接得到每根柱的买/卖成交量 。
import numpy as np
def build_volume_bars(trade_price, trade_vol, target_vol):
"""把逐笔成交聚合成成交量柱,返回每根柱的 (收盘价, 总成交量, 买方量, 卖方量)"""
bars, cum_vol = [], 0.0
bprice, bvol, bbuy = 0.0, 0.0, 0.0
last_price = trade_price[0]
for p, v in zip(trade_price, trade_vol):
# Tick Rule:涨=买,跌=卖,平=沿用上次方向
if p > last_price:
sign = 1
elif p < last_price:
sign = -1
else:
sign = 0
buy = v if sign >= 0 else 0.0
sell = 0.0 if sign >= 0 else v
bprice, bvol, bbuy = p, bvol + v, bbuy + buy
cum_vol += v
last_price = p
if cum_vol >= target_vol:
bars.append((bprice, bvol, bbuy, bvol - bbuy))
bprice, bvol, bbuy, cum_vol = p, 0.0, 0.0, 0.0
return barspython三、VPIN 公式:买卖成交量的不对称#
对每根成交量柱,定义订单流不平衡的绝对量:
- 分子 是这根柱里”无法被对手方抵消”的单向成交量——正是逆向选择的载体;
- 除以 做了归一,所以 VPIN 落在 0(买卖完全均衡)到 1(一根柱全是单边)之间;
- 对最近 根柱(实证常用 )取平均,既平滑噪声又保留”订单流在变毒”的趋势。
关键点:VPIN 高 ≠ 价格一定在跌。它度量的是”有人在单向扫货”这件事本身。但单向扫货通常意味着知情者掌握了你不知道的信息,所以高 VPIN 往往领先于剧烈的单边行情和流动性收缩。
def compute_vpin(buy_vol, sell_vol, n=50):
"""VPIN:近 n 根成交量柱的 |买卖量差|/总量 的滑动平均(无前视)"""
total = buy_vol + sell_vol
imb = np.abs(buy_vol - sell_vol) / np.where(total > 0, total, 1.0)
vpin = np.full(len(imb), np.nan)
for i in range(n - 1, len(imb)):
vpin[i] = imb[i - n + 1:i + 1].mean()
vpin[:n - 1] = imb[:n - 1].mean()
return vpinpython四、实证:毒性事件里 VPIN 会尖叫#
我们模拟一段含 3 段”毒性事件”的订单流(每段约 120 根成交量柱):正常时段买卖大致均衡(买方占比 ~50%),毒性时段知情者持续单向砸盘(买方占比 ~20%),并伴随放量。结果非常干净:
- 正常区 VPIN 均值 0.12,毒性区 0.50;
- 阈值设在 0.40 时,能抓到 76.1% 的毒性柱;
- VPIN 的飙升明显领先于价格的剧烈下跌,这正是它作为”预警器”的价值。

更关键的是领先性检验:把 和下一根柱的收益画在一起,二者是单调负相关的——VPIN 越高,接下来那根柱越可能亏钱。这说明 VPIN 不是事后的巧合,而是带着预测力的。

五、防护回测:毒性升破阈值就空仓#
最直接的用法是当”风控开关”:用上一根柱的 VPIN 决定当前柱的仓位(避免前视),一旦 就空仓(持币),否则满仓多头。
def vpin_filter_backtest(bar_ret, vpin, threshold=0.40):
"""VPIN 过滤:上一根柱 VPIN>阈值则本柱空仓(无前视)"""
pos = np.where(np.roll(vpin > threshold, 1), 0.0, 1.0)
pos[0] = 1.0
nav = np.cumprod(np.exp(bar_ret * pos))
return nav, pos
def perf(nav, rets):
r = np.diff(nav) / nav[:-1]
cagr = nav[-1] ** (252.0 / len(nav)) - 1
sharpe = r.mean() / r.std() * np.sqrt(252)
mdd = (nav / np.maximum.accumulate(nav) - 1).min()
return cagr, sharpe, mddpython回测结果(样本内,仅作方法演示):
| 方案 | CAGR | 夏普 | 最大回撤 | 空仓占比 |
|---|---|---|---|---|
| 裸多头 | 0.1% | 0.05 | −21.8% | 0% |
| VPIN 过滤 | 2.0% | 0.45 | −11.3% | 8.3% |

裸多头在毒性砸盘里吃了 −21.8% 的回撤;VPIN 过滤只在 8.3% 的时间空仓(绝大部分是毒性区间),就把回撤砍到 −11.3%、夏普拉了 9 倍。注意:它牺牲了一点上行(空仓时也错过反弹),但换回的是尾部风险的实质性下降——这对杠杆账户和做市库存管理是决定性的。
六、真实陷阱(不平坑你会反被 VPIN 坑)#
1. 分类误差会制造假信号。 Tick Rule 在震荡市会频繁误判方向,把噪声当成”毒性”。更稳的是 Lee-Ready,但需要盘口数据;退而求其次,可对 Tick Rule 信号做平滑或用更大 n。
2. 正常趋势市也会高 OFI。 一根强劲的利多新闻驱动的纯买方趋势,OFI 同样很高,但这是”信息已公开”的良性单边,不是毒性。单纯 VPIN 分不清”知情单向”和”一致预期单向”——必须叠加别的信息(如成交量是否异常放大、是否伴随价差走阔)。
3. 阈值必须随波动率/流动性调整。 固定 0.40 在平静市可能误报、在危机市又太松。实务上用滚动分位数(如 95% 分位)动态设阈,或按波动率缩放。
4. VPIN 本身有 n 根柱的滞后。 它是对过去 n 根柱的平均,毒性刚启动时反应慢半拍;n 太小则噪声大。50 是经验值,需按你的成交量柱粒度回测。
5. 它度量”量”不度量”质”。 VPIN 高只说明成交单向,不说明信息真的有内容。配合价差(spread)、深度(depth)、报价频率(quote stuffing 会污染它)一起看,才不会被假毒性骗。
6. 流动性真空可能自我实现。 一旦很多人用 VPIN 触发撤单/空仓,流动性会真的消失,反而加剧闪崩——这是微观结构指标共有的”反射性”风险。
小结#
VPIN 把”订单流毒性”这个原本只存在于做市商直觉里的东西,变成了一个可计算、可监控、可当风控开关的指标:用成交量柱 + 买卖成交量不平衡,实时量化”做市商正在被逆向选择”的程度。它最擅长在闪崩、流动性枯竭之前发出预警,作为组合层的尾部保护非常便宜(只空仓 8% 的时间就砍掉一半回撤)。但它不是水晶球:分类误差、趋势市误报、阈值僵化、滞后与反射性,都是实盘必须配齐”校验层”才能用的真实代价。把它当警报器,而不是当圣杯。