Eine Formel für eine Option
1973 zeigten Black und Scholes: Folgt eine Aktie dem Lognormalmodell mit konstanter Volatilität, lässt sich eine Option durch Handel mit der Aktie und einer Anleihe nachbilden, ihr Preis hängt also nicht davon ab, für wie wahrscheinlich Anleger einen Anstieg halten. Der Preis eines europäischen Calls ist S * N(d1) - K * exp(-rT) * N(d2): die Aktie, die Sie erhalten, wenn die Option im Geld endet, gewichtet mit einer wahrscheinlichkeitsähnlichen Zahl, minus der abgezinste Strike, gewichtet mit der risikoneutralen Ausübungswahrscheinlichkeit N(d2). Der Put folgt aus der Parität.
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.15Der Call und der Put
N ist die Verteilungsfunktion der Standardnormalverteilung, die Pythons math.erf als 0.5 * (1 + erf(x / sqrt(2))) liefert. d1 und d2 verbinden die Moneyness ln(S/K), den Drift und die Volatilität über die Laufzeit der Option. Damit gilt: Call = S * N(d1) - K * exp(-rT) * N(d2) und Put = K * exp(-rT) * N(-d2) - S * N(-d1). Bei Kassakurs 100, Strike 100, 5 % Zins, 20 % Volatilität und einem Jahr kostet der Call 10,45 und der Put 5,57, und die Differenz 4,88 ist genau der Paritätswert 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 holdsWas den Preis bewegt
Fünf Eingaben bestimmen den Preis. Ein höherer Strike macht den Call billiger (80: 24,59; 100: 10,45; 120: 3,25). Eine höhere Volatilität verteuert beide Optionen, weil mehr Unsicherheit dem Inhaber nur Aufwärtspotenzial hinzufügt (10 %: 6,81; 20 %: 10,45; 40 %: 18,02). Eine längere Laufzeit erhöht den Preis ebenfalls (3 Monate: 4,62; 1 Jahr: 10,45; 4 Jahre: 25,21). Beachten Sie, dass die erwartete Rendite der Aktie in der Formel überhaupt nicht vorkommt: Nur die Volatilität muss geschätzt werden, weshalb notierte Optionspreise oft als Volatilität ausgedrückt werden.
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)))sowied1 = (ln(S/K) + (r + sigma²/2) T) / (sigma sqrt(T)),d2 = d1 - sigma sqrt(T).- Call =
S N(d1) - K e^(-rT) N(d2); Put =K e^(-rT) N(-d2) - S N(-d1); ihre Differenz ist der ParitätswertS - K e^(-rT). - Preise steigen mit Volatilität und Laufzeit und fallen mit dem Strike des Calls; die erwartete Rendite fehlt, nur die Volatilität wird gebraucht.
Als Nächstes: Delta, wie stark sich der Optionspreis bewegt, wenn sich die Aktie um einen Dollar bewegt.
Lab: Was bewertet wird
- Mit
norm_cdfdie kumulierte Wahrscheinlichkeit der Glocke bauen25 Pkt. - Mit
d1_d2die beiden Black-Scholes-Größen berechnen25 Pkt. - Mit
bs_calleinen Call bewerten25 Pkt. - Mit
bs_puteinen Put bewerten25 Pkt.