Skip to content

11.4 二叉树与有限差分法

概念详解

当期权有美式行权、提前行权边界复杂边界条件时,Black-Scholes 解析公式就力不从心了。1980 年代以来,业界发展出两大数值方法体系:

  1. 二叉树/三叉树方法: 离散时间、离散价格空间,通过构造资产价格的树状结构反向递推求解
  2. 有限差分方法(FDM): 直接对 Black-Scholes PDE 离散化,用矩阵求解

两种方法都收敛到 BS 解析解(如果标的资产确实服从几何布朗运动),但各有优劣:

维度二叉树FDM
美式期权天然支持需特殊处理(PSOR)
实现难度简单中等
收敛速度O(1/n)O(Δt, ΔS²)
路径依赖(障碍/亚式)
多维扩展困难困难

实务中,美式期权优先用二叉树(简单);欧式期权精确定价用 Crank-Nicolson FDM;路径依赖期权则用蒙特卡洛(见 11.5 章)。

名词解释:网格化(Grid)

数值方法的核心操作是构造网格:价格维度 S[0,Smax],时间维度 T0。网格的粗细决定了精度——价格维度 100 格、时间维度 500 格是常见精度上限。

名词解释:边界条件(Boundary Conditions)

数值方法需要在网格的边界给出 V(S, t) 的值。欧式 Call: V(0,t)=0, V(Smax,t)=SmaxKer(Tt)欧式 Put: V(0,t)=Ker(Tt), V(Smax,t)=0。边界条件选错,数值解会显著偏离。

CRR 二叉树模型

Cox-Ross-Rubinstein (CRR) 二叉树模型是最经典的期权定价数值方法之一。其核心思想是将连续时间下的标的资产价格过程离散化为一个二项树结构:

$$\begin{aligned} u &= e^{\sigma\sqrt{\Delta t}} \quad \text{(上涨因子)} \\ d &= e^{-\sigma\sqrt{\Delta t}} \quad \text{(下跌因子)} \\ p &= \frac{e^{r\Delta t} - d}{u - d} \quad \text{(风险中性上涨概率)} \end{aligned}$$
名词解释:风险中性定价

在风险中性测度下,所有资产的预期收益率等于无风险利率。这意味着我们可以用无风险利率贴现预期收益来为衍生品定价,而无需知道资产的真实预期收益率。

PYTHON54 行 · 1.8 KB
📄此处有展示代码54 行 · 1.8 KB展开 ▼
python
import numpy as np

def crr_binomial_tree(S0, K, T, r, sigma, n_steps, option_type='call', american=False):
    """
    CRR 二叉树期权定价
    american=True 时支持提前行权(美式期权)
    """
    dt = T / n_steps
    u = np.exp(sigma * np.sqrt(dt))
    d = 1 / u
    p = (np.exp(r * dt) - d) / (u - d)
    disc = np.exp(-r * dt)

    # 初始化终端价格
    S = np.zeros(n_steps + 1)
    V = np.zeros(n_steps + 1)

    for i in range(n_steps + 1):
        S[i] = S0 * (u ** (n_steps - i)) * (d ** i)
        if option_type == 'call':
            V[i] = max(S[i] - K, 0)
        else:
            V[i] = max(K - S[i], 0)

    # 向后递推
    for step in range(n_steps - 1, -1, -1):
        for i in range(step + 1):
            S[i] = S0 * (u ** (step - i)) * (d ** i)
            # 持有价值(风险中性期望的贴现值)
            hold_value = disc * (p * V[i] + (1 - p) * V[i + 1])

            if american:
                # 美式期权:取持有价值和立即行权价值的最大值
                if option_type == 'call':
                    exercise_value = S[i] - K
                else:
                    exercise_value = K - S[i]
                V[i] = max(hold_value, exercise_value)
            else:
                V[i] = hold_value

    return V[0]


# 欧式与美式期权定价对比
S0, K, T, r, sigma, n = 100, 100, 1.0, 0.03, 0.25, 200

eu_call = crr_binomial_tree(S0, K, T, r, sigma, n, 'call', american=False)
am_call = crr_binomial_tree(S0, K, T, r, sigma, n, 'call', american=True)
eu_put = crr_binomial_tree(S0, K, T, r, sigma, n, 'put', american=False)
am_put = crr_binomial_tree(S0, K, T, r, sigma, n, 'put', american=True)

print(f"欧式看涨: {eu_call:.4f}  |  美式看涨: {am_call:.4f}")
print(f"欧式看跌: {eu_put:.4f}  |  美式看跌: {am_put:.4f}")
点击展开可浏览运行结果
欧式看涨: 11.3361  |  美式看涨: 11.3361
欧式看跌: 8.3807  |  美式看跌: 8.6683

收敛特性:CRR 二叉树的收敛速度是 O(1/n),且存在振荡现象。可以通过对偶数步和奇数步结果取平均来平滑。

美式期权提前行权边界

美式看跌期权的关键特征是存在一个最优行权边界:当资产价格低于此边界时,应尽早行权。

PYTHON23 行 · 762 B
📄此处有展示代码23 行 · 762 B展开 ▼
python
def find_early_exercise_boundary(S0, K, T, r, sigma, n_steps):
    """计算美式看跌期权的最优行权边界"""
    dt = T / n_steps
    u = np.exp(sigma * np.sqrt(dt))
    d = 1 / u
    p = (np.exp(r * dt) - d) / (u - d)
    disc = np.exp(-r * dt)

    boundary = []
    times = []

    # 在每个时间步查找使持有价值=行权价值的临界价格
    for step in range(n_steps):
        t = step * dt
        S = np.array([S0 * (u ** (step - i)) * (d ** i) for i in range(step + 1)])
        V = np.zeros(step + 1)
        for i in range(step + 1):
            V[i] = max(K - S[i], 0)
        # 此处为简化示意,完整实现需反向递推
        boundary.append(S[np.argmax(V > 0)])
        times.append(t)

    return times, boundary
点击展开可浏览运行结果
📘 本段代码定义了 1 个函数/类:函数 `find_early_exercise_boundary`(计算美式看跌期权的最优行权边界)。该片段为教学展示(未包含独立运行的输入数据),可在实战练习中结合真实数据调用。

有限差分法:从二叉树的离散到偏微分方程的求解

有限差分法直接对 Black-Scholes PDE 进行数值求解:

$$\frac{\partial V}{\partial t} + \frac{1}{2}\sigma^2 S^2 \frac{\partial^2 V}{\partial S^2} + rS\frac{\partial V}{\partial S} - rV = 0$$

显式差分法

直接从前一时间步计算后一时间步的值,实现简单,但有严格的稳定性条件:

$$\Delta t \leq \frac{1}{\sigma^2 S_{\max}^2}(\Delta S)^2$$

隐式差分法

需要逐时间步求解线性方程组,但无条件稳定:

PYTHON59 行 · 1.7 KB
📄此处有展示代码59 行 · 1.7 KB展开 ▼
python
from scipy.linalg import solve_banded

def implicit_fdm(S0, K, T, r, sigma, S_max, n_S, n_T, option_type='put'):
    """
    隐式有限差分法 —— 欧式期权定价
    S_max: 截断的标的价格上界 (通常 2-3x S0)
    n_S: 价格网格数
    n_T: 时间网格数
    """
    dS = S_max / n_S
    dt = T / n_T
    S = np.linspace(0, S_max, n_S + 1)

    # 终端条件
    if option_type == 'call':
        V = np.maximum(S - K, 0)
    else:
        V = np.maximum(K - S, 0)

    # 边界条件
    # 构建三对角矩阵的系数
    for j in range(n_T, 0, -1):
        a = np.zeros(n_S - 1)
        b = np.zeros(n_S - 1)
        c = np.zeros(n_S - 1)
        d = np.zeros(n_S - 1)

        for i in range(1, n_S):
            Si = i * dS
            a[i-1] = 0.5 * dt * (r * i - sigma**2 * i**2)
            b[i-1] = 1 + dt * (sigma**2 * i**2 + r)
            c[i-1] = -0.5 * dt * (sigma**2 * i**2 + r * i)
            d[i-1] = V[i]

        # 边界条件修正
        if option_type == 'call':
            d[-1] -= c[-1] * (S_max - K * np.exp(-r * (T - j * dt)))
        else:
            d[0] -= a[0] * (K * np.exp(-r * (T - j * dt)))

        # 求解三对角系统
        ab = np.zeros((3, n_S - 1))
        ab[0, 1:] = c[:-1]
        ab[1, :] = b
        ab[2, :-1] = a[1:]

        V[1:n_S] = solve_banded((1, 1), ab, d)

        # 重新应用边界条件
        if option_type == 'call':
            V[0] = 0
            V[n_S] = S_max - K * np.exp(-r * (T - j * dt))
        else:
            V[0] = K * np.exp(-r * (T - j * dt))
            V[n_S] = 0

    # 查找 S0 对应的期权价格
    idx = int(S0 / dS)
    return V[idx] + (V[idx+1] - V[idx]) * (S0 - S[idx]) / dS
点击展开可浏览运行结果
📘 本段代码定义了 1 个函数/类:函数 `implicit_fdm`(隐式有限差分法 —— 欧式期权定价)。该片段为教学展示(未包含独立运行的输入数据),可在实战练习中结合真实数据调用。

Crank-Nicolson 方法

Crank-Nicolson 是显式和隐式的平均,兼具无条件稳定性和二阶收敛精度 O(Δt2,ΔS2)。其核心思想是对时间导数采用中心差分:

$$\frac{V^{n+1} - V^n}{\Delta t} = \frac{1}{2}\left(\mathcal{L}V^{n+1} + \mathcal{L}V^n\right)$$

三种方法对比

维度二叉树显式FDM隐式FDMCrank-Nicolson
实现难度简单简单中等中等
收敛速度O(1/n)O(Δt,ΔS2)O(Δt,ΔS2)O(Δt2,ΔS2)
稳定性稳定有条件稳定无条件稳定无条件稳定
美式期权天然支持需特殊处理需特殊处理需特殊处理
路径依赖一般不支持不支持不支持
多维扩展困难困难困难困难

方法选择建议

  • 美式期权(无路径依赖) 二叉树,实现简单且自然支持提前行权
  • 欧式期权高精度定价 Crank-Nicolson,收敛快且稳定
  • 路径依赖期权 蒙特卡洛(见11.5章)
PYTHON26 行 · 935 B
📄此处有展示代码26 行 · 935 B展开 ▼
python
# 三种方法定价结果对比
import time

S0, K, T, r, sigma = 100, 100, 1.0, 0.03, 0.25
n_steps = 500

# CRR 二叉树
t0 = time.time()
crr_price = crr_binomial_tree(S0, K, T, r, sigma, n_steps, 'call', american=False)
t_crr = time.time() - t0

# 隐式FDM
t0 = time.time()
fdm_price = implicit_fdm(S0, K, T, r, sigma, S_max=300, n_S=500, n_T=500, option_type='call')
t_fdm = time.time() - t0

# BS 解析解(基准)
from scipy.stats import norm
d1 = (np.log(S0/K) + (r + sigma**2/2)*T) / (sigma*np.sqrt(T))
d2 = d1 - sigma*np.sqrt(T)
bs_price = S0*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2)

print(f"{'方法':<20} {'价格':<12} {'误差':<12} {'耗时':<10}")
print(f"{'BS解析解':<20} {bs_price:<12.6f} {'--':<12} {'--':<10}")
print(f"{'CRR二叉树':<20} {crr_price:<12.6f} {abs(crr_price-bs_price):<12.6f} {t_crr:<10.4f}")
print(f"{'隐式FDM':<20} {fdm_price:<12.6f} {abs(fdm_price-bs_price):<12.6f} {t_fdm:<10.4f}")
点击展开可浏览运行结果
📘 本段为代码片段(依赖上文变量或外部输入,如 df/data/参数等),无法独立运行

常见误区

误区 1:"二叉树步数越多,价格越准"

CRR 二叉树的收敛速度为 O(1/n),但振荡收敛——偶数步和奇数步的结果在真实价格两侧交替。简单提高步数可能反而没有改善。专业做法:Cox-Ross-Rubinstein 抖动技巧,或者用平均步数结果(取 n=999 和 n=1000 取均值)。

误区 2:"显式 FDM 速度慢,所以最好用隐式"

显式 FDM 确实有稳定性限制,但显式的实现简单+并行化容易。隐式需要每步求解三对角矩阵(O(N) 但是 cache-unfriendly)。Crank-Nicolson 介于两者之间。

误区 3:"FDM 可以直接处理美式期权"

不能。美式期权的"提前行权"特征使得 PDE 不再纯线性——行权条件 max(Vcontinuation,Vexercise) 引入了非线性。专业做法:Projected Successive Over-Relaxation (PSOR) 算法,或 Brennan-Schwartz 算法。

误区 4:"网格越密,数值越准"

网格密度无限增大,并不能无限提高精度——截断误差与机器精度收敛。实务中,价格维度 100-500 格、时间维度 100-500 格就能达到 0.001% 误差。盲目提高密度只是浪费时间。

误区 5:"三叉树比二叉树更准,但效果有限"

三叉树在数学上更接近连续过程,但当步数较多时与二叉树差别已经很小,且实现复杂。实务中二叉树才是主流,三叉树主要用于奇异期权或一些特殊品种(如可转债内嵌的赎回/回售条款)。

题目 1
小测验
题目 1:CRR 二叉树的核心是?
  • AA. 三叉树替代
  • BB. 离散化的二叉树结构,节点价格通过 u/d 因子上下调整,概率 p 通过风险中性定价
  • CC. 直接对 BS 公式离散
  • DD. 自适应网格
💡查看答案与解析展开 ▼
正确答案:B
CRR 用 u=eσΔtd=1/u 离散价格过程,风险中性概率 p=(erΔtd)/(ud),再从到期 payoff 反向递推。A 错,三叉树是另一类方法;C 错,它离散的是价格过程而非 BS 公式;D 错,自适应网格属于 FDM 的概念。
题目 2
Crank-Nicolson FDM 的优势是?
  • AA. 实现最简单
  • BB. 无条件稳定 + 二阶时间精度
  • CC. 总是优于 BS 解析解
  • DD. 不需要矩阵求解
💡查看答案与解析展开 ▼
正确答案:B
Crank-Nicolson 取显式与隐式的平均,对时间导数用中心差分,故无条件稳定且具 O(Δt2,ΔS2) 二阶时间精度。A 错,显式 FDM 实现最简单;C 错,数值解只是逼近解析解,谈不上优于;D 错,每步仍需解三对角方程组。
题目 3
美式期权最适合用?
  • AA. 蒙特卡洛 LS 方法
  • BB. 二叉树(天然支持提前行权)
  • CC. Crank-Nicolson FDM
  • DD. 解析公式 + 调整
💡查看答案与解析展开 ▼
正确答案:B
二叉树每个节点都能比较持有价值与行权价值,取 V=max(Vhold,Vexercise),天然支持提前行权,也能直接读出美式 Put 的行权边界。A 错,LSM 需回归估计且倾向低估,多用于多资产;C 错,FDM 处理美式要加 PSOR;D 错,美式无闭式解。

实战练习

  1. CRR 收敛性分析: 对 1 年期 ATM Call (S0=K=100, r=3%, σ=20%), 分别用 n=10,50,100,500,1000 计算价格,绘制"n vs 价格"图,观察振荡收敛现象。

  2. 三方法对比: 编写函数 crr_call, implicit_fdm_call, crank_nicolson_call,对比欧式 Call 的价格(对比 BS 解析解)和计算耗时(直接测量 wall-clock 时间)。理解精度 vs 速度的权衡。

  3. 美式 Put 提前行权边界: 编写代码计算 6 个月到期的美式看跌期权的最优行权边界曲线(在 (S, t) 平面上),绘制行权边界与标的价/到期时间的关系。

  4. 数值稳定性测试: 隐式 FDM 在粗网格(50×50)下应给出稳定答案,但显式 FDM 在同样网格下可能发散。用代码验证:找到显式 FDM 不稳定的参数范围,理解稳定性条件。

  5. 三叉树 vs 二叉树: 实现基本的三叉树模型,与 CRR 二叉树对比: 当步数较多时,差异是否显著? 哪些期权类型下三叉树明显更准?

延伸阅读

  • Hull, J.C. (2018). Options, Futures, and Other Derivatives. Chapter 21 详细介绍二叉树。
  • Glasserman, P. (2003). Monte Carlo Methods in Financial Engineering. Springer. 虽以蒙特卡洛为主,但第 5 章专门讲解 FDM 与树方法。
  • Wilmott, P., Howison, S. & Dewynne, J. (1995). The Mathematics of Financial Derivatives. Cambridge. FDM 的数学完整参考。
  • Brennan, M. & Schwartz, E. (1977). "The Valuation of American Put Options." Journal of Finance. 美式期权数值定价的奠基论文。
  • Hull, J. & White, A. (1990). "Valuing Derivative Securities Using the Explicit Finite-Difference Method." 显式 FDM 的经典论文。

本章要点

  • 二叉树方法: 离散化的二项过程,反向递推期权价值,天然支持美式期权。CRR 是最常用形式。
  • 显式 FDM: 实现最简单,但有严格的稳定性条件 Δt(ΔS)2σ2Smax2
  • 隐式 FDM: 需要逐时间步求解三对角矩阵,但无条件稳定
  • Crank-Nicolson: 显式+隐式平均,精度 O(Δt2),无条件稳定,是欧式高精度定价首选
  • 美式期权最常用的数值方法是二叉树;FDM 处理美式需 PSOR 或 Brennan-Schwartz 算法。
  • 路径依赖期权(亚式/障碍)用二叉树/FDM 都不方便,应使用蒙特卡洛(详见 11.5)。
  • 实务选择: 美式 → 二叉树;欧式精确定价 → Crank-Nicolson FDM;路径依赖 → 蒙特卡洛。

下一章 11.5 将进入 蒙特卡洛定价进阶,讲解方差缩减、对偶变量、控制变量、Longstaff-Schwartz 等加速技巧。