Mímisbrunnr知恵の泉

← 金融工学 一覧

🎓 レベル:発展 | 重要度:B(標準)

📎 前提:BS方程式の導出 | 関連:二項木の実装

要点(BLUF)

1. ブラック–ショールズ方程式を格子で解く

BS方程式の導出 の方程式

Vt+12σ2S22VS2+rSVSrV=0\frac{\partial V}{\partial t} + \tfrac12\sigma^2 S^2\frac{\partial^2 V}{\partial S^2} + rS\frac{\partial V}{\partial S} - rV = 0

を、SS 方向に Si=iΔSS_i = i\,\Delta Si=0,,NSi=0,\dots,N_S)、時間方向に刻んで離散化します。満期 t=Tt=T ではペイオフが分かっている(V(S,T)=max(SK,0)V(S,T)=\max(S-K,0))ので、そこを出発点に時間をさかのぼって現在 t=0t=0 の価格を求めます。これは熱伝導方程式と同じ後ろ向き拡散の構造です。

2. 陽解法の更新式

微分を差分に置き換えます。V/t\partial V/\partial t を前進差分、V/S\partial V/\partial S を中心差分、2V/S2\partial^2 V/\partial S^2 を2次中心差分にすると、各点の現在値が「1つ未来の時間ステップの隣接3点」で書けます。Si=iΔSS_i=i\Delta S を使うと ΔS\Delta S が消え、係数は格子番号 ii だけで決まります。

Vim=aiVi1m+1+biVim+1+ciVi+1m+1V_i^{m} = a_i\,V_{i-1}^{m+1} + b_i\,V_i^{m+1} + c_i\,V_{i+1}^{m+1} ai=12Δt(σ2i2ri),bi=1Δt(σ2i2+r),ci=12Δt(σ2i2+ri)a_i = \tfrac12\Delta t\,(\sigma^2 i^2 - r i),\quad b_i = 1 - \Delta t\,(\sigma^2 i^2 + r),\quad c_i = \tfrac12\Delta t\,(\sigma^2 i^2 + r i)

境界は、コールなら下端 V(0,t)=0V(0,t)=0、上端 V(Smax,t)=SmaxKer(Tt)V(S_{\max},t)=S_{\max}-Ke^{-r(T-t)}安定条件として bi0b_i\ge0、つまり Δt1/(σ2NS2)\Delta t \le 1/(\sigma^2 N_S^2) 程度に時間刻みを小さく取る必要があります(これを破ると数値が爆発します)。

3. 実装と検証

import numpy as np
from scipy.stats import norm

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

def fd_explicit_call(S0, K, r, sigma, T, Smax, NS, NT):
    dS = Smax/NS; dt = T/NT
    i = np.arange(NS+1)
    V = np.maximum(i*dS - K, 0.0)                # 満期ペイオフ(出発点)
    a = 0.5*dt*(sigma**2*i**2 - r*i)
    b = 1 - dt*(sigma**2*i**2 + r)
    c = 0.5*dt*(sigma**2*i**2 + r*i)
    for m in range(NT):                          # 時間を後ろ向きに進める
        Vnew = V.copy()
        Vnew[1:NS] = a[1:NS]*V[0:NS-1] + b[1:NS]*V[1:NS] + c[1:NS]*V[2:NS+1]
        tau = (m+1)*dt
        Vnew[0] = 0.0                            # 下端境界
        Vnew[NS] = Smax - K*np.exp(-r*tau)       # 上端境界
        V = Vnew
    return np.interp(S0, i*dS, V)                # S0 での価格を補間

S0, K, r, sigma, T = 100.0, 100.0, 0.05, 0.2, 1.0
# 安定条件:dt <= 1/(σ²·NS²)。NS=300 なら NT を大きく取る
price_fd = fd_explicit_call(S0, K, r, sigma, T, Smax=300, NS=300, NT=20000)
print(f"有限差分(陽解法)コール = {price_fd:.4f}")
print(f"BS厳密値                = {bs_call(S0, K, r, sigma, T):.4f}")

出力:

有限差分(陽解法)コール = 10.4482
BS厳密値                = 10.4506

出力の意味:格子で偏微分方程式を解いた価格 10.4482 は、BS 厳密値 10.4506 と小数2桁で一致します(差は格子の離散化誤差)。モンテカルロ(モンテカルロ法によるオプション価格)が乱数で期待値を近似したのに対し、有限差分は方程式そのものを解いています——確率的な誤差はなく、格子を細かくすれば決定論的に精度が上がります。おまけに、最終格子 V の隣接差分からデルタ(V/S\partial V/\partial S)やガンマ(2V/S2\partial^2 V/\partial S^2)も同時に読み取れます。

4. 長所・短所と陰解法

⚠️ よくある誤解

関連ノート