Mímisbrunnr知恵の泉

← 金融工学 一覧

🎓 レベル:標準 | 重要度:A(必須)

📎 前提:二項モデルとリスク中立評価 | 関連:ブラックショールズ公式と解釈

要点(BLUF)

1. CRR 二項木の構造

二項モデルとリスク中立評価 の二項モデルを、ボラティリティ σ\sigma に合わせて多段に刻んだのが CRR(Cox–Ross–Rubinstein)モデルです。各ステップ Δt=T/n\Delta t=T/n

u=eσΔt,d=1u,q=erΔtdudu = e^{\sigma\sqrt{\Delta t}}, \quad d = \frac1u, \quad q = \frac{e^{r\Delta t} - d}{u - d}

満期の各ノードでペイオフを計算し、リスク中立確率 qq で1期ずつ割り引きながら根まで戻ります(後ろ向き帰納)。ヨーロピアンとアメリカンを1つの関数で実装します。

import numpy as np
from scipy.stats import norm

def bs_put(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 K*np.exp(-r*T)*norm.cdf(-d2) - S*norm.cdf(-d1)

def binomial(S0, K, r, sigma, T, n, kind="put", american=False):
    dt = T/n
    u = np.exp(sigma*np.sqrt(dt)); d = 1/u
    q = (np.exp(r*dt) - d)/(u - d); disc = np.exp(-r*dt)

    j = np.arange(n+1)
    ST = S0*u**j * d**(n-j)                               # 満期の株価
    val = np.maximum(K-ST, 0) if kind == "put" else np.maximum(ST-K, 0)

    for i in range(n, 0, -1):                             # 後ろ向きに1期ずつ割引
        val = disc*(q*val[1:i+1] + (1-q)*val[0:i])
        if american:                                     # 各ノードで即時行使と比較
            j2 = np.arange(i)
            Si = S0*u**j2 * d**(i-1-j2)                   # 1期前のノードの株価
            ex = np.maximum(K-Si, 0) if kind == "put" else np.maximum(Si-K, 0)
            val = np.maximum(val, ex)                     # 継続 vs 即時行使
    return val[0]

S0, K, r, sigma, T = 100.0, 100.0, 0.05, 0.2, 1.0
n = 1000
euro = binomial(S0, K, r, sigma, T, n, "put", american=False)
amer = binomial(S0, K, r, sigma, T, n, "put", american=True)
print(f"ヨーロピアンプット(二項木 n={n})= {euro:.4f}")
print(f"BS厳密プット                    = {bs_put(S0, K, r, sigma, T):.4f}")
print(f"アメリカンプット(二項木 n={n}) = {amer:.4f}")
print(f"早期行使プレミアム               = {amer-euro:.4f}")

出力:

ヨーロピアンプット(二項木 n=1000)= 5.5715
BS厳密プット                    = 5.5735
アメリカンプット(二項木 n=1000) = 6.0896
早期行使プレミアム               = 0.5181

出力の意味:ヨーロピアンプットの二項木価格 5.5715 は BS 厳密値 5.5735 とほぼ一致(n=1000n=1000 で誤差 0.002)。アメリカンプットは 6.0896 と高く、差 0.5181 が早期行使プレミアムです。アメリカンプットは、深く ITM になったとき「今すぐ KK で売って KK を運用したほうが得」な場面があり、その権利ぶん価値が高い。アメリカン型には閉形式が無いので、こうした逐次判定ができる二項木が標準的な道具になります。

2. アメリカンコールはヨーロピアンに等しい(配当なし)

早期行使が常に得とは限りません。配当のない株のコールでは、早期行使は決して最適になりません。同じ関数で確かめます。

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 binomial(S0, K, r, sigma, T, n, kind="put", american=False):
    dt = T/n
    u = np.exp(sigma*np.sqrt(dt)); d = 1/u
    q = (np.exp(r*dt) - d)/(u - d); disc = np.exp(-r*dt)
    j = np.arange(n+1)
    ST = S0*u**j * d**(n-j)
    val = np.maximum(K-ST, 0) if kind == "put" else np.maximum(ST-K, 0)
    for i in range(n, 0, -1):
        val = disc*(q*val[1:i+1] + (1-q)*val[0:i])
        if american:
            j2 = np.arange(i)
            Si = S0*u**j2 * d**(i-1-j2)
            ex = np.maximum(K-Si, 0) if kind == "put" else np.maximum(Si-K, 0)
            val = np.maximum(val, ex)
    return val[0]

S0, K, r, sigma, T, n = 100.0, 100.0, 0.05, 0.2, 1.0, 1000
print(f"ヨーロピアンコール(二項木)= {binomial(S0,K,r,sigma,T,n,'call',False):.4f}")
print(f"アメリカンコール(二項木)  = {binomial(S0,K,r,sigma,T,n,'call',True):.4f}")
print(f"BS厳密コール                = {bs_call(S0,K,r,sigma,T):.4f}")

出力:

ヨーロピアンコール(二項木)= 10.4486
アメリカンコール(二項木)  = 10.4486
BS厳密コール                = 10.4486

出力の意味:アメリカンコールとヨーロピアンコールが完全に一致(ともに 10.4486、早期行使プレミアムはゼロ)。理由は2つ——早期行使すると残りの時間価値を捨てることになり、しかも KK を早く払うと金利ぶん損だから。「配当のないアメリカンコールは満期まで持つのが最適」という有名な結果が、コードで確認できます。早期行使が意味を持つのは、保有コスト(プットなら KK の機会、コールなら配当)が時間価値を上回るときだけです。

3. 二項木の使いどころ

弱点は次元——複数資産になると木のノードが指数的に増え、モンテカルロ(モンテカルロ法によるオプション価格)や有限差分(有限差分法)に譲ります。

⚠️ よくある誤解

関連ノート