Um smile em quatro números
Opções de juros e de câmbio negociam em muitos strikes, e as mesas precisam de um jeito suave e ciente de arbitragem para interpolar e extrapolar as volatilidades cotadas. O SABR (Hagan, Kumar, Lesniewski, Woodward, 2002) é o padrão de mercado. Ele modela um forward F com sua própria volatilidade aleatória alpha: dF = alpha F^beta dW e d alpha = nu alpha dZ, com correlação rho entre os choques. Quatro parâmetros moldam o smile de um vencimento: alpha define o nível geral, beta como a volatilidade depende do nível de preço (0 normal, 1 lognormal), rho a inclinação (skew) e nu a curvatura (quanto as pontas sobem).
# 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)A fórmula de Hagan
A expansão assintótica de Hagan dá a volatilidade implícita de Black sem simulação. No dinheiro (K = F) é alpha / F^(1-beta) vezes uma correção de tempo 1 + (...) * T, em que o parêntese combina três efeitos: a curvatura beta da espinha dorsal, o termo de skew rho * nu e o termo de smile nu^2. Fora do dinheiro, a mesma correção multiplica mais dois fatores: um denominador na log-moneyness L = ln(F/K) e a razão z / chi(z), com z = (nu/alpha) (FK)^((1-beta)/2) L e chi(z) = ln((sqrt(1 - 2 rho z + z^2) + z - rho) / (1 - rho)). Quando z tende a 0 a razão tende a 1, de modo que a fórmula se une suavemente ao valor no dinheiro, mas calcular 0 / 0 diretamente falharia: trate um z minúsculo como um limite.
# 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 = 0Lendo o smile e ajustando-o
Trace a volatilidade implícita contra o strike e os parâmetros têm assinaturas claras. Um rho negativo eleva os strikes baixos e abaixa os altos (skew descendente, típico de ações e de muitos juros); rho = 0 dá um smile simétrico. Um nu maior eleva as duas pontas. beta move a espinha dorsal: quanto a volatilidade no dinheiro muda quando o forward se move. Os profissionais fixam beta por convenção ou pelo histórico e depois calibram o resto às volatilidades cotadas de cada vencimento (próximo tópico), muitas vezes resolvendo alpha a partir da cotação no dinheiro para que ela case exatamente. Duas cautelas: a fórmula é uma aproximação que se degrada em vencimentos longos e strikes muito baixos, onde pode implicar densidades de probabilidade 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 estritamente entre -1 e 1, nu não enorme) e reajuste cada vencimento separadamente e de forma suave no tempo. Para juros baixos ou negativos use a versão normal (Bachelier) da fórmula, que não quebra perto de zero.- O SABR dá a cada vencimento um smile com quatro parâmetros: alpha (nível), beta (espinha dorsal), rho (skew) e nu (curvatura).
- Fórmula de Hagan = pré-fator x
z / chi(z)x correção de tempo; no dinheiro reduz-se aalpha / F^(1-beta)vezes a correção, ez / chi(z)tende a 1 quandoztende a 0. - Um rho negativo inclina o smile para baixo, um nu maior eleva as pontas; ajuste cada vencimento separadamente, verifique arbitragem nas pontas e use a versão normal perto de juros zero.
A seguir: calibração de modelos, ajustar os parâmetros de um modelo aos preços de mercado.
Lab: o que é avaliado
- Somar a correção de tempo com
sabr_correction25 pts - Ler o ponto no dinheiro com
sabr_atm_vol25 pts - Domar o 0 / 0 em
z_over_chi25 pts - Desenhar o smile com
sabr_implied_vol25 pts