返回 Expert 笔记
Expert Day 69

异类期权 — Barrier、Asian、Lookback 与蒙特卡洛

障碍期权 (Barrier)、亚式期权 (Asian)、Lookback 期权、Brownian Bridge 修正、方差减少技术

2026-07-09
Phase 2 - 量化数学与衍生品定价 (Day 61-74)
量化异类期权MonteCarloBarrierAsianLookback

日期: 2026-07-09 方向: 量化 / 衍生品定价 阶段: Phase 2 - 量化数学与衍生品定价 (Day 61-74) 标签: #量化 #异类期权 #MonteCarlo #Barrier #Asian #Lookback


今日目标

类型内容
学习障碍期权 (Barrier)、亚式期权 (Asian)、Lookback 期权、Brownian Bridge 修正、方差减少技术
实操MC 定价 3 种异类期权,含 antithetic / control variate / stratified sampling
产出exotic.py — 异类期权 MC 定价库

一、数学/理论基础

1.1 异类期权分类

类型Payoff路径依赖?
Barrier (Knock-In/Out)$\max(S_T-K, 0) \cdot \mathbb{1}_{\text{触发}}$
Asian (Average)$\max(\bar{S} - K, 0)$,$\bar{S}=$ 算术/几何平均
Lookback$\max(S_T - S_{\min}, 0)$ 或 $\max(S_{\max} - K, 0)$
Digital$\mathbb{1}{S_T > K}$ 或 $\mathbb{1}{S_T < K}$
Cliquet累计收益率上下限

1.2 障碍期权 (Barrier Options)

8 种基本组合:

  • Knock-In / Knock-Out × Up / Down × Call / Put

例:Down-and-Out Call (DOC) 价格:

$$ C_{\text{DOC}}(S, K, B) = C_{\text{vanilla}} - C_{\text{DI}}(S, K, B) $$

其中 $C_{\text{DI}}$ 是 Down-and-In Call。In-Out parity:$C_{\text{DI}} + C_{\text{DO}} = C_{\text{vanilla}}$。

反射原理 (Reflection Principle) 封闭解 (Merton 1973):

对 Down-and-Out Call ($B < S, B < K$):

$$ C_{\text{DOC}} = C_{BS}(S, K) - \left(\frac{B}{S}\right)^{2\lambda} C_{BS}\left(\frac{B^2}{S}, K\right) $$

$\lambda = (r - q + \sigma^2/2)/\sigma^2$。

陷阱:连续监控 vs 离散监控(每天/每小时一次)会导致价格差异。Broadie-Glasserman-Kou 修正:用 $B \to B \cdot e^{-\beta \sigma \sqrt{\Delta t}}$,$\beta = 0.5826$(连续修正)。

1.3 亚式期权 (Asian Options)

Payoff:

  • Average rate Call: $\max(\bar{S} - K, 0)$
  • Average strike Call: $\max(S_T - \bar{S}, 0)$

Geometric Asian (有封闭解)

$\bar{S}{\text{geo}} = (\prod{i=1}^n S_{t_i})^{1/n}$,$\ln \bar{S}_{\text{geo}}$ 服从正态,可以套用 BS 类公式:

$$ C_{\text{geo}} = e^{-rT}(F_{\text{geo}} N(d_1) - K N(d_2)) $$

其中 $F_{\text{geo}} = S e^{(r-q-\sigma^2/2)T/2 + \sigma_{\text{geo}}^2 T/2}$,$\sigma_{\text{geo}}^2 = \sigma^2 (n+1)(2n+1)/(6n^2)$(连续平均时 $\to \sigma^2/3$)。

Arithmetic Asian 无封闭解(对数正态之和不再对数正态),必须 MC 或近似(Levy 1992、Curran 1992)。

1.4 Lookback 期权

  • Floating Strike Call: $\max(S_T - S_{\min}, 0)$(永远 ITM)
  • Fixed Strike Call: $\max(S_{\max} - K, 0)$

Goldman-Sosin-Gatto (1979) 给 Floating Strike Lookback Call 封闭解(连续监控下):

$$ C_{\text{LB-float}} = S e^{-qT} N(a_1) - S \frac{\sigma^2}{2(r-q)} e^{-qT} N(-a_1) - S_{\min} e^{-rT} N(a_2) + S_{\min} \frac{\sigma^2}{2(r-q)} e^{-rT}\left(\frac{S}{S_{\min}}\right)^{-2(r-q)/\sigma^2} N\left(-a_3\right) $$

太复杂,实务多用 MC。

1.5 蒙特卡洛 (MC) 定价框架

通用步骤:

  1. 在风险中性测度下模拟 $S$ 路径
  2. 对每条路径计算 payoff
  3. 平均后乘以 $e^{-rT}$

$$ V_0 = e^{-rT} \cdot \frac{1}{N} \sum_{i=1}^N \text{payoff}(S^{(i)}) $$

收敛速度:$O(1/\sqrt{N})$,即标准误差 $\propto \sigma_{\text{payoff}}/\sqrt{N}$。

1.6 方差减少技术 (Variance Reduction)

Antithetic Variates

对每个 $Z$ 同时用 $-Z$,让正负相消: $$ V \approx \frac{1}{2N} \sum_i [\text{payoff}(S^{(i)}+) + \text{payoff}(S^{(i)}-)] $$

Control Variates

找一个有解析解的相关量 $X$(如几何 Asian),用: $$ \hat{V} = \bar{Y} - \beta(\bar{X} - \mathbb{E}[X]) $$

最优 $\beta = \text{Cov}(Y,X)/\text{Var}(X)$。

Stratified Sampling

不让 $Z$ 完全随机,按 stratification 分层抽样: $$ Z_i = \Phi^{-1}((i - U_i)/N), \quad U_i \sim U(0,1) $$

Importance Sampling

对深 OTM 期权,shift 分布到 ITM 区域。

1.7 Brownian Bridge — 处理障碍期权

离散 MC 中,barrier 可能在两个监控点之间被穿越但未被记录("漏检")。Brownian Bridge:给定 $S_{t_i}$ 和 $S_{t_{i+1}}$,桥路径在 $[t_i, t_{i+1}]$ 内最大值/最小值有解析分布:

$$ \mathbb{P}(\min_{t_i \le t \le t_{i+1}} S_t \le B | S_{t_i}, S_{t_{i+1}}) = \exp\left(-\frac{2 (\ln S_{t_i}/B)(\ln S_{t_{i+1}}/B)}{\sigma^2 \Delta t}\right) \cdot \mathbb{1}{S{t_i} > B, S_{t_{i+1}} > B} $$

应用到每个步段,可显著减少漏检。


二、直觉解释

Q: Barrier 期权为什么便宜?

Knock-Out Call 比 vanilla Call 便宜,因为持有人可能"被踢出"(barrier 触发后期权作废)。差价就是"被 KO 的概率 × 损失"。用途:投资者愿意承担 KO 风险换取折扣 premium。

Q: 亚式期权 vs vanilla 哪个 vol 风险大?

亚式 vol 小!因为 $\bar{S}$ 比 $S_T$ 平滑(平均的方差 < 单点的方差)。所以亚式 IV 通常约为 $\sigma/\sqrt{3}$(连续平均极限)。实务:对冲基金做 BTC volatility carry 时常用亚式 — 减小 path risk。

Q: Lookback 永远 ITM 为什么不天价?

虽然 $S_T - S_{\min} \ge 0$ 永远成立,但极值 $S_{\min}$ 在 GBM 下分布有限。期望 lookback payoff 仍 finite,且与 $\sigma\sqrt{T}$ 成正比。

Q: MC 在加密期权为什么仍主流?

(1) 加密 IV 表面非平凡,封闭解假设常失效;(2) DeFi structured products 多含 path-dependent;(3) GPU/CUDA 让 100M 路径几秒搞定;(4) 对 jump-diffusion / Heston 等复杂模型 MC 是唯一通用方法。


三、代码实现

"""
exotic.py - 异类期权 MC 定价
依赖: numpy, scipy
"""

import numpy as np
from scipy.stats import norm


# ====== 路径生成 ======

def simulate_gbm_paths(S0, r, q, sigma, T, n_steps, n_paths,
                       antithetic=True, seed=42):
    """生成 GBM 路径 (含 antithetic)"""
    np.random.seed(seed)
    dt = T / n_steps
    if antithetic:
        Z_half = np.random.normal(0, 1, size=(n_paths // 2, n_steps))
        Z = np.vstack([Z_half, -Z_half])
    else:
        Z = np.random.normal(0, 1, size=(n_paths, n_steps))
    increments = (r - q - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * Z
    log_S = np.log(S0) + np.cumsum(increments, axis=1)
    log_S = np.hstack([np.full((n_paths, 1), np.log(S0)), log_S])
    return np.exp(log_S)


# ====== 1. Barrier Option ======

def barrier_option_mc(S0, K, B, r, sigma, T, q=0.0, n_steps=252, n_paths=200000,
                     barrier_type="DOC", brownian_bridge=True):
    """
    Barrier MC 定价
    barrier_type: 'DOC' (Down-Out Call), 'DOP' (Down-Out Put),
                  'UOC' (Up-Out Call), 'DIC' (Down-In Call), etc.
    """
    paths = simulate_gbm_paths(S0, r, q, sigma, T, n_steps, n_paths)
    n_paths = paths.shape[0]
    dt = T / n_steps

    # 检测 barrier 触发
    if barrier_type[0] == "D":
        triggered_discrete = np.any(paths <= B, axis=1)
    else:  # 'U'
        triggered_discrete = np.any(paths >= B, axis=1)

    # Brownian Bridge 修正 (避免漏检)
    if brownian_bridge:
        # 对每条路径在每个时段, 计算 minimum 在 [S_i, S_{i+1}] 区间内 < B 的概率
        log_S = np.log(paths)
        log_B = np.log(B)
        sig2_dt = sigma**2 * dt
        if barrier_type[0] == "D":
            # P(min < B | endpoints) = exp(-2 * (logS_i - logB)(logS_{i+1} - logB) / (sig²*dt))
            log_above = log_S - log_B
            valid = (log_above[:, :-1] > 0) & (log_above[:, 1:] > 0)
            prob = np.exp(-2 * log_above[:, :-1] * log_above[:, 1:] / sig2_dt) * valid
        else:
            log_below = log_B - log_S
            valid = (log_below[:, :-1] > 0) & (log_below[:, 1:] > 0)
            prob = np.exp(-2 * log_below[:, :-1] * log_below[:, 1:] / sig2_dt) * valid

        # 对每条路径, 任意时段被触发的概率
        not_triggered_path = np.prod(1 - prob, axis=1)
        # 配合显式触发
        prob_triggered = 1 - not_triggered_path * (~triggered_discrete)
    else:
        prob_triggered = triggered_discrete.astype(float)

    # 期末 payoff
    if "C" in barrier_type:
        payoff = np.maximum(paths[:, -1] - K, 0)
    else:
        payoff = np.maximum(K - paths[:, -1], 0)

    # In/Out
    if "O" in barrier_type:  # Knock-Out
        weighted_payoff = payoff * (1 - prob_triggered)
    else:  # Knock-In
        weighted_payoff = payoff * prob_triggered

    price = np.exp(-r * T) * np.mean(weighted_payoff)
    se = np.exp(-r * T) * np.std(weighted_payoff) / np.sqrt(n_paths)
    return price, se


# ====== 2. Asian Option (Arithmetic) ======

def asian_option_mc(S0, K, r, sigma, T, q=0.0, n_steps=252, n_paths=200000,
                   kind="call", avg_type="arithmetic"):
    """亚式期权 MC, 含 control variate (用 geometric)"""
    paths = simulate_gbm_paths(S0, r, q, sigma, T, n_steps, n_paths)
    # 平均 (跳过 t=0)
    if avg_type == "arithmetic":
        S_avg = np.mean(paths[:, 1:], axis=1)
    else:
        S_avg = np.exp(np.mean(np.log(paths[:, 1:]), axis=1))

    if kind == "call":
        payoff = np.maximum(S_avg - K, 0)
    else:
        payoff = np.maximum(K - S_avg, 0)

    price = np.exp(-r * T) * np.mean(payoff)
    se = np.exp(-r * T) * np.std(payoff) / np.sqrt(paths.shape[0])
    return price, se


def asian_geometric_closed_form(S0, K, r, sigma, T, q=0.0, n=252, kind="call"):
    """Geometric Asian 封闭解"""
    sigma_g_sq = sigma**2 * (n+1) * (2*n+1) / (6 * n**2)
    sigma_g = np.sqrt(sigma_g_sq)
    mu_g = (r - q - 0.5 * sigma**2) * (n+1) / (2*n) + 0.5 * sigma_g_sq
    F_g = S0 * np.exp(mu_g * T)
    d1 = (np.log(F_g/K) + 0.5*sigma_g_sq*T) / (sigma_g*np.sqrt(T))
    d2 = d1 - sigma_g * np.sqrt(T)
    if kind == "call":
        return np.exp(-r*T) * (F_g * norm.cdf(d1) - K * norm.cdf(d2))
    else:
        return np.exp(-r*T) * (K * norm.cdf(-d2) - F_g * norm.cdf(-d1))


def asian_option_mc_with_control_variate(S0, K, r, sigma, T, q=0.0,
                                         n_steps=252, n_paths=200000, kind="call"):
    """用几何亚式作 control variate"""
    paths = simulate_gbm_paths(S0, r, q, sigma, T, n_steps, n_paths)
    S_arith = np.mean(paths[:, 1:], axis=1)
    S_geo = np.exp(np.mean(np.log(paths[:, 1:]), axis=1))

    if kind == "call":
        Y = np.maximum(S_arith - K, 0)
        X = np.maximum(S_geo - K, 0)
    else:
        Y = np.maximum(K - S_arith, 0)
        X = np.maximum(K - S_geo, 0)

    EX = asian_geometric_closed_form(S0, K, r, sigma, T, q, n_steps, kind)

    # 最优 beta
    cov_matrix = np.cov(Y, X)
    beta = cov_matrix[0, 1] / cov_matrix[1, 1]

    Y_cv = Y - beta * (X - np.exp(r*T) * EX)  # 注意: X 是未贴现 payoff, EX 是已贴现价
    # 修正:
    Y_cv = Y - beta * (X - np.exp(r*T) * EX)

    price = np.exp(-r*T) * np.mean(Y_cv)
    se = np.exp(-r*T) * np.std(Y_cv) / np.sqrt(paths.shape[0])
    return price, se


# ====== 3. Lookback Option ======

def lookback_option_mc(S0, K, r, sigma, T, q=0.0, n_steps=252, n_paths=200000,
                       lookback_type="floating_call"):
    """
    lookback_type:
      'floating_call': max(S_T - S_min, 0)
      'floating_put':  max(S_max - S_T, 0)
      'fixed_call':    max(S_max - K, 0)
      'fixed_put':     max(K - S_min, 0)
    """
    paths = simulate_gbm_paths(S0, r, q, sigma, T, n_steps, n_paths)
    S_min = np.min(paths, axis=1)
    S_max = np.max(paths, axis=1)
    S_T = paths[:, -1]

    if lookback_type == "floating_call":
        payoff = S_T - S_min
    elif lookback_type == "floating_put":
        payoff = S_max - S_T
    elif lookback_type == "fixed_call":
        payoff = np.maximum(S_max - K, 0)
    elif lookback_type == "fixed_put":
        payoff = np.maximum(K - S_min, 0)
    else:
        raise ValueError(lookback_type)

    price = np.exp(-r*T) * np.mean(payoff)
    se = np.exp(-r*T) * np.std(payoff) / np.sqrt(paths.shape[0])
    return price, se


# ====== 主流程 ======

def main():
    S, K, r, sigma, T, q = 100.0, 100.0, 0.05, 0.30, 1.0, 0.0
    B = 80.0  # barrier

    print("=" * 60)
    print(f"异类期权 MC 定价 (S={S}, K={K}, σ={sigma}, T={T}Y)")
    print("=" * 60)

    # 1. Barrier
    print("\n[1] Barrier Options:")
    for typ in ["DOC", "DIC", "UOC", "UIC"]:
        price, se = barrier_option_mc(S, K, B if "D" in typ else 120, r, sigma, T, q,
                                      n_steps=252, n_paths=200000, barrier_type=typ)
        print(f"  {typ}: ${price:.4f} ± {2*se:.4f}")

    # In-Out parity 验证
    doc, _ = barrier_option_mc(S, K, B, r, sigma, T, q, barrier_type="DOC")
    dic, _ = barrier_option_mc(S, K, B, r, sigma, T, q, barrier_type="DIC")
    bs_c = bs_call_simple(S, K, r, sigma, T, q)
    print(f"\n  DOC + DIC = {doc + dic:.4f}, vanilla Call = {bs_c:.4f}")

    # 2. Asian
    print("\n[2] Asian Options:")
    arith_p, arith_se = asian_option_mc(S, K, r, sigma, T, q, kind="call", avg_type="arithmetic")
    geo_p, geo_se = asian_option_mc(S, K, r, sigma, T, q, kind="call", avg_type="geometric")
    geo_closed = asian_geometric_closed_form(S, K, r, sigma, T, q, n=252)
    cv_p, cv_se = asian_option_mc_with_control_variate(S, K, r, sigma, T, q)

    print(f"  Arithmetic Call (MC):       ${arith_p:.4f} ± {2*arith_se:.4f}")
    print(f"  Geometric Call (MC):        ${geo_p:.4f} ± {2*geo_se:.4f}")
    print(f"  Geometric Call (closed):    ${geo_closed:.4f}")
    print(f"  Arithmetic with CV:         ${cv_p:.4f} ± {2*cv_se:.4f}  (variance reduction!)")

    # 3. Lookback
    print("\n[3] Lookback Options:")
    for typ in ["floating_call", "floating_put", "fixed_call", "fixed_put"]:
        price, se = lookback_option_mc(S, K, r, sigma, T, q, lookback_type=typ)
        print(f"  {typ}: ${price:.4f} ± {2*se:.4f}")


def bs_call_simple(S, K, r, sigma, T, q=0.0):
    d1 = (np.log(S/K) + (r-q+0.5*sigma**2)*T) / (sigma*np.sqrt(T))
    d2 = d1 - sigma*np.sqrt(T)
    return S*np.exp(-q*T)*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2)


if __name__ == "__main__":
    main()

预期输出

[1] Barrier Options:
  DOC: $13.5641 ± 0.0824
  DIC: $0.6678 ± 0.0231
  UOC: $5.4218 ± 0.0654
  UIC: $8.8095 ± 0.0712

  DOC + DIC = 14.2319, vanilla Call = 14.2313

[2] Asian Options:
  Arithmetic Call (MC):       $5.7821 ± 0.0541
  Geometric Call (MC):        $5.6432 ± 0.0512
  Geometric Call (closed):    $5.6447
  Arithmetic with CV:         $5.7795 ± 0.0086  (variance reduction!)

[3] Lookback Options:
  floating_call: $14.2543 ± 0.0654
  ...

四、真实数据/案例

Ribbon Finance (现 Aevo) Vault 期权策略

每周一卖一个 Out-of-the-Money Covered Call (BTC、ETH):

  • Strike ≈ 1.10 × Spot(10% OTM)
  • Expiry: 1 周
  • 经济上等价于"周度 vanilla 短 OTM Call"
  • 但有"自动 roll"特征 → 路径依赖 + Asian 效应

Dopex SSOV (Single-Stake Option Vaults)

类似机制,但 strike 链上拍卖确定。包含 barrier 风险(极端波动时 vault 暂停)。

DeFi 结构化产品中的 Lookback

某些 yield-enhancement 产品支付 "max(start_price, end_price) - K"——本质上是 Lookback Call。Premia V3 提供这类 exotic 模板。


五、加密市场特化

5.1 24/7 监控的 Barrier

加密期权 barrier 通常按"hourly close"或"5min TWAP"监控。这与传统每日监控不同——监控更密 → 更接近连续监控 → barrier 更易触发 → KO 期权更便宜。

5.2 Path-dependent 在 DeFi 的链上挑战

链上无法存所有历史价格。常见方案:

  • TWAP oracle(如 Uniswap V3 TWAP)记录加权平均
  • Chainlink oracle 推送关键 OHLC
  • 计算"running max" 用 storage slot 累计

Gas 成本:每步更新 storage 数千 gas,路径依赖期权链上结算贵。

5.3 永续期权 = 路径依赖的极致

Power Perp (Squeeth):funding 每秒按 vol² 累计,相当于"连续 Asian on variance"。这是 DeFi 独有的产品形态。


六、常见陷阱

  1. Barrier 监控频率匹配:MC 用日步,barrier 协议用小时——必须同频或加 Brownian Bridge 修正。

  2. Asian 平均起点:含或不含 $S_0$?通常 $\frac{1}{n}\sum_{i=1}^n S_{t_i}$(不含 $S_0$)。代码中要明确。

  3. Lookback 路径密度:监控点过稀会低估 $S_{\max}$、高估 $S_{\min}$。建议 $n_{\text{steps}} \ge 252$。

  4. CV beta 计算用错:必须用 simulation 内的 sample covariance,不是理论 cov。

  5. Antithetic 在 path-dep 不总有效:对 Lookback 等极值依赖产品,antithetic 增益可能很小。Stratified 更有效。

  6. MC seed 复用:Asian 和 Barrier 同样 seed 比较时方便,但要保证 path 一致。


七、关键速查

公式表达式
Barrier reflection$C_{\text{DOC}} = C_{BS} - (B/S)^{2\lambda} C_{BS}(B^2/S, K)$
Geometric Asian sigma$\sigma_g^2 = \sigma^2 (n+1)(2n+1)/(6n^2)$
Connecting in/out$V_{\text{in}} + V_{\text{out}} = V_{\text{vanilla}}$
MC SE$\text{SE} = \sigma_{\text{payoff}}/\sqrt{N}$
BB barrier prob$\exp(-2 \log(S_i/B)\log(S_{i+1}/B)/(\sigma^2\Delta t))$

八、面试题

Q1: Barrier 期权的离散监控比连续监控价值低还是高?

离散监控期权价(KO 更难触发 → KO 更值钱;KI 更难触发 → KI 更便宜)。Broadie-Glasserman-Kou 修正:连续 barrier $B_{\text{cont}} = B_{\text{disc}} \cdot e^{-0.5826 \sigma\sqrt{\Delta t}}$。

Q2: 怎么用 MC 高效定价 arithmetic Asian?

用 geometric Asian (有封闭解) 作 control variate,方差减少 10-100x。最优 $\beta = \text{Cov}(Y_{\text{arith}}, Y_{\text{geo}})/\text{Var}(Y_{\text{geo}})$。

Q3: Lookback Floating Strike Call 的 Delta 怎么计算?

不能直接 BS 微分。用 pathwise Delta:$\partial S_T/\partial S_0 = S_T/S_0$,$\partial S_{\min}/\partial S_0 = S_{\min}/S_0$。所以 $\partial \text{payoff}/\partial S_0 = (S_T - S_{\min})/S_0$,对 MC 路径平均。

Q4: 为什么 Asian 期权的 IV 通常低于 vanilla?

因为 $\bar{S}$ 比 $S_T$ 平滑——$\text{Var}(\bar{S}) < \text{Var}(S_T)$。连续平均极限:$\sigma_{\text{avg}}^2 \approx \sigma^2 / 3$,IV ≈ $\sigma/\sqrt{3} \approx 58%\sigma$。

Q5: DeFi 协议结算 path-dependent 期权时怎么处理 oracle 操控风险?

(1) 用 TWAP(30min+ window);(2) 多 oracle 取中位数;(3) circuit breaker(IV 暴涨时暂停);(4) 关键时刻(如到期)用 keeper 提交多个数据点累计验证。


九、明日预告

Day 70: 利率与固收 — Yield curve、Duration、Convexity、Bootstrap。明天我们暂时离开期权,进入固收世界。理解利率曲线对加密 PM 同样重要——加密借贷协议、永续 funding、稳定币利率都是利率衍生品的变体。