1. 期权定价模型实现与比较

任务目标

实现Black-Scholes、二叉树和蒙特卡洛三种欧式看涨期权定价模型,在给定相同参数下比较定价结果与计算耗时,验证三种模型收敛于同一理论价值。

环境依赖

仅需Python 3.8+标准库(math、random、time),无需第三方库。随机数使用固定种子保证可复现。

完整实现

import math
import random
import time

# ---------- 公共参数 ----------
S0 = 100.0      # 标的现价
K = 105.0       # 行权价
T = 1.0         # 到期时间(年)
r = 0.05        # 无风险利率
sigma = 0.20    # 波动率
N_BIN = 500     # 二叉树步数
N_MC = 100000   # 蒙特卡洛路径数
SEED = 42

# ---------- 1. Black-Scholes 解析解 ----------
def bs_call(S0, K, T, r, sigma):
    d1 = (math.log(S0 / K) + (r + 0.5 * sigma**2) * T) / (sigma * math.sqrt(T))
    d2 = d1 - sigma * math.sqrt(T)
    # 标准正态分布CDF(数值近似)
    def norm_cdf(x):
        return 0.5 * (1.0 + math.erf(x / math.sqrt(2.0)))
    return S0 * norm_cdf(d1) - K * math.exp(-r * T) * norm_cdf(d2)

# ---------- 2. 二叉树模型(CRR) ----------
def binomial_call(S0, K, T, r, sigma, N):
    dt = T / N
    u = math.exp(sigma * math.sqrt(dt))
    d = 1.0 / u
    p = (math.exp(r * dt) - d) / (u - d)
    # 到期日期权价值
    prices = [S0 * (u ** (N - i)) * (d ** i) for i in range(N + 1)]
    values = [max(0.0, px - K) for px in prices]
    # 逆向递推
    for step in range(N - 1, -1, -1):
        for i in range(step + 1):
            values[i] = math.exp(-r * dt) * (p * values[i] + (1 - p) * values[i + 1])
    return values[0]

# ---------- 3. 蒙特卡洛模拟 ----------
def mc_call(S0, K, T, r, sigma, n_paths, seed):
    rng = random.Random(seed)
    dt = T  # 单步模拟
    drift = (r - 0.5 * sigma**2) * dt
    vol = sigma * math.sqrt(dt)
    total = 0.0
    for _ in range(n_paths):
        z = rng.gauss(0.0, 1.0)
        ST = S0 * math.exp(drift + vol * z)
        total += max(0.0, ST - K)
    return math.exp(-r * T) * total / n_paths

# ---------- 运行与比较 ----------
# BS
t0 = time.perf_counter()
bs_price = bs_call(S0, K, T, r, sigma)
t_bs = time.perf_counter() - t0

# 二叉树
t0 = time.perf_counter()
bin_price = binomial_call(S0, K, T, r, sigma, N_BIN)
t_bin = time.perf_counter() - t0

# 蒙特卡洛
t0 = time.perf_counter()
mc_price = mc_call(S0, K, T, r, sigma, N_MC, SEED)
t_mc = time.perf_counter() - t0

# 输出结果
print(f"Black-Scholes: {bs_price:.4f}  耗时 {t_bs*1000:.2f} ms")
print(f"二叉树 (N={N_BIN}): {bin_price:.4f}  耗时 {t_bin*1000:.2f} ms")
print(f"蒙特卡洛 (N={N_MC}): {mc_price:.4f}  耗时 {t_mc*1000:.2f} ms")
print(f"二叉树误差: {abs(bin_price - bs_price)/bs_price*100:.3f}%")
print(f"蒙特卡洛误差: {abs(mc_price - bs_price)/bs_price*100:.3f}%")

运行方式

将代码保存为 option_pricing.py,在终端执行:

python option_pricing.py

验证方法与判定标准

程序输出三种模型的价格与耗时。判定通过条件:

  • 二叉树价格与BS价格偏差小于0.5%(N=500时通常偏差<0.1%);
  • 蒙特卡洛价格与BS价格偏差在1%以内(10万条路径下标准误约0.15元,对应约0.5%相对误差);
  • 耗时排序符合预期:BS < 二叉树 < 蒙特卡洛。

若需更高蒙特卡洛精度,可增大N_MC至50万,误差将降至0.2%以内,但耗时线性增加。

关键说明

  • 二叉树采用CRR参数化,步数N_BIN决定收敛精度,500步已足够;
  • 蒙特卡洛使用单步几何布朗运动模拟,SEED=42固定随机序列,每次运行结果一致;
  • BS模型为标准正态CDF的erf近似,精度达1e-15,不影响比较结论。
三种期权定价模型对比(S₀=100, K=105, T=1年, r=5%, σ=20%) 定价结果(元) 0 5 10 15 8.02 BS 8.03 二叉树 8.05 蒙特卡洛 计算耗时(毫秒,对数刻度) 0.01 0.1 1 10 100 BS ~50ms 二叉树 ~300ms 蒙特卡洛 注:二叉树N=500步,蒙特卡洛N=100,000条路径;耗时基于典型PC单次运行,实际值因硬件而异