5D Library › 信贷周期、自组织临界性与市场相变的统计物理 · English

第五章 隐含波动率、偏度与恐慌指数

布莱克–斯科尔斯公式与隐含波动率

布莱克与斯科尔斯在 1973 年给出了欧式期权的定价公式 (Black and Scholes 1973)。它假设标的资产价格服从几何布朗运动,波动率 σ\sigma 不变,可以无摩擦地连续交易。看涨期权的价格为

C=SN(d1)−Ke−rTN(d2),d1,2=ln⁡(S/K)+(r±σ2/2)TσTC = S\,N(d_1) – K e^{-rT} N(d_2), \qquad d_{1,2} = \frac{\ln(S/K) + (r \pm \sigma^2/2)\,T}{\sigma\sqrt{T}}

其中 SS 是标的价格,KK 是行权价,TT 是到期时间,rr 是无风险利率,NN 是标准正态分布函数。公式中只有 σ\sigma 不能直接观察。反过来,给定市场上的期权价格,求出使公式价格等于市场价格的 σ\sigma,这个数就叫隐含波动率。它没有解析解,但可以用牛顿法迭代:每一步用期权价格对 σ\sigma 的导数(称为 vega)修正一次。

如果布莱克–斯科尔斯的假设成立,同一到期日、不同行权价的期权应该给出同一个隐含波动率。实际上并非如此。

证据

1987 年之后的偏度。 鲁宾斯坦报告,标准普尔 500 指数期权的隐含波动率在 1987 年 10 月股灾之后呈现出明显而持久的形态:行权价越低(越是虚值的看跌期权),隐含波动率越高 (Rubinstein 1994)。这种形态通常称为波动率「偏度」或「微笑」。

跳跃怎样产生偏度

一种产生偏度的方式,是让价格过程除了连续的波动之外,还会偶尔发生向下的跳跃。默顿在 1976 年给出了这种「跳跃–扩散」过程下的期权价格:它等于一系列布莱克–斯科尔斯价格按跳跃次数的泊松概率加权求和 (Merton 1976)。

推导

标的价格 100,三个月到期,连续部分的波动率为 15%;此外平均每两年发生一次跳跃,跳跃的平均幅度约为 −10%,标准差 10%。先用一个已知的价格检验牛顿法,再对每个行权价用虚值期权(行权价低于 100 用看跌期权,高于 100 用看涨期权)的跳跃–扩散价格反推布莱克–斯科尔斯隐含波动率。

# Black-Scholes (1973) prices, implied volatility by Newton's method, and the skew that appears when
# the true process has downward jumps (Merton 1976 jump-diffusion, priced exactly as a Poisson-
# weighted sum of Black-Scholes prices). Parameters are illustrative, not fitted to any market.
import math
Ncdf = lambda x: 0.5 * math.erfc(-x / math.sqrt(2))
npdf = lambda x: math.exp(-x * x / 2) / math.sqrt(2 * math.pi)

def bs(S, K, T, r, s, call=True):
    d1 = (math.log(S / K) + (r + s * s / 2) * T) / (s * math.sqrt(T)); d2 = d1 - s * math.sqrt(T)
    if call: return S * Ncdf(d1) - K * math.exp(-r * T) * Ncdf(d2)
    return K * math.exp(-r * T) * Ncdf(-d2) - S * Ncdf(-d1)

def vega(S, K, T, r, s):
    d1 = (math.log(S / K) + (r + s * s / 2) * T) / (s * math.sqrt(T))
    return S * npdf(d1) * math.sqrt(T)

def implied_vol(price, S, K, T, r, call=True, s=0.3):
    for it in range(50):
        diff = bs(S, K, T, r, s, call) - price
        if abs(diff) < 1e-10: return s, it
        s = max(1e-4, s - diff / vega(S, K, T, r, s))           # Newton step
    raise ValueError("no convergence")

def merton(S, K, T, r, s, lam, muj, dj, call=True, nmax=40):
    k = math.exp(muj + dj * dj / 2) - 1                          # mean relative jump size
    lp = lam * (1 + k)
    tot = 0.0
    for n in range(nmax):
        sn = math.sqrt(s * s + n * dj * dj / T)
        rn = r - lam * k + n * math.log(1 + k) / T
        tot += math.exp(-lp * T) * (lp * T) ** n / math.factorial(n) * bs(S, K, T, rn, sn, call)
    return tot

S, T, r = 100.0, 0.25, 0.03
p = bs(S, 95, T, r, 0.22, call=False)
iv, it = implied_vol(p, S, 95, T, r, call=False)
print(f"round trip: put K = 95 priced at sigma 22 % -> {p:.4f}; Newton recovers {iv:.6f} in {it} steps")
print("strike   option   jump-diffusion price   Black-Scholes implied vol")
ivs = {}
for K in (80, 85, 90, 95, 100, 105, 110, 115, 120):
    call = K >= S                                                # out-of-the-money option at each strike
    pr = merton(S, K, T, r, 0.15, lam=0.5, muj=-0.10, dj=0.10, call=call)
    ivs[K], _ = implied_vol(pr, S, K, T, r, call)
    print(f"  {K:4d}   {'call' if call else 'put ':4s}        {pr:8.4f}                 {ivs[K]:6.2%}")
print(f"skew: implied vol at 90 minus at 110 = {ivs[90] - ivs[110]:+.2%}"
      f" (diffusion sd alone is 15.00 %; with no jumps every strike would show 15.00 %)")
# round trip: put K = 95 priced at sigma 22 % -> 1.9997; Newton recovers 0.220000 in 3 steps
# strike   option   jump-diffusion price   Black-Scholes implied vol
#     80   put           0.0958                 23.41%
#     85   put           0.2347                 21.41%
#     90   put           0.5592                 19.46%
#     95   put           1.3503                 18.00%
#    100   call          3.7864                 17.11%
#    105   call          1.6830                 16.61%
#    110   call          0.6137                 16.33%
#    115   call          0.1856                 16.19%
#    120   call          0.0483                 16.19%
# skew: implied vol at 90 minus at 110 = +3.13% (diffusion sd alone is 15.00 %; with no jumps every strike would show 15.00 %)
把跳跃–扩散模型的期权价格当作布莱克–斯科尔斯价格来读,得到的隐含波动率随行权价下降而升高。点线是连续部分的波动率 15%。

牛顿法三步就恢复了 22% 的隐含波动率。在跳跃–扩散模型中,行权价 80 的看跌期权隐含波动率约为 23.4%,行权价 110 以上的看涨期权约为 16.2–16.3%;90 与 110 之间相差约 3.1 个百分点。所有行权价的隐含波动率都高于 15%,因为跳跃本身增加了总波动;而左边高得多,因为跳跃主要是向下的,使深度虚值的看跌期权比在纯连续模型中更有价值。

注

偏度不是「崩盘的概率」。 期权价格是风险中性的价格:它们既反映市场参与者对下跌可能性的判断,也反映他们为避免下跌而愿意支付的保险费,也就是风险溢价。虚值看跌期权的隐含波动率高,可能是因为下跌的可能性被认为较大,也可能是因为对保护的需求大、而愿意卖出这种保险的人要求高额补偿,通常两者兼而有之。所以不能把偏度直接换算成「市场认为下个月崩盘的概率」。另外,产生偏度的机制也不只跳跃一种,随机波动率模型(波动率与价格负相关)也能产生类似的形态。

恐慌指数与均值回归

芝加哥期权交易所的 VIX 指数常被称为「恐慌指数」。惠利说明了它的来历:1993 年推出时用的是标准普尔 100 指数平值期权的隐含波动率;2003 年改为用标准普尔 500 指数一系列行权价的期权价格计算未来 30 天的预期波动率,不再依赖布莱克–斯科尔斯模型 (Whaley 2009)。它衡量的同样是风险中性的预期,并且在股市下跌时往往急升。

波动率指数的一个显著特征是均值回归:急升之后往往回落,长期低迷之后往往回升。一个常用的简化描述是让它的对数服从奥恩斯坦–乌伦贝克过程 (Uhlenbeck and Ornstein 1930):

dx=θ(μ−x)dt+ηdW,x=ln⁡Vdx = \theta\,(\mu – x)\,dt + \eta\,dW, \qquad x = \ln V

θ\theta 越大,回归越快;偏离的「半衰期」为 ln⁡2/θ\ln 2/\theta。

推导

用一个半衰期为 30 个交易日、长期水平为 18 的模拟序列(不是真实的 VIX),先计算一次急升到 40 之后、没有新冲击时的回落路径(也是这一模型下的中位数路径);再看用 1 年和 10 年的日数据估计半衰期有多准;最后计算「隐含波动率排名」(IV Rank)与百分位这两个常用指标。

# Mean reversion of a volatility index, modelled as an Ornstein-Uhlenbeck process for its logarithm:
#   x = ln(V),  dx = theta (mu - x) dt + eta dW      (daily steps of 1/252 year)
# mu = ln 18, half-life 30 trading days, eta = 1.1 per sqrt(year). A simulated series, not the VIX.
import math, random, statistics as st
MU, HALF, ETA, DT = math.log(18), 30, 1.1, 1 / 252
TH = math.log(2) / (HALF * DT)

def path(n, rnd, x0=MU):
    phi, sd = math.exp(-TH * DT), ETA * math.sqrt((1 - math.exp(-2 * TH * DT)) / (2 * TH))
    x, out = x0, []
    for _ in range(n):
        x = MU + phi * (x - MU) + sd * rnd.gauss(0, 1); out.append(x)
    return out

def half_life(x):
    """Regress x[t+1] on x[t]; half-life = -ln 2 / ln(slope), in days."""
    a, b = x[:-1], x[1:]
    ma, mb = st.fmean(a), st.fmean(b)
    s = sum((u - ma) * (v - mb) for u, v in zip(a, b)) / sum((u - ma) ** 2 for u in a)
    return -math.log(2) / math.log(s) if 0 < s < 1 else float("inf")

rnd = random.Random(4)
print("level after a spike to 40 with no new shocks (the median path), days:", ", ".join(
    f"{h}: {math.exp(MU + (math.log(40) - MU) * math.exp(-TH * DT * h)):.1f}" for h in (0, 10, 30, 60, 120)))
for years in (1, 10):
    est = sorted(half_life(path(252 * years, rnd)) for _ in range(200))
    print(f"half-life estimated from {years:2d} year(s) of daily data, 200 samples: median {est[100]:.0f} days,"
          f" middle 80 % {est[20]:.0f}-{est[180]:.0f} (true {HALF})")
v = [math.exp(u) for u in path(252, rnd)]
cur, lo, hi = v[-1], min(v), max(v)
print(f"one simulated year: last {cur:.1f}, range {lo:.1f}-{hi:.1f};"
      f" IV-rank-style position {(cur - lo) / (hi - lo):.0%}, percentile {sum(u < cur for u in v) / len(v):.0%}")
# level after a spike to 40 with no new shocks (the median path), days: 0: 40.0, 10: 33.9, 30: 26.8, 60: 22.0, 120: 18.9
# half-life estimated from  1 year(s) of daily data, 200 samples: median 18 days, middle 80 % 9-37 (true 30)
# half-life estimated from 10 year(s) of daily data, 200 samples: median 29 days, middle 80 % 23-36 (true 30)
# one simulated year: last 26.8, range 13.4-34.1; IV-rank-style position 65%, percentile 85%

在这个模型中,急升到 40 之后,没有新冲击时 30 个交易日回到约 27,120 天回到约 19;这也是分布的中位数,由于对数正态分布右偏,平均值略高。但这条路径不是保证:均值回归描述的是平均的倾向,一次急升之后完全可能出现更高的急升。

估计结果更值得注意:用 1 年的数据估计,半衰期的中位数只有约 18 天(真值 30),而且散布在 9 到 37 天之间;用 10 年的数据才接近真值。短样本系统地高估了均值回归的速度,这是自回归系数在小样本中向下偏的结果。

最后一行显示两种常用指标可以相差很大:同一个读数,在过去一年的区间中位于 65% 的位置(IV Rank 的算法:减去最低值、除以区间),却高于过去一年 85% 的日子(百分位)。IV Rank 只由最高值和最低值两天决定,一次极端读数就会改变它;百分位用到了全部数据。

本章小结

隐含波动率是使布莱克–斯科尔斯公式与市场价格一致的波动率,可以用牛顿法反推。1987 年之后,指数期权出现了持久的偏度;含向下跳跃的价格过程可以产生这种形态。偏度是风险中性的价格,包含风险溢价,不能直接读作崩盘概率。波动率指数有均值回归的倾向,但短样本会高估回归速度,常用的 IV Rank 与百分位可以给出很不相同的读数。下一章讨论两种更有野心的方法:在危机来临之前识别它的信号。

参考文献

Black, Fischer, and Myron Scholes. 1973. “The Pricing of Options and Corporate Liabilities.” Journal of Political Economy 81 (3): 637–54.
Merton, Robert C. 1976. “Option Pricing When Underlying Stock Returns Are Discontinuous.” Journal of Financial Economics 3 (1–2): 125–44.
Rubinstein, Mark. 1994. “Implied Binomial Trees.” Journal of Finance 49 (3): 771–818.
Uhlenbeck, G. E., and L. S. Ornstein. 1930. “On the Theory of the Brownian Motion.” Physical Review 36 (5): 823–41.
Whaley, Robert E. 2009. “Understanding the VIX.” Journal of Portfolio Management 35 (3): 98–105.

Fan, Y. (2026). Credit Cycles, Self-Organised Criticality and the Statistical Physics of Market Phase Transitions: From Minsky's Financial Instability Hypothesis and Sandpile Power-Law Avalanches to Implied-Volatility Skew, Read Beside Classical Chinese Thought on Rise and Decline [信贷周期、自组织临界性与市场相变的统计物理] (Version 1.0.0). 5D Library. https://doi.org/10.5281/zenodo.23754711 · Licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0).