Ein Smile in vier Zahlen
Zins- und FX-Optionen werden über viele Strikes gehandelt, und Desks brauchen einen glatten, arbitragebewussten Weg, die quotierten Volatilitäten zu interpolieren und zu extrapolieren. SABR (Hagan, Kumar, Lesniewski, Woodward, 2002) ist der Marktstandard. Es modelliert einen Forward F mit eigener zufälliger Volatilität alpha: dF = alpha F^beta dW und d alpha = nu alpha dZ mit Korrelation rho zwischen den Schocks. Vier Parameter formen den Smile eines Verfalls: alpha setzt das Gesamtniveau, beta wie die Volatilität vom Preisniveau abhängt (0 normal, 1 lognormal), rho die Neigung (Skew) und nu die Krümmung (wie stark die Flügel steigen).
# The four parameters of one expiry, for a rate forward of 3%
f, t = 0.03, 1.0 # forward rate and expiry in years
alpha, beta, rho, nu = 0.035, 0.5, -0.3, 0.4
print(round(alpha / f ** (1 - beta), 4)) # 0.2021 alpha / f^(1-beta) is roughly the at-the-money volatility (before the correction)Hagans Formel
Hagans asymptotische Entwicklung liefert die implizite Black-Volatilität ohne Simulation. At the money (K = F) ist sie alpha / F^(1-beta) mal einer Zeitkorrektur 1 + (...) * T, wobei die Klammer drei Effekte kombiniert: die beta-Krümmung des Rückgrats, den Skew-Term rho * nu und den Smile-Term nu^2. Abseits des Geldes multipliziert dieselbe Korrektur zwei weitere Faktoren: einen Nenner in der Log-Moneyness L = ln(F/K) und das Verhältnis z / chi(z) mit z = (nu/alpha) (FK)^((1-beta)/2) L und chi(z) = ln((sqrt(1 - 2 rho z + z^2) + z - rho) / (1 - rho)). Strebt z gegen 0, geht das Verhältnis gegen 1, die Formel schließt also glatt an den At-the-money-Wert an, doch 0 / 0 direkt zu berechnen würde scheitern: Behandeln Sie winziges z als Grenzwert.
# The pieces of Hagan's formula: the time correction, the at-the-money volatility and z / chi(z)
import math
def sabr_correction(f, k, t, alpha, beta, rho, nu):
fk = f * k
return 1 + ((1 - beta) ** 2 / 24 * alpha ** 2 / fk ** (1 - beta) + rho * beta * nu * alpha / (4 * fk ** ((1 - beta) / 2)) + (2 - 3 * rho ** 2) * nu ** 2 / 24) * t
def sabr_atm_vol(f, t, alpha, beta, rho, nu):
return alpha / f ** (1 - beta) * sabr_correction(f, f, t, alpha, beta, rho, nu)
def z_over_chi(z, rho):
if abs(z) < 1e-7:
return 1.0
return z / math.log((math.sqrt(1 - 2 * rho * z + z ** 2) + z - rho) / (1 - rho))
print(round(sabr_atm_vol(0.03, 1.0, 0.035, 0.5, -0.3, 0.4), 6)) # 0.203877 the at-the-money volatility
print(round(z_over_chi(0.5, -0.3), 6), z_over_chi(0.0, -0.3)) # 1.103683 1.0 near 1, and exactly 1.0 at z = 0Den Smile lesen und anpassen
Tragen Sie die implizite Volatilität gegen den Strike auf, und die Parameter haben klare Signaturen. Ein negatives rho hebt die niedrigen Strikes und senkt die hohen (abwärts gerichteter Skew, typisch für Aktien und viele Zinsen); rho = 0 gibt einen symmetrischen Smile. Ein größeres nu hebt beide Flügel. beta bewegt das Rückgrat: wie stark sich die At-the-money-Volatilität ändert, wenn der Forward sich bewegt. Praktiker legen beta per Konvention oder aus der Historie fest und kalibrieren den Rest an die quotierten Volatilitäten jedes Verfalls (nächstes Thema), oft lösen sie alpha aus der At-the-money-Quote, damit sie exakt passt. Zwei Warnungen: Die Formel ist eine Näherung, die bei langen Laufzeiten und sehr niedrigen Strikes schlechter wird, wo sie negative Wahrscheinlichkeitsdichten implizieren kann.
# The smile for three values of rho: a negative rho lifts the low strikes (downward skew)
import math
def sabr_vol(f, k, t, alpha, beta, rho, nu):
fk = f * k
log = math.log(f / k)
mid = fk ** ((1 - beta) / 2)
z = nu / alpha * mid * log
ratio = 1.0 if abs(z) < 1e-7 else z / math.log((math.sqrt(1 - 2 * rho * z + z ** 2) + z - rho) / (1 - rho))
denominator = mid * (1 + (1 - beta) ** 2 / 24 * log ** 2 + (1 - beta) ** 4 / 1920 * log ** 4)
bracket = 1 + ((1 - beta) ** 2 / 24 * alpha ** 2 / fk ** (1 - beta) + rho * beta * nu * alpha / (4 * mid) + (2 - 3 * rho ** 2) * nu ** 2 / 24) * t
return alpha / denominator * ratio * bracket
for rho in (-0.5, 0.0, 0.5):
print(rho, [round(sabr_vol(0.03, k, 1.0, 0.035, 0.5, rho, 0.4), 4) for k in (0.02, 0.03, 0.04)])
# one line per rho: the first value (low strike) is the highest when rho is negative and the lowest when rho is positive# A free sanity check: with beta = 1 and nu = 0 SABR is Black-Scholes, so the at-the-money volatility is alpha at every expiry
def atm(f, t, alpha, beta, rho, nu):
fk = f * f
bracket = 1 + ((1 - beta) ** 2 / 24 * alpha ** 2 / fk ** (1 - beta) + rho * beta * nu * alpha / (4 * fk ** ((1 - beta) / 2)) + (2 - 3 * rho ** 2) * nu ** 2 / 24) * t
return alpha / f ** (1 - beta) * bracket
print(atm(100.0, 0.5, 0.2, 1.0, -0.3, 0.0), atm(100.0, 5.0, 0.2, 1.0, -0.3, 0.0)) # 0.2 0.2rho strikt zwischen -1 und 1, nu nicht riesig) und kalibrieren Sie jeden Verfall getrennt und glatt über die Zeit. Für niedrige oder negative Zinsen nutzen Sie die Normal-Version (Bachelier) der Formel, die nahe null nicht zusammenbricht.- SABR gibt jedem Verfall einen Smile aus vier Parametern: alpha (Niveau), beta (Rückgrat), rho (Skew) und nu (Krümmung).
- Hagans Formel = Vorfaktor x
z / chi(z)x Zeitkorrektur; am Geld wird sie zualpha / F^(1-beta)mal Korrektur, undz / chi(z)geht gegen 1, wennzgegen 0 geht. - Ein negatives rho neigt den Smile nach unten, ein größeres nu hebt die Flügel; kalibrieren Sie jeden Verfall getrennt, prüfen Sie Arbitrage an den Flügeln und nutzen Sie nahe Nullzinsen die Normal-Version.
Als Nächstes: Modellkalibrierung, Modellparameter an Marktpreise anpassen.
Lab: Was bewertet wird
- Die Zeitkorrektur mit
sabr_correctionergänzen25 Pkt. - Den At-the-money-Punkt mit
sabr_atm_volablesen25 Pkt. - Die 0 / 0 in
z_over_chizähmen25 Pkt. - Den Smile mit
sabr_implied_volzeichnen25 Pkt.