オプションの価格式
1973年にブラックとショールズは、株価が一定のボラティリティの対数正規モデルに従うなら、株式と債券の売買でオプションを複製でき、その価格は投資家が上昇をどれだけ見込むかに依存しないことを示しました。ヨーロピアン・コールの価格は S * N(d1) - K * exp(-rT) * N(d2) です。オプションがイン・ザ・マネーで終わるときに受け取る株を確率に似た数で重み付けしたものから、支払う割引後の行使価格を、行使されるリスク中立確率 N(d2) で重み付けしたものを引きます。プットはパリティから得られます。
import math
def norm_cdf(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2))) # N(x): the probability that a standard normal is below x
print(round(norm_cdf(0.0), 4), round(norm_cdf(1.96), 4)) # 0.5 0.975
def d1_d2(spot, strike, rate, sigma, t):
d1 = (math.log(spot / strike) + (rate + 0.5 * sigma ** 2) * t) / (sigma * math.sqrt(t))
return d1, d1 - sigma * math.sqrt(t)
d1, d2 = d1_d2(100, 100, 0.05, 0.2, 1)
print(round(d1, 4), round(d2, 4)) # 0.35 0.15コールとプット
N は標準正規分布の分布関数で、Python の math.erf を使えば 0.5 * (1 + erf(x / sqrt(2))) で得られます。d1 と d2 は、ln(S/K)(現在の位置)、ドリフト、オプションの期間にわたるボラティリティをまとめた量です。これらを使って、コール = S * N(d1) - K * exp(-rT) * N(d2)、プット = K * exp(-rT) * N(-d2) - S * N(-d1)。現物100、行使価格100、金利5%、ボラティリティ20%、1年なら、コールは10.45、プットは5.57で、差の4.88はパリティ値 S - K * exp(-rT) とちょうど一致します。
def bs_call(spot, strike, rate, sigma, t):
d1, d2 = d1_d2(spot, strike, rate, sigma, t)
return spot * norm_cdf(d1) - strike * math.exp(-rate * t) * norm_cdf(d2)
def bs_put(spot, strike, rate, sigma, t):
d1, d2 = d1_d2(spot, strike, rate, sigma, t)
return strike * math.exp(-rate * t) * norm_cdf(-d2) - spot * norm_cdf(-d1)
call, put = bs_call(100, 100, 0.05, 0.2, 1), bs_put(100, 100, 0.05, 0.2, 1)
print(round(call, 4), round(put, 4)) # 10.4506 5.5735
print(round(call - put, 4), round(100 - 100 * math.exp(-0.05), 4)) # 4.8771 4.8771 put-call parity holds価格を動かすもの
価格を決める入力は5つです。行使価格が高いほどコールは安くなります(80:24.59、100:10.45、120:3.25)。ボラティリティが高いほど、不確実性は保有者に上昇の余地だけを加えるので、両方のオプションが高くなります(10%:6.81、20%:10.45、40%:18.02)。満期までの時間が長いほど価格も上がります(3か月:4.62、1年:10.45、4年:25.21)。株の期待リターンは式にまったく現れません。推定が必要なのはボラティリティだけなので、オプションの提示価格はボラティリティで表されることがよくあります。
for strike in (80, 100, 120):
print("strike", strike, round(bs_call(100, strike, 0.05, 0.2, 1), 4)) # 24.5888, 10.4506, 3.2475
for sigma in (0.1, 0.2, 0.4):
print("sigma", sigma, round(bs_call(100, 100, 0.05, sigma, 1), 4)) # 6.805, 10.4506, 18.023
for t in (0.25, 1, 4):
print("t", t, round(bs_call(100, 100, 0.05, 0.2, t), 4)) # 4.615, 10.4506, 25.2133# Time value: the call is worth more than its intrinsic value (what it would pay if it expired today)
intrinsic = max(100 - 100 * math.exp(-0.05), 0)
print(round(intrinsic, 4), round(bs_call(100, 100, 0.05, 0.2, 1) - intrinsic, 4)) # 4.8771 5.5735 intrinsic value and time valueN(x) = 0.5 * (1 + erf(x / sqrt(2)))、d1 = (ln(S/K) + (r + sigma²/2) T) / (sigma sqrt(T))、d2 = d1 - sigma sqrt(T)- コール =
S N(d1) - K e^(-rT) N(d2)、プット =K e^(-rT) N(-d2) - S N(-d1)。その差はパリティ値S - K e^(-rT) - 価格はボラティリティと期間で上がり、コールの行使価格で下がる。株の期待リターンは不要で、必要なのはボラティリティだけ
次はデルタです。株が1ドル動いたときにオプション価格がどれだけ動くかを学びます。
ラボ:採点される内容
norm_cdfで釣鐘型の累積確率を作る25点d1_d2でブラック=ショールズの2つの量を計算する25点bs_callでコールを価格付けする25点bs_putでプットを価格付けする25点