3 votos

adelante + desplazamiento

Estoy tratando de fijar el precio de un cap/floor usando Quantlib en Python. El código inicial de este sitio web: http://gouthamanbalaraman.com/blog/interest-rate-cap-floor-valuation-quantlib-python.html

Aquí está mi código para fijar el precio de un piso en EURIBOR1M.

Cuando imprimo los resultados, obtengo el siguiente error:

RuntimeError: avance + desplazamiento (-0.437337 + 0) debe ser positivo

Y cuando lanzo el cómputo de un piso me sale este error:

start_date = ql.Date(4, 2, 2019)
end_date = ql.Date(31, 8 , 2023)
period = ql.Period(1, ql.Months)
calendar = ql.TARGET()
buss_convention = ql.ModifiedFollowing
rule = ql.DateGeneration.Forward
end_of_month = False

schedule = ql.Schedule(start_date, end_date, period,
                       calendar, buss_convention, buss_convention, 
                       rule, end_of_month)

ibor_index = ql.Euribor(ql.Period(1, ql.Months), ts_handle)
ibor_index.addFixing(ql.Date(31,1, 2019), -0.368)
ibor_leg = ql.IborLeg([2074408.03], schedule, ibor_index)

strike = 0.0
floor = ql.Floor(ibor_leg, [strike])

vols = ql.QuoteHandle(ql.SimpleQuote(0.547295))
engine2 = ql.BlackCapFloorEngine(ts_handle, ovs_handle)
floor.setPricingEngine(engine2)
print (floor.NPV())

RuntimeError: avance + desplazamiento (-0,368 + 0) debe ser positivo

 import QuantLib as ql
    import matplotlib.pyplot as plt
    import numpy as np
    %matplotlib inline

calc_date = ql.Date(22, 2, 2019)
ql.Settings.instance().evaluationDate = calc_date

dates = [ql.Date(22,2,2019), ql.Date(22,4,2019), 
         ql.Date(23,5,2019), ql.Date(24,6,2019),
         ql.Date(24,7,2019), ql.Date(22,8,2019),
         ql.Date(23,9,2019), ql.Date(23,10,2019),
         ql.Date(22,11,2019), ql.Date(23,12,2019),
         ql.Date(23,1,2020), ql.Date(24,2,2020),
         ql.Date(22,5,2020), ql.Date(24,8,2020),
         ql.Date(23,11,2020), ql.Date(22,2,2021),
         ql.Date(24,2,2022), ql.Date(23,2,2023),
         ql.Date(22,2,2024), ql.Date(24,2,2025),
         ql.Date(23,2,2026), ql.Date(22,2,2027), 
         ql.Date(24,2,2028), ql.Date(22,2,2029),
         ql.Date(24,2,2031), ql.Date(23,2,2034), 
         ql.Date(24,2,2039), ql.Date(22,2,2044),
         ql.Date(22,2,2049), 
         ]

yields = [-0.36800000,-0.36500000,
          -0.36520000,-0.36430000,
          -0.36350000,-0.36200000,
          -0.36190000,-0.36150000,
          -0.36000000,-0.35890000,
          -0.35680000,-0.35410000,
          -0.34600000,-0.33650000,
          -0.32000000,-0.30490000,
          -0.22600000,-0.13200000,
          -0.02640000,0.08200000,
          0.19150000,0.30100000,
          0.40100000,0.49900000,
          0.68700000,0.89380000,
          1.06480000,1.13200000,
          1.14900000]

day_count = ql.ActualActual()
calendar = ql.TARGET()
interpolation = ql.Linear()
compounding = ql.Compounded
compounding_frequency = ql.Annual

term_structure = ql.ZeroCurve(dates, yields, day_count, calendar, 
                       interpolation, compounding, compounding_frequency)
ts_handle = ql.YieldTermStructureHandle(term_structure)
ts_handle.referenceDate()

strikes = [0.01,0.02, 0.025, 0.03, 0.04, 0.05]
expiries = [ql.Period(i, ql.Years) for i in range(1,6)]
vols = ql.Matrix(len(expiries), len(strikes))
data = [
        [90.635, 96.25, 73.745, 67.215, 61.17],#vector of vols by strike
        [66.665, 70.58, 60.48,  55.18,  49.6],
        [61.225, 64.64, 56.595, 55.18, 49.6],
        [57.25,  60.33, 53.5695, 49.045, 43.695],
        [51.645, 54.29, 49.065,  45.015, 39.915],
        [47.755,50.13,  45.8,    42.04,  37.21]
   ]

for i in range(vols.rows()):
    for j in range(vols.columns()):
        vols[i][j] = data[j][i]/100.0

calendar = ql.UnitedStates()
bdc = ql.ModifiedFollowing
daycount = ql.Actual365Fixed()
settlement_days = 2
capfloor_vol = ql.CapFloorTermVolSurface(settlement_days, calendar, bdc, expiries, strikes, vols, daycount)

optionlet_surf = ql.OptionletStripper1(capfloor_vol, ibor_index)
ovs_handle = ql.OptionletVolatilityStructureHandle(
    ql.StrippedOptionletAdapter(optionlet_surf)
)
tenors = np.arange(0,10,0.25)

tenors = np.arange(0,5,0.25)
strike = 0.015
capfloor_vols = [capfloor_vol.volatility(t, strike) for t in tenors]
opionlet_vols = [ovs_handle.volatility(t, strike) for t in tenors]

plt.plot(tenors, capfloor_vols, "--", label="CapFloor Vols")
plt.plot(tenors, opionlet_vols,"-", label="Optionlet Vols")
plt.legend(bbox_to_anchor=(0.5, 0.25))*

2voto

Daniel Sims Puntos 373

Desde Github Parece que el avance + desplazamiento > 0 es un requisito del motor de precios en Quantlib.

void checkParameters(QuantLib::Real strike,
                     QuantLib::Real forward,
                     QuantLib::Real displacement)
{
    QL_REQUIRE(displacement >= 0.0, "displacement ("
                                        << displacement
                                        << ") must be non-negative");
    QL_REQUIRE(strike + displacement >= 0.0,
               "strike + displacement (" << strike << " + " << displacement
                                         << ") must be non-negative");
    QL_REQUIRE(forward + displacement > 0.0, "forward + displacement ("
                                                 << forward << " + "
                                                 << displacement
                                                 << ") must be positive");
}

En tu código se llama a 'AddFixing' con el número negativo exacto que aparece en el error.

ibor_index.addFixing(ql.Date(31,1, 2019), -0.368)

Según tengo entendido, la parte numérica de 'AddFixing' es una tasa de inflación/interés. El motor interpreta esta tasa como la porción "a futuro" de la ecuación. En la mayoría de los casos, puedo entender que siempre sea positiva, pero recientemente, con la aparición de los tipos de interés negativos, puedo ver por qué se pretende que sea negativa. Si mis suposiciones son correctas, podría valer la pena contribuir o presentar un error en el código base de QuantLib para permitir números negativos aquí.

Editar: Parece que este es el comportamiento esperado y la forma de manejar los tipos de interés negativos es añadir el desplazamiento. Más información se puede encontrar en este hilo . Esencialmente, un número negativo no puede introducirse en un logaritmo. El desplazamiento se puede calcular o tal vez se puede obtener del proveedor de la comilla.

0 votos

Gracias por su respuesta. si quito el addFixing sigo obteniendo el error: RuntimeError: forward + displacement (-0.368 + 0) debe ser positivo. ¿Hay alguna forma de solucionarlo?

0 votos

¿Qué pasa si usted pone una tasa positiva en addFixing como un paso de solución de problemas - para ver si al menos se ejecuta a través del código.

0 votos

Creo que la clave aquí va a estar en un número de desplazamiento positivo. Hay algunas discusiones en torno a los tipos de interés negativos y cómo tratarlos en quantlib. Aquí por ejemplo: quantlib.10058.n7.nabble.com/ y quantlib.10058.n7.nabble.com/ Esto permitirá que su tipo de interés a plazo siga siendo negativo mientras se corrige el modelo de tipo de interés lognormal.

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X