QuantLib
QuantLib copied to clipboard
Errors / FuturesRateHelper Convexity Adjustment Yield Curve bootstrapping issue
Hi all,
I am facing an issue with bootstrapping my Bbsw3M curve. I have sourced market quotes from LSEG Refinitiv for 3M deposit, futures, and swap rates.
In using the FuturesRateHelper, specifically the convexity adjustment I receive the error:
RuntimeError: 1st iteration: failed at 5th alive instrument, pillar March 17th, 2026, maturity March 17th, 2026, reference date September 13th, 2024: root not bracketed: f[-1,1] -> [1.670495e+01,2.187378e+02]
Note that I have no issues with getting my aonia curve.
Thanks in advance for your help with these issues.
My complete code is as follows: import QuantLib as ql import refinitiv.data as rd import os import matplotlib.pyplot as plt from matplotlib.ticker import PercentFormatter
today = ql.Date(11, ql.September, 2024) ql.Settings.instance().evaluationDate = today
os.environ["RD_LIB_CONFIG_PATH"] = "./Configuration" rd.open_session()
depo_data = rd.get_data(universe = ["AUDOND=", "AUDSND=", "AUDTND=", "AUDSWD=", "AUD2WD=","AUD3WD=", "AUD3MD="], fields = "MID_PRICE")
fut_data = rd.get_data(universe= ["YBAH5", "YBAM5", "YBAU5", "YBAZ5", "YBAH6", "YBAM6", "YBAU6", "YBAZ6"], fields = ["BID", "CONVX_BIAS", "EXPIR_DATE"])
irs_data = rd.get_data(universe=["AUDQM3AB1Y=", "AUDQM3AB2Y=", "AUDQM3AB3Y=", "AUDQM3AB4Y=", "AUDQM3AB5Y=", "AUDQM3AB7Y=", "AUDQM3AB10Y="], fields = "MID_PRICE")
rd.close_session()
bbsw_helpers = []
bbsw_helpers = [ ql.DepositRateHelper( ql.QuoteHandle(ql.SimpleQuote(depo_data.loc[depo_data['Instrument']=='AUD3MD=', 'MID_PRICE'].values[0] / 100)), ql.Period(3, ql.Months), 3, ql.Australia(), ql.Following, False, ql.Actual360(), ) ]
bbsw3m = ql.Bbsw3M()
bbsw_helpers += [ ql.FuturesRateHelper( ql.QuoteHandle( ql.SimpleQuote( fut_data.loc[fut_data['Instrument'] == inst, 'BID'].values[0] ) ), start_date, bbsw3m, ql.QuoteHandle(fut_data.loc[fut_data['Instrument'] == inst, 'CONVX_BIAS'].values[0]), ql.Futures.IMM ) for inst, start_date in [ ("YBAH5", ql.Date(19, ql.March, 2025)), ("YBAM5", ql.Date(18, ql.June, 2025)), ("YBAU5", ql.Date(17, ql.September, 2025)), ("YBAZ5", ql.Date(17, ql.December, 2025)), ("YBAH6", ql.Date(18, ql.March, 2026)), ("YBAM6", ql.Date(17, ql.June, 2026)), ("YBAU6", ql.Date(16, ql.September, 2026)), ("YBAZ6", ql.Date(16, ql.December,2026)) ] ]
discount_curve = ql.RelinkableYieldTermStructureHandle() discount_curve.linkTo(aonia_curve)
bbsw_helpers += [ ql.SwapRateHelper( ql.QuoteHandle(ql.SimpleQuote(3.516/100)), ql.Period(5, ql.Years), ql.Australia(), ql.Annual, ql.Following, ql.Actual365(), bbsw3m, ql.QuoteHandle() ql.Period(0, Days), discount_curve) ]
bbsw3m_curve = ql.PiecewiseConvexMonotoneForward( 2, ql.Australia(), bbsw_helpers, ql.Actual365Fixed() ) bbsw3m_curve.enableExtrapolation()
today = bbsw3m_curve.referenceDate() end = today + ql.Period(60, ql.Years) bbsw_dates = [ ql.Date(serial) for serial in range(today.serialNumber(), end.serialNumber() + 1)] bbsw_rates = [ bbsw3m_curve.forwardRate( d, bbsw3m.maturityDate(d), ql.Actual360(), ql.Simple ).rate() for d in bbsw_dates ]
ax = plt.figure(figsize=(9, 6)).add_subplot(1, 1, 1) ax.axhline(0.0, linewidth=1, color="black") ax.set_xlim(min(bbsw_dates).to_date(), max(bbsw_dates).to_date()) ax.yaxis.set_major_formatter(PercentFormatter(1.0)) ax.plot_date([d.to_date() for d in bbsw_dates], bbsw_rates, "-")
plt.xlabel('Date') plt.ylabel('Rate') plt.title("BBSW Curve") plt.grid(True) plt.show()
For reference, the data I have obtained for deposits, futures and swaps are as follows:
Deposits Instrument MID_PRICE 0 AUDOND= 4.3 1 AUDSND= 4.25 2 AUDTND= 4.3 3 AUDSWD= 4.35 4 AUD2WD= 4.58 5 AUD3WD= 4.42 6 AUD3MD= 4.49
Futures Instrument BID CONVX_BIAS EXPIR_DATE 0 YBAH5 96.19 0.262 2025-03-13 1 YBAM5 96.48 0.482 2025-06-12 2 YBAU5 96.63 0.758 2025-09-11 3 YBAZ5 96.73 1.086 2025-12-11 4 YBAH6 96.8 1.464 2026-03-12 5 YBAM6 96.83 1.889 2026-06-11 6 YBAU6 96.84 2.359 2026-09-10 7 YBAZ6 96.81 2.871 2026-12-10
SWAPS Instrument MID_PRICE 0 AUDQM3AB1Y= 3.987 1 AUDQM3AB2Y= 3.621 2 AUDQM3AB3Y= 3.492 3 AUDQM3AB4Y= 3.475 4 AUDQM3AB5Y= 3.516 5 AUDQM3AB7Y= 3.651 6 AUDQM3AB10Y= 3.833