価格が動く、あと2つの理由
デルタ、ガンマ、ベガは株価とそのボラティリティをカバーします。ブラック=ショールズの式の入力で残るのは、満期までの時間と金利です。シータは時間の経過によるオプション価値の変化(式の t は毎日縮みます)、ローは金利が動いたときの変化です。トレーダーが毎日感じるのは普通シータで、買ったオプションは目減りする資産であり、毎日失うプレミアムは凸性を持つことの対価です。
import math
def norm_cdf(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
def norm_pdf(x):
return math.exp(-0.5 * x * x) / math.sqrt(2 * math.pi)
def d1(spot, strike, rate, sigma, t):
return (math.log(spot / strike) + (rate + 0.5 * sigma ** 2) * t) / (sigma * math.sqrt(t))
def d2(spot, strike, rate, sigma, t):
return d1(spot, strike, rate, sigma, t) - sigma * math.sqrt(t)
def call_theta(spot, strike, rate, sigma, t):
decay = -spot * norm_pdf(d1(spot, strike, rate, sigma, t)) * sigma / (2 * math.sqrt(t))
carry = -rate * strike * math.exp(-rate * t) * norm_cdf(d2(spot, strike, rate, sigma, t))
return decay + carry
theta = call_theta(100, 100, 0.05, 0.2, 1)
print(round(theta, 4)) # -6.414 per year
print(round(theta / 365, 4)) # -0.0176 per calendar dayシータ:なぜ時間は痛手なのか
シータの第1項 -S * pdf(d1) * sigma / (2 * sqrt(T)) は*オプション価値*の減衰です。時間が少ないほど大きく動く可能性が減るからです。第2項 -r * K * exp(-rT) * N(d2) は、まだ支払わなくてよい行使価格の利息で、コールの買い手が得ます。コールでは両方とも負なのでシータも負で、損失は一定ではなく、満期が近づくほど、特にアット・ザ・マネーで加速します。通常は暦日あたり theta / 365 で示します。
# Theta per day for the same option as expiry approaches: the decay speeds up
import math
def norm_cdf(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
def norm_pdf(x):
return math.exp(-0.5 * x * x) / math.sqrt(2 * math.pi)
def call_theta(spot, strike, rate, sigma, t):
d_1 = (math.log(spot / strike) + (rate + 0.5 * sigma ** 2) * t) / (sigma * math.sqrt(t))
d_2 = d_1 - sigma * math.sqrt(t)
return -spot * norm_pdf(d_1) * sigma / (2 * math.sqrt(t)) - rate * strike * math.exp(-rate * t) * norm_cdf(d_2)
for days in (360, 90, 30, 7):
per_day = call_theta(100, 100, 0.05, 0.2, days / 365) / 365
print(days, "days left:", round(per_day, 4)) # 360: -0.0177, 90: -0.0288, 30: -0.045, 7: -0.0858ロー:金利
ローは K * T * exp(-rT) * N(d2) で、コールでは正です。金利が上がると、将来支払う行使価格の現在価値が下がるからです。プットは符号が逆です。満期の短いオプションでは最も小さいギリシャ文字で、長期のもの(LEAPS、長期ワラント)では重要になります。ベガをボラティリティ1ポイントで示すのと同じく、金利1パーセントポイントあたり rho / 100 で示します。
# Rho of the one-year call at several rates: it grows with the rate and with the time left
import math
def norm_cdf(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
def call_rho(spot, strike, rate, sigma, t):
d_1 = (math.log(spot / strike) + (rate + 0.5 * sigma ** 2) * t) / (sigma * math.sqrt(t))
return strike * t * math.exp(-rate * t) * norm_cdf(d_1 - sigma * math.sqrt(t))
for rate in (0.0, 0.05, 0.10):
print("rate", rate, "rho per point:", round(call_rho(100, 100, rate, 0.2, 1) / 100, 4)) # 0.0: 0.4602, 0.05: 0.5323, 0.1: 0.5931
print("two years, 5%:", round(call_rho(100, 100, 0.05, 0.2, 2) / 100, 4)) # 1.0568# Check theta and rho by bumping the inputs: they are slopes of the price
import math
def norm_cdf(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
def bs_call(spot, strike, rate, sigma, t):
d_1 = (math.log(spot / strike) + (rate + 0.5 * sigma ** 2) * t) / (sigma * math.sqrt(t))
return spot * norm_cdf(d_1) - strike * math.exp(-rate * t) * norm_cdf(d_1 - sigma * math.sqrt(t))
h = 1e-5
theta = -(bs_call(100, 100, 0.05, 0.2, 1 + h) - bs_call(100, 100, 0.05, 0.2, 1 - h)) / (2 * h)
rho = (bs_call(100, 100, 0.05 + h, 0.2, 1) - bs_call(100, 100, 0.05 - h, 0.2, 1)) / (2 * h)
print(round(theta, 4), round(rho, 4)) # -6.414 53.2325シータはガンマの対価デルタヘッジしたロングのオプションは、株が動けばガンマで稼ぎ、動かない日はシータを払います。ヘッジ済みのポジションではこの2つがほぼ釣り合います:
theta ~ -0.5 * sigma^2 * S^2 * gamma(金利ゼロの場合)。ロング・ガンマのトレーダーは、すでに価格に織り込まれたボラティリティより株が大きく動くことに賭けているわけです。- シータは時間経過で失う価値。ロング・コールでは負で、満期が近いほど、またアット・ザ・マネーで速い。1日あたり
theta / 365で示す - ローは金利への感応度。コールでは正、プットでは負で、長期ほど大きい。1ポイントあたり
rho / 100で示す - どちらも価格の傾きなので、
tやrateを少し動かせばどんな式でも検算できる
次はインプライド・ボラティリティです。式を逆に使って、オプション価格から市場のボラティリティを読み取ります。
ラボ:採点される内容
call_thetaで時間の経過を価格にする25点theta_per_dayで1日あたりの減価を示す25点call_rhoで金利への感応度を測る25点rho_per_pointで1パーセントポイントあたりのローを示す25点