Skip to content
All library documents

Diagnosing QuantLib Basis-Swap Curve Bootstrap Failures

Article Quant Q&A · Author: finleymahoney

Summary

The document describes difficulties bootstrapping a one-month EURIBOR curve from deposits and six-month swap or basis quotes with QuantLib. The reported failure occurs at a long-dated instrument with a root that cannot be bracketed. The accepted answer points to two practical checks: explicitly set QuantLib’s evaluation date to the intended reference date, and use log-cubic discount interpolation to preserve monotonicity where spline-cubic interpolation may produce problematic discount factors.

The author also reports that switching interpolation allowed the calculation to run, but the resulting curve differed substantially from a provider’s curve when using the Ibor-Ibor basis helper. A manual construction using swap helpers and basis adjustments reportedly matched more closely. The document includes extensive illustrative code and market quotes, but it does not resolve the helper discrepancy or establish that the manual method is generally correct. Curve conventions, quote units, helper arguments, and interpolation choices remain important diagnostic points.

Key ideas

  • Set the library evaluation date explicitly so it matches the intended curve reference date.
  • Log-cubic discount interpolation is suggested to preserve monotonicity in discount factors.
  • A bootstrap root-bracketing failure can arise while solving for a distant instrument’s curve node.
  • The reported basis-helper curve differed from a provider’s result, while a manual basis adjustment reportedly aligned more closely.
  • The document does not establish the cause of that discrepancy or validate the manual construction generally.

Tags

Full text
# QuantLib issue with bootstrapping using IborIborBasisSwapRateHelper


# QuantLib issue with bootstrapping using IborIborBasisSwapRateHelper












I have been trying to bootstrap a 1M EURIBOR curve using 1M deposit rates and 6M swap rates, applying 6M->1M Basis using the IborIborBasisSwapRateHelper class in QuantLib.

The 6M curve bootstraps fine but when I get to the 1M curve I run into the error:

> RuntimeError: 1st iteration: failed at 18th alive instrument, pillar January 30th, 2051, maturity January 30th, 2051, reference date January 27th, 2026: root not bracketed: f[0.00351779,90.0242] -> [-1.979117e-01,-3.780997e-01]

I am working in C++ but, to simplify things, below is a verbose python mock-up of what I am doing which exhibits the same error. I know I should be using ESTR as the discount curve in both bootstraps but I have tried that and it did not help so to keep things simple I have not included it in the mock-up.

```
import QuantLib as ql
reference_date = ql.Date(21, ql.October, 2025)

#EURIBOR 6M
eur6m_helpers = []
eur6m_calendar = ql.TARGET()
eur6m_convention = ql.ModifiedFollowing
eur6m_settle_days = 0
eur6m_curve_dcb = ql.Actual360()

eur6m_depo_eom = True
eur6m_depo_dcb = ql.Actual360()
eur6m_depo_tenors = [ql.Period(1,ql.Days), ql.Period(2,ql.Days), ql.Period(1,ql.Weeks), ql.Period(6,ql.Months)]
eur6m_depo_fixing_days = [0, 0, 2, 2]
eur6m_depo_rates = [2.0, 2.0, 1.924, 2.113]

eur6m_fra_eom = True
eur6m_fra_dcb = ql.Actual360()
eur6m_fra_fixing_days = 2
eur6m_fra_period_start = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
eur6m_fra_period_end = [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
eur6m_fra_rates = [2.085, 2.065, 2.043, 2.021, 2.003, 1.989, 1.9805, 1.9725, 1.985, 1.9705, 1.9745, 1.984]

eur6m_swap_eom = True
eur6m_swap_settle_days = 2
eur6m_swap_fixed_freq = ql.Annual
eur6m_swap_dcb = ql.Thirty360(ql.Thirty360.European)
eur6m_swap_float_index = ql.Euribor6M()
eur6m_swap_tenors = [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)]
eur6m_swap_rates = [2.069, 2.129, 2.20, 2.265, 2.335, 2.40, 2.465, 2.5255, 2.5855, 2.681, 2.7825, 2.8415, 2.8385, 2.825]

i = 0
for rate in eur6m_depo_rates:
    eur6m_helpers.append(ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), eur6m_depo_tenors[i], eur6m_depo_fixing_days[i], eur6m_calendar, eur6m_convention, eur6m_depo_eom, eur6m_depo_dcb))
    i += 1

i = 0
for rate in eur6m_fra_rates:
    eur6m_helpers.append(ql.FraRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), eur6m_fra_period_start[i], eur6m_fra_period_end[i], eur6m_fra_fixing_days, eur6m_calendar, eur6m_convention, eur6m_fra_eom, eur6m_fra_dcb))
    i += 1

i = 0
for rate in eur6m_swap_rates:
    eur6m_helpers.append(ql.SwapRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), eur6m_swap_tenors[i], eur6m_calendar, eur6m_swap_fixed_freq, eur6m_convention, eur6m_swap_dcb, eur6m_swap_float_index, ql.QuoteHandle(), ql.Period(eur6m_swap_settle_days, ql.Days)))
    i += 1

eur6m_curve = ql.PiecewiseSplineCubicDiscount(eur6m_settle_days, eur6m_calendar, eur6m_helpers, eur6m_curve_dcb)
eur6m_curve.enableExtrapolation()

nodes = []
dates = []
dfs = []
nodes = eur6m_curve.nodes()
for (date, df) in nodes:
    dates.append(date)
    dfs.append(df)

dc = ql.NaturalLogCubicDiscountCurve(dates, dfs, eur6m_curve_dcb, eur6m_calendar)
dc = ql.YieldTermStructureHandle(dc)

#EURIBOR 6M -> 1M Basis
eur1m_helpers = []

eur1m_depo_eom = True
eur1m_depo_dcb = ql.Actual360()
eur1m_depo_tenors = [ql.Period(1,ql.Days), ql.Period(2,ql.Days), ql.Period(1,ql.Weeks), ql.Period(6,ql.Months)]
eur1m_depo_fixing_days = [0, 0, 2, 2]
eur1m_depo_rates = [2.0, 2.0, 1.924, 1.919]

eur1m_basis_eom = True
eur1m_basis_settle_days = 2
eur1m_basis_quote_index = ql.Euribor1M()
eur1m_basis_base_index = ql.Euribor6M(ql.YieldTermStructureHandle(eur6m_curve))
eur1m_basis_tenors = [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)]
eur1m_basis_spreads = [-20.289, -19.136, -18.564, -17.574, -16.828, -15.465, -14.881, -14.061, -13.152, -12.239, -10.447, -7.265, -4.048, -1.905, -0.65]

i = 0
for rate in eur1m_depo_rates:
    eur1m_helpers.append(ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), eur1m_depo_tenors[i], eur1m_depo_fixing_days[i], eur6m_calendar, eur6m_convention, eur1m_depo_eom, eur1m_depo_dcb))
    i += 1

i = 0
for spread in eur1m_basis_spreads:
    eur1m_helpers.append(ql.IborIborBasisSwapRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/10000.0)), eur1m_basis_tenors[i], eur1m_basis_settle_days, eur6m_calendar, eur6m_convention, eur1m_basis_eom, eur1m_basis_base_index, eur1m_basis_quote_index, dc, False))
    i += 1

eur1m_curve = ql.PiecewiseSplineCubicDiscount(eur6m_settle_days, eur6m_calendar, eur1m_helpers, eur6m_curve_dcb)
eur1m_curve.enableExtrapolation()

nodes = []
dates = []
dfs = []
nodes = eur1m_curve.nodes()
```

Could this error be driven by the market data I'm feeding in? Let me know if anything jumps out at you or if you've fixed this sort of thing before.

EDIT

Thanks to K. Roman I have updated the code to use `ql.PiecewiseLogCubicDiscount` for interpolation. This allows the code to run but I get results pretty far off what I was expecting.

I have plugged in data from a different provider, from which I have known good bootstrap results to compare against. When using the `ql.IborIborBasisSwapRateHelper` I get results that deviate significantly from the providers own bootstrap results. When just using the 1M deposit rates along with the 6M swap quotes using `ql.SwapRateHelper` and adding the basis manually I get pretty much bang on the providers own results. I have also brought back using ESTR as the discount curve.

Result Table

Using IborIborBasisSwapRateHelper (DC = ESTR)

```
import QuantLib as ql

ql.Settings.instance().evaluationDate = ql.Date(21, ql.October, 2025)

eur6m_calendar = ql.TARGET()
eur6m_convention = ql.ModifiedFollowing
eur6m_settle_days = 0
eur6m_curve_dcb = ql.Actual360()

#ESTR
estr_helpers = []
estr_eom = True
estr_settle_days = 2
estr_pay_freq = ql.Annual
estr_float_index = ql.Estr()
estr_ois_tenors = [ql.Period(1,ql.Days), ql.Period(2,ql.Days),ql.Period(1,ql.Weeks), ql.Period(2,ql.Weeks),  ql.Period(3,ql.Weeks), ql.Period(1,ql.Months), ql.Period(2,ql.Months), ql.Period(3,ql.Months), ql.Period(4,ql.Months), ql.Period(5,ql.Months), 
                   ql.Period(6,ql.Months),ql.Period(7,ql.Months),ql.Period(8,ql.Months),ql.Period(9,ql.Months),ql.Period(10,ql.Months),ql.Period(11,ql.Months),ql.Period(1,ql.Years),ql.Period(15,ql.Months),ql.Period(18,ql.Months),ql.Period(21,ql.Months),
                   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(11,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),ql.Period(40,ql.Years),ql.Period(50,ql.Years)]
estr_ois_rates = [1.92700, 1.92715, 1.92750, 1.92630, 1.92520, 1.92510,1.92580,1.91600,1.90990, 1.90400,1.89100,1.87850, 1.86900,1.85900,1.85000,1.84300,1.83700,1.81900,1.81300,1.81600,1.82630,1.88900,1.96880,2.04810,2.12340,2.19530,
                  2.26450, 2.33230, 2.39380, 2.45040, 2.50330, 2.62060, 2.70340, 2.71350, 2.70690, 2.67680,2.62690 ]

i = 0
for rate in estr_ois_rates:
    estr_helpers.append(ql.OISRateHelper(estr_settle_days, estr_ois_tenors[i], ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), estr_float_index, paymentFrequency =estr_pay_freq, endOfMonth=estr_eom))
    i += 1

estr_curve = ql.PiecewiseLogCubicDiscount(estr_settle_days, eur6m_calendar, estr_helpers, eur6m_curve_dcb)
estr_curve.enableExtrapolation()

nodes = []
dates = []
dfs = []
nodes = estr_curve.nodes()
for (date, df) in nodes:
    dates.append(date)
    dfs.append(df)

dc = ql.NaturalLogCubicDiscountCurve(dates, dfs, eur6m_curve_dcb, eur6m_calendar)
dc = ql.YieldTermStructureHandle(dc)

# EURIBOR 6M (ICE)
eur6m_helpers = []

eur6m_depo_eom = True
eur6m_depo_dcb = ql.Actual360()
eur6m_depo_tenors = [ql.Period(1,ql.Days), ql.Period(2,ql.Days), ql.Period(1,ql.Weeks), ql.Period(6,ql.Months)]
eur6m_depo_fixing_days = [0, 0, 2, 2]
eur6m_depo_rates = [1.82000, 1.88000, 1.90100, 2.11000]

eur6m_fra_eom = True
eur6m_fra_dcb = ql.Actual360()
eur6m_fra_fixing_days = 2
eur6m_fra_period_start = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
eur6m_fra_period_end = [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
eur6m_fra_rates = [2.08700,2.06600, 2.04300, 2.02100,2.00200, 1.99100, 1.98000, 1.97200, 1.97000, 1.97000, 1.97300, 1.98200]

eur6m_swap_eom = True
eur6m_swap_settle_days = 0
eur6m_swap_fixed_freq = ql.Annual
eur6m_swap_dcb = ql.Thirty360(ql.Thirty360.European)
eur6m_swap_float_index = ql.Euribor6M()
eur6m_swap_tenors = [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(11,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)]
eur6m_swap_rates = [2.07040, 2.13120,2.20270, 2.27230, 2.34020, 2.40530, 2.46840, 2.52740, 2.58140, 2.63200, 2.67770, 2.77880, 2.84300, 2.84020, 2.82420]

i = 0
for rate in eur6m_depo_rates:
    eur6m_helpers.append(ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), eur6m_depo_tenors[i], eur6m_depo_fixing_days[i], eur6m_calendar, eur6m_convention, eur6m_depo_eom, eur6m_depo_dcb))
    i += 1

i = 0
for rate in eur6m_fra_rates:
    eur6m_helpers.append(ql.FraRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), eur6m_fra_period_start[i], eur6m_fra_period_end[i], eur6m_fra_fixing_days, eur6m_calendar, eur6m_convention, eur6m_fra_eom, eur6m_fra_dcb))
    i += 1

i = 0
for rate in eur6m_swap_rates:
    eur6m_helpers.append(ql.SwapRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), eur6m_swap_tenors[i], eur6m_calendar, eur6m_swap_fixed_freq, eur6m_convention, eur6m_swap_dcb, eur6m_swap_float_index, ql.QuoteHandle(), ql.Period(eur6m_swap_settle_days, ql.Days), dc))
    i += 1

eur6m_curve = ql.PiecewiseLogCubicDiscount(eur6m_settle_days, eur6m_calendar, eur6m_helpers, eur6m_curve_dcb)
eur6m_curve.enableExtrapolation()

#EURIBOR 6M -> 1M Basis
eur1m_helpers = []

eur1m_depo_eom = True
eur1m_depo_dcb = ql.Actual360()
eur1m_depo_tenors = [ql.Period(1,ql.Days), ql.Period(2,ql.Days), ql.Period(1,ql.Weeks), ql.Period(1,ql.Months)]
eur1m_depo_fixing_days = [0, 0, 2, 2]
eur1m_depo_rates = [1.82, 1.88, 1.901, 1.904]

eur1m_basis_eom = True
eur1m_basis_settle_days = 2
eur1m_basis_quote_index = ql.Euribor1M()
eur1m_basis_base_index = ql.Euribor6M(ql.YieldTermStructureHandle(eur6m_curve))
eur1m_basis_tenors = [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(11,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)]
eur1m_basis_spreads = [-20.559, -19.361, -18.463, -17.764, -16.866, -15.868, -15.070, -14.172, -13.174, -12.275, -11.277, -10.279, -7.086,-3.792, -1.796, -0.499]

i = 0
for rate in eur1m_depo_rates:
    eur1m_helpers.append(ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), eur1m_depo_tenors[i], eur1m_depo_fixing_days[i], eur6m_calendar, eur6m_convention, eur1m_depo_eom, eur1m_depo_dcb))
    i += 1

i = 0
for spread in eur1m_basis_spreads:
    eur1m_helpers.append(ql.IborIborBasisSwapRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/10000.0)), eur1m_basis_tenors[i], eur1m_basis_settle_days, eur6m_calendar, eur6m_convention, eur1m_basis_eom, eur1m_basis_base_index, eur1m_basis_quote_index, dc, False))
    i += 1

eur1m_curve = ql.PiecewiseLogCubicDiscount(eur6m_settle_days, eur6m_calendar, eur1m_helpers, eur6m_curve_dcb)
eur1m_curve.enableExtrapolation()
nodes = eur1m_curve.nodes()
```

Using SwapRateHelper + Basis (DC = ESTR)

```
import QuantLib as ql

ql.Settings.instance().evaluationDate = ql.Date(21, ql.October, 2025)

eur6m_calendar = ql.TARGET()
eur6m_convention = ql.ModifiedFollowing
eur6m_settle_days = 0
eur6m_curve_dcb = ql.Actual360()

#ESTR
estr_helpers = []
estr_eom = True
estr_settle_days = 2
estr_pay_freq = ql.Annual
estr_float_index = ql.Estr()
estr_ois_tenors = [ql.Period(1,ql.Days), ql.Period(2,ql.Days),ql.Period(1,ql.Weeks), ql.Period(2,ql.Weeks),  ql.Period(3,ql.Weeks), ql.Period(1,ql.Months), ql.Period(2,ql.Months), ql.Period(3,ql.Months), ql.Period(4,ql.Months), ql.Period(5,ql.Months), 
                   ql.Period(6,ql.Months),ql.Period(7,ql.Months),ql.Period(8,ql.Months),ql.Period(9,ql.Months),ql.Period(10,ql.Months),ql.Period(11,ql.Months),ql.Period(1,ql.Years),ql.Period(15,ql.Months),ql.Period(18,ql.Months),ql.Period(21,ql.Months),
                   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(11,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),ql.Period(40,ql.Years),ql.Period(50,ql.Years)]
estr_ois_rates = [1.92700, 1.92715, 1.92750, 1.92630, 1.92520, 1.92510,1.92580,1.91600,1.90990, 1.90400,1.89100,1.87850, 1.86900,1.85900,1.85000,1.84300,1.83700,1.81900,1.81300,1.81600,1.82630,1.88900,1.96880,2.04810,2.12340,2.19530,
                  2.26450, 2.33230, 2.39380, 2.45040, 2.50330, 2.62060, 2.70340, 2.71350, 2.70690, 2.67680,2.62690 ]

i = 0
for rate in estr_ois_rates:
    estr_helpers.append(ql.OISRateHelper(estr_settle_days, estr_ois_tenors[i], ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), estr_float_index, paymentFrequency =estr_pay_freq, endOfMonth=estr_eom))
    i += 1

estr_curve = ql.PiecewiseLogCubicDiscount(estr_settle_days, eur6m_calendar, estr_helpers, eur6m_curve_dcb)
estr_curve.enableExtrapolation()

nodes = []
dates = []
dfs = []
nodes = estr_curve.nodes()
for (date, df) in nodes:
    dates.append(date)
    dfs.append(df)

dc = ql.NaturalLogCubicDiscountCurve(dates, dfs, eur6m_curve_dcb, eur6m_calendar)
dc = ql.YieldTermStructureHandle(dc)

# EURIBOR 6M + 1M Basis
eur6m_helpers = []

eur6m_depo_eom = True
eur6m_depo_dcb = ql.Actual360()
eur6m_depo_tenors = [ql.Period(1,ql.Days), ql.Period(2,ql.Days), ql.Period(1,ql.Weeks), ql.Period(1,ql.Months)]
eur6m_depo_fixing_days = [0, 0, 2, 2]
eur6m_depo_rates = [1.82, 1.88, 1.901, 1.904]

eur6m_swap_eom = True
eur6m_swap_settle_days = 0
eur6m_swap_fixed_freq = ql.Annual
eur6m_swap_dcb = ql.Thirty360(ql.Thirty360.European)
eur6m_swap_float_index = ql.Euribor6M()
eur6m_swap_tenors = [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(11,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)]
eur6m_swap_rates = [2.08381, 2.07040, 2.13120,2.20270, 2.27230, 2.34020, 2.40530, 2.46840, 2.52740, 2.58140, 2.63200, 2.67770, 2.77880, 2.84300, 2.84020, 2.82420]
eur1m_basis_tenors = [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(11,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)]
eur1m_basis_spreads = [-20.559, -19.361, -18.463, -17.764, -16.866, -15.868, -15.070, -14.172, -13.174, -12.275, -11.277, -10.279, -7.086,-3.792, -1.796, -0.499]

i = 0
for rate in eur6m_depo_rates:
    eur6m_helpers.append(ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(rate/100.0)), eur6m_depo_tenors[i], eur6m_depo_fixing_days[i], eur6m_calendar, eur6m_convention, eur6m_depo_eom, eur6m_depo_dcb))
    i += 1

i = 0
for rate in eur6m_swap_rates:
    eur6m_helpers.append(ql.SwapRateHelper(ql.QuoteHandle(ql.SimpleQuote((rate+(eur1m_basis_spreads[i]/100))/100.0)), eur6m_swap_tenors[i], eur6m_calendar, eur6m_swap_fixed_freq, eur6m_convention, eur6m_swap_dcb, eur6m_swap_float_index, ql.QuoteHandle(), ql.Period(eur6m_swap_settle_days, ql.Days), dc))
    i += 1

eur1m_curve = ql.PiecewiseLogCubicDiscount(eur6m_settle_days, eur6m_calendar, eur6m_helpers, eur6m_curve_dcb)
eur1m_curve.enableExtrapolation()
nodes = eur1m_curve.nodes()
```

## Answer by K. Roman (score 2)

https://quant.stackexchange.com/a/85421

- Use `ql.Settings.instance().evaluationDate = reference_date` else your `reference_date` is TOD = 27.01.2026

> RuntimeError: 1st iteration: failed at 18th alive instrument, pillar January 30th, 2051, maturity January 30th, 2051, reference date January 27th, 2026

- Use `ql.PiecewiseLogCubicDiscount` instead of `ql.PiecewiseSplineCubicDiscount` to save monotonicity

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.