👏

最小二乗法モンテカルロを用いたアメリカンオプションプライシング

2024/10/16に公開

using Random
using Statistics
using LinearAlgebra
using Plots
using Polynomials

# 標準正規乱数を生成する関数
function gen_sn(M, I; anti_paths=true, mo_match=true)
    if anti_paths
        sn = randn(M + 1, Int(I / 2))
        sn = hcat(sn, -sn)
    else
        sn = randn(M + 1, I)
    end
    if mo_match
        sn = (sn .- mean(sn)) ./ std(sn)
    end
    return sn
end

# アメリカン・プットオプションの価格を計算する関数
function price_american_put_option(K::Float64, S0::Float64, r::Float64, sigma::Float64, T::Float64; M::Int=50, I::Int=10000)
    dt = T / M                       # タイムステップの長さ
    df = exp(-r * dt)                # 割引ファクター
    S = zeros(M + 1, I)              # 資産価格パスの行列
    S[1, :] .= S0                    # 初期資産価格を設定
    sn = gen_sn(M, I)                # 標準正規乱数の生成

    # 資産価格パスのシミュレーション
    for t in 2:M+1
        S[t, :] = S[t - 1, :] .* exp.((r - 0.5 * sigma^2) * dt .+ sigma * sqrt(dt) .* sn[t, :])
    end

    h = max.(K .- S, 0.0)            # 即時行使価値
    V = copy(h)                      # オプション価値行列

    # Longstaff-Schwartzアルゴリズムの実装(逆順ループ)
    for t in M:-1:2
        discounted_V = V[t + 1, :] * df   # 次期のオプション価値を現在価値に割引

        # 回帰モデルのフィッティング(次数3の多項式)
        p = fit(S[t, :], discounted_V, 3)

        # 継続価値の推定
        C = p.(S[t, :])

        # 行使戦略の決定
        V[t, :] = ifelse.(C .> h[t, :], V[t + 1, :] * df, h[t, :])
    end

    C0 = df * mean(V[2, :])               # オプション価格の推定
    return C0
end

# 固定パラメータ
S0 = 100.0      # 初期資産価格
r = 0.05        # 無リスク金利
T = 1.0         # 満期(年)
M = 50          # タイムステップ数
I = 10000       # シミュレーションパス数

# 変化させるパラメータ
K_range = range(70.0, 150.0, length=100)
sigma_range = range(0.10, 0.30, length=100)

# オプション価格を格納する行列
option_prices = zeros(length(K_range), length(sigma_range))

# ProgressMeterを使用して進捗を表示(オプション)
using ProgressMeter
@showprogress 1 "Calculating option prices..." for i in 1:length(K_range)
    K = K_range[i]
    for j in 1:length(sigma_range)
        sigma = sigma_range[j]
        # オプション価格の計算
        option_price = price_american_put_option(K, S0, r, sigma, T, M=M, I=I)
        option_prices[i, j] = option_price
    end
end

# 3D サーフェスプロット
plot(
    K_range,
    sigma_range,
    option_prices',
    st = :surface,
    xlabel = "Strike Price K",
    ylabel = "Volatility σ",
    zlabel = "Option Price",
    title = "American Put Option Prices"
)

参考

https://quant.stackexchange.com/questions/43310/least-squares-monte-carlo-by-neural-network-estimator-for-pricing-american-optio

Discussion