Una sonrisa en cuatro números
Las opciones de tipos y de divisas se negocian en muchos strikes y las mesas necesitan una forma suave y consciente del arbitraje de interpolar y extrapolar las volatilidades cotizadas. SABR (Hagan, Kumar, Lesniewski, Woodward, 2002) es el estándar del mercado. Modela un forward F con su propia volatilidad aleatoria alpha: dF = alpha F^beta dW y d alpha = nu alpha dZ, con correlación rho entre los choques. Cuatro parámetros dan forma a la sonrisa de un vencimiento: alpha fija el nivel global, beta cómo depende la volatilidad del nivel de precio (0 normal, 1 lognormal), rho la inclinación (skew) y nu la curvatura (cuánto suben las alas).
# 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)La fórmula de Hagan
El desarrollo asintótico de Hagan da la volatilidad implícita de Black sin simulación. En el dinero (K = F) es alpha / F^(1-beta) por una corrección temporal 1 + (...) * T, donde el paréntesis combina tres efectos: la curvatura beta de la columna vertebral, el término de skew rho * nu y el término de sonrisa nu^2. Fuera del dinero, la misma corrección multiplica dos factores más: un denominador en la log-moneyness L = ln(F/K) y el cociente z / chi(z), con z = (nu/alpha) (FK)^((1-beta)/2) L y chi(z) = ln((sqrt(1 - 2 rho z + z^2) + z - rho) / (1 - rho)). Cuando z tiende a 0 el cociente tiende a 1, así que la fórmula enlaza suavemente con el valor en el dinero, pero calcular 0 / 0 directamente fallaría: trata un z diminuto como un límite.
# 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 = 0Leer la sonrisa y ajustarla
Traza la volatilidad implícita frente al strike y los parámetros tienen firmas claras. Un rho negativo eleva los strikes bajos y baja los altos (skew descendente, típico de acciones y de muchos tipos); rho = 0 da una sonrisa simétrica. Un nu mayor eleva ambas alas. beta mueve la columna vertebral: cuánto cambia la volatilidad en el dinero cuando se mueve el forward. Los profesionales fijan beta por convención o por el histórico y luego calibran el resto con las volatilidades cotizadas de cada vencimiento (tema siguiente), resolviendo a menudo alpha a partir de la cotización en el dinero para que coincida exactamente. Dos advertencias: la fórmula es una aproximación que se degrada en vencimientos largos y strikes muy bajos, donde puede implicar densidades de probabilidad negativas.
# 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 estrictamente entre -1 y 1, nu no enorme) y reajusta cada vencimiento por separado y con suavidad en el tiempo. Para tipos bajos o negativos usa la versión normal (Bachelier) de la fórmula, que no se rompe cerca de cero.- SABR da a cada vencimiento una sonrisa con cuatro parámetros: alpha (nivel), beta (columna vertebral), rho (skew) y nu (curvatura).
- Fórmula de Hagan = prefactor x
z / chi(z)x corrección temporal; en el dinero se reduce aalpha / F^(1-beta)por la corrección, yz / chi(z)tiende a 1 cuandoztiende a 0. - Un rho negativo inclina la sonrisa hacia abajo, un nu mayor eleva las alas; ajusta cada vencimiento por separado, comprueba el arbitraje en las alas y usa la versión normal con tipos cercanos a cero.
A continuación: calibración de modelos, ajustar los parámetros de un modelo a los precios de mercado.
Lab: qué se califica
- Añadir la corrección temporal con
sabr_correction25 pts - Leer el punto en el dinero con
sabr_atm_vol25 pts - Domar el 0 / 0 en
z_over_chi25 pts - Dibujar la sonrisa con
sabr_implied_vol25 pts