Estoy tratando de calibrar el modelo G2++ a los cap de tasas de interés utilizando la biblioteca Quantlib en Python. Tengo el problema de que mi optimización siempre se detiene con los valores iniciales. Así que probablemente mi configuración para los ayudantes de cap o la optimización en sí está mal. Desafortunadamente, no puedo avanzar aquí y estaría encantado de tener algo de ayuda.
Espero que alguien tenga experiencia con Quantlib y pueda ayudar. Adjunto está mi código con algunos datos de muestra.
¡Muchas gracias!
import QuantLib as ql
# Configuraciones iniciales
fecha_valoracion = ql.Date(29, 1, 2024)
ql.Settings.instance().evaluationDate = fecha_valoracion
# Configuración de la curva de rendimiento
vencimientos_swap = [ql.Period(6, ql.Months), ql.Period(1, ql.Years), ql.Period(2, ql.Years),
ql.Period(3, ql.Years), ql.Period(4, ql.Years), ql.Period(5, ql.Years),
ql.Period(6, ql.Years), ql.Period(7, ql.Years), ql.Period(8, ql.Years),
ql.Period(9, ql.Years), ql.Period(10, ql.Years), ql.Period(12, ql.Years),
ql.Period(15, ql.Years), ql.Period(20, ql.Years), ql.Period(25, ql.Years),
ql.Period(30, ql.Years)]
fechas = [fecha_valoracion + vencimiento for vencimiento in vencimientos_swap]
tasas = [0.03873, 0.03524, 0.02955, 0.02745, 0.02662, 0.02631, 0.02625, 0.02631,
0.02644, 0.02661, 0.02680, 0.02720, 0.02749, 0.02696, 0.02598, 0.02499]
dias = ql.Actual360()
calendario = ql.Germany()
interpolacion = ql.Linear()
capitalizacion = ql.Compounded
frecuencia_capitalizacion = ql.Semiannual
estructura_plazos = ql.ZeroCurve(fechas, tasas, dias, calendario,
interpolacion, capitalizacion, frecuencia_capitalizacion)
ts_manejador = ql.YieldTermStructureHandle(estructura_plazos)
# Cap Vols
vols_mercado = {
1: 0.9081,
2: 1.0488,
3: 1.0533,
4: 1.0391,
5: 1.0232,
6: 1.008,
7: 0.9926,
8: 0.978,
9: 0.9633,
10: 0.9498,
12: 0.9246,
15: 0.8901,
20: 0.8439,
25: 0.8091,
}
# Configuración del Modelo
modelo = ql.G2(ts_manejador)
# Crear Objetos Cap
ayudantes_cap = []
fecha_inicio = fecha_valoracion + ql.Period(6,ql.Months)
for vencimiento, volatilidad in vols_mercado.items():
periodo = ql.Period(vencimiento, ql.Years)
fecha_fin = calendario.advance(fecha_valoracion, periodo)
cronograma = ql.Schedule(fecha_inicio, fecha_fin, ql.Period(ql.Annual), calendario,
ql.Unadjusted, ql.Unadjusted, ql.DateGeneration.Forward, False)
# Cálculo de la Tasa de Strike
tasa_fwd = estructura_plazos.forwardRate(fecha_inicio, fecha_fin, dias, capitalizacion, frecuencia_capitalizacion).rate()
cita_strike = ql.SimpleQuote(tasa_fwd)
# Cita de Volatilidad
vol_cita = ql.QuoteHandle(ql.SimpleQuote(volatilidad))
# Configuración del Ayudante de Cap
ayudante = ql.CapHelper(periodo, vol_cita, cita_strike, ql.Annual, dias, False, ts_manejador)
ayudante.setPricingEngine(ql.BlackCapFloorEngine(ts_manejador, vol_cita))
ayudantes_cap.append(ayudante)
# Configuración del método de calibración
metodo_optimizacion = ql.LevenbergMarquardt(1e-8, 1e-8, 1e-8)
# Definición de criterios de finalización
criterios_fin = ql.EndCriteria(1000, 500, 1e-8, 1e-8, 1e-8)
# Calibración
modelo.calibrate(ayudantes_cap, metodo_optimizacion, criterios_fin)
# Resultados
a, sigma, b, eta, rho = modelo.params()
print(f"Parámetros del modelo G2++: a = {a}, sigma = {sigma}, b = {b}, eta = {eta}, rho = {rho}")
```