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))*