已实现波动率双幂变差:用 Bipower 检验把连续波动与跳跃剥开
你看到某天波动率从 1.2% 跳到 3%,这是真实跳跃还是采样噪声?已实现方差 RV(收益平方和)把『连续扩散波动』和『瞬时跳跃』一股脑混在一起,根本分不清。Barndorff-Nielsen-Shephard 的双幂变差 BV 用相邻收益绝对值的乘积,对跳跃免疫、只估连续积分方差;再用 RV−BV 把跳跃变差剥出来,并用 RV/BV 比值做跳跃检验。本文用高频 GBM+泊松跳跃合成数据,从零复现 BV 估计、RV/BV 检测与波动分解,并点明日内频率、微观结构噪声、有限样本、非交易时段四类真实陷阱(中阶)。
某天收盘,你算出来「今日已实现波动率 3.1%」。昨天还是 1.2%。
你第一反应是:「市场出大事了,这是个跳跃。」
但等等——3.1% 里有几成是连续的日内波动(正常该有的),又有几成是真正的瞬时跳跃(开盘跳空、盘中闪崩、重大新闻)?如果分不开,你既没法给期权准确定价(跳跃风险要单独定价),也没法定量「今天到底有多异常」。
已实现方差 RV = Σ 收益² 做不到这一点:它把连续扩散和跳跃都装进平方和里,对跳跃极度敏感。一个 5 倍 sigma 的跳,平方后贡献 25 倍方差。
双幂变差(Bipower Variation, BV) 是 Barndorff-Nielsen & Shephard(2004/2006)的答案:它用「相邻收益绝对值的乘积」代替平方和,对跳跃免疫,只干净地估计连续部分的积分方差。本文从零复现 BV,并演示怎么用它把跳跃从波动里剥出来。
一、为什么 RV 分不清连续和跳跃#
高频对数收益离散化:
其中 是连续扩散, 是泊松跳跃(瞬时位移)。
- 真实连续方差(积分方差):
- 已实现方差:
也就是 。RV 不仅估了连续部分,还把跳跃的平方也收了进来——所以 RV 永远 ≥ IV,且偏差完全由跳跃造成。
问题就在这:你看到 RV 大,不知道是 IV 大了,还是跳大了。
二、双幂变差:用绝对值乘积「跳过」跳跃#
BV 的定义是:
为什么它能只估连续部分?关键点:
- 用绝对值而非平方:平方对极端值(跳跃)超级敏感,绝对值温和得多;
- 取相邻两个 bar 的乘积 :在连续扩散下,(用正态绝对值的一阶矩 校正);
- 跳跃几乎不可能同时落在相邻两个 bar:如果你只在某个 bar 跳一次,那么乘积里最多一个因子含跳,但 的概率极限仍由连续部分主导,跳跃项以更小速率消失——于是 ,完全不受跳跃影响。
一句话:BV 把「平方」换成了「相邻绝对值乘积」,跳跃在乘积里被稀释掉了,连续方差被保留。
三、合成高频数据:GBM + 泊松跳跃#
造一组日内 5 分钟(78 根)对数收益,含连续扩散 + 随机泊松跳跃:
import numpy as np
MU1 = np.sqrt(2 / np.pi) # 0.7979
N_INTRA = 78 # 日内 5 分钟 bar 数
SIGMA_DAY = 0.013 # 日连续波动 1.3%
SIG_INT = SIGMA_DAY / np.sqrt(N_INTRA)
SIG_JUMP = 0.013
LAMBDA = 0.45 # 每日跳跃强度
def sim_day(jump=True, seed=None):
r = np.random.default_rng(seed)
cont = SIG_INT * r.normal(size=N_INTRA)
k = None
if jump and r.uniform() < LAMBDA:
k = r.integers(5, N_INTRA - 1)
cont[k] += r.normal(0, SIG_JUMP) # 盘中某 bar 瞬时跳
return cont, k
def rv(x): return np.sum(x ** 2)
def bv(x): return (1.0 / MU1 ** 2) * np.sum(np.abs(x[1:]) * np.abs(x[:-1]))python真实连续日方差 。
四、单次演示:含跳日 RV/BV 立刻暴露#
取一个含跳日:
day, k = sim_day(jump=True, seed=7)
RV_d, BV_d = rv(day), bv(day)
print(RV_d, BV_d, RV_d / BV_d, k)
# 0.00019 0.00015 1.249 45python
图 1:上=累计对数价格,第 45 根 bar 的红点是一个瞬时跳(连续扩散之外的竖直位移);下=5 分钟收益,该 bar 收益明显异常。但光看这根红 bar,你分不清「这是跳、还是连续波动的尾部」——得靠 BV 来拆。
关键读出:
- RV = 0.00019(含跳,偏大);
- BV = 0.00015(去掉跳,只估连续,逼近真实 IV=0.00017);
- RV/BV = 1.249 > 1——比值越偏离 1,跳跃越可疑。
五、蒙特卡洛:无跳日 vs 含跳日系统性分离#
跑 200 天(约 47.5% 的天含跳),对比两类:
M = 200; RVs, BVs, ratios, has_jump = [], [], [], []
for i in range(M):
x, k = sim_day(jump=True, seed=100 + i)
RVs.append(rv(x)); BVs.append(bv(x)); ratios.append(rv(x) / bv(x))
has_jump.append(k is not None)python
图 2:左=BV(连续)对 RV(含跳)散点,对角虚线是 RV=BV 基准线,含跳日(红)整体落在线上方;右=RV/BV 比值分布,含跳日(红)系统性右移。
实跑数字:
| 指标 | 含跳日(95 天) | 无跳日(105 天) |
|---|---|---|
| RV/BV 均值 | 1.481 | 1.023 |
| BV 均值 | 0.00018 | 0.00018 |
| RV 均值 | (偏高) | — |
- 无跳日 RV/BV ≈ 1.023,紧贴 1——证明 BV 在无跳时与 RV 一致,干净还原 IV;
- 含跳日 RV/BV ≈ 1.481,显著右偏——跳跃把 RV 抬离 BV;
- BV 全样本均值 0.00018,几乎等于真实 IV=0.00017——BV 的连续方差估计是准的;
- RV 全样本均值 0.00023 > IV——正是跳跃贡献的部分。
六、跳跃检验与波动分解#
把 RV/BV 当成跳跃「筛子」,阈值取 1.10 试检:
- 含跳日命中 59/95(召回率 62%);
- 无跳日误报 21/105(误报率 20%)。
召回不算高、误报不算低——这正是朴素阈值法的软肋,也是 BNS 要建正式检验统计量的原因(见下一节)。
更准确的做法是直接分解:

图 3:上=每日 RV/BV 时序,越过橙色阈值 1.10 的红点判为跳跃日;下=把每日总方差拆成蓝色(连续 BV)与红色(跳跃 JV)——一眼看出「波动哪天来自跳、哪天只是连续颠簸」。
七、更严谨:BNS 正式跳跃检验统计量#
朴素比值阈值依赖经验,且有限样本下方差大。BNS 给出带渐近零分布的正式检验:
\widehat{V} = \bigl(\mu_1^{-4} + 2\mu_1^{-2} - 5\bigr)\,\frac{1}{n}\sum_{t=1}^{n} |r_t|^4 \;\xrightarrow{d}\; N(0,1) \quad (\text{无跳时})$$ 其中 $\mu_1^{-4}\approx 2.466$, $\mu_1^{-2}\approx 1.571$,故系数 $\mu_1^{-4}+2\mu_1^{-2}-5 \approx 0.608$。跳跃存在时 $RV-BV>0$,$Z$ 显著为正——在 99% 置信下判跳。 实操要点:这个检验的**功效(power)随日内 bar 数 n 增大而提升**。当 n 只有 78(5 分钟)时,第四矩项 $\frac{1}{n}\sum|r_t|^4$ 偏小、Z 方差大,所以本文朴素阈值才出现 20% 误报。**把采样频率提到 1 分钟甚至 tick 级,n 上去,检验立刻变锋利**——这是下一节陷阱 1 的核心。 ## 八、四类真实陷阱 1. **日内频率不足**:BV/Z 的相合性依赖 n→∞。若只用日收益(退化成 RV 本身),BV=RV,根本分不开;用 5 分钟(78 根)尚可但功效有限(见上)。实务至少 5~15 分钟,想精细捕捉盘中跳用 1~5 分钟。 2. **微观结构噪声**:真实 tick 数据有买卖价差造成的「噪声」,会让 RV 在高频下**反而被噪声放大**(Epps 效应),BV 虽比 RV 稳健但仍受污染。落地要用更长抽样间隔或 TSRV(子采样)先去噪,再算 BV。 3. **有限样本偏差**:$\mu_1^{-2}$ 是渐近校正;小样本下 BV 仍有偏。可用有限样本修正(如加入 $\frac{n}{n-2}$ 型调整),或报告 BV 的置信区间而非单点。 4. **非交易时段与隔夜跳**:RV/BV 只在**连续交易时段**内一致。隔夜跳空、午休跳,在合成数据里被塞进第一根 bar,会污染 BV(因为它落在某个相邻乘积里)。真实落地要把隔夜收益单独处理,不混进日内 BV。 ## 九、结论 双幂变差把「波动率」这个含混的词,拆成了两个可分别定价的量: - **连续积分方差 IV**:用 **BV ≈ 0.00018** 还原(本文逼近真实 0.00017),对跳跃免疫; - **跳跃变差 JV** = $\max(RV-BV,0)$,把瞬时冲击单独剥离; - **检测**:RV/BV 比值——无跳日 ≈1.02、含跳日 ≈1.48,显著右移;正式检验用 BNS 的 $Z\sim N(0,1)$; - **分解**:RV = BV + JV,让你看清单日波动究竟「颠」在哪里。 但记住四个坑:日内频率要够、要防微观结构噪声、要校有限样本、要隔离隔夜跳。跳过任何一步,BV 给你的「连续波动」都可能是假的。 --- *本文数据均为自洽合成(日内 5 分钟 GBM + 泊松跳跃),仅用于演示方法。真实落地时:提高日内采样频率增强检验功效、用 TSRV/子采样去微观结构噪声、对 BV 做有限样本修正、隔夜收益单独处理,并把 BV/Z 接入日内波动率监控。代码已全部跑通,数字即输出。*