2
$\begingroup$

I'm trying to build a euro swap curve with real up to date data. I should say that examples provided in github work fine. as soon as I add the 5y swap, I got the following error :

RuntimeError: 1st iteration: failed at 14th alive instrument, maturity September 28th, 2020, reference date September 28th, 2015: root not bracketed: f[-1,1] -> [3.260558e-001,5.904525e-002]

edit (error with error lines) :

RuntimeError: void __thiscall QuantLib::IterativeBootstrap<class QuantLib::PiecewiseYieldCurve<struct QuantLib::ForwardRate,class QuantLib::BackwardFlat,class QuantLib::IterativeBootstrap> >::calculate(void) const: 
  d:\PycharmProjects\quantlib\QuantLib\ql/termstructures/iterativebootstrap.hpp(217): 
1st iteration: failed at 14th alive instrument, maturity September 28th, 2020, reference date September 28th, 2015: double __thiscall QuantLib::Solver1D<class QuantLib::Brent>::solve<class QuantLib::BootstrapError<class QuantLib::PiecewiseYieldCurve<struct QuantLib::ForwardRate,class QuantLib::BackwardFlat,class QuantLib::IterativeBootstrap> >>(const class QuantLib::BootstrapError<class QuantLib::PiecewiseYieldCurve<struct QuantLib::ForwardRate,class QuantLib::BackwardFlat,class QuantLib::IterativeBootstrap> > &,double,double,double,double) const: 
  d:\PycharmProjects\quantlib\QuantLib\ql/math/solver1d.hpp(202): 
root not bracketed: f[-1,1] -> [3.260558e-001,5.904525e-002]

I have to say that I get no error if I remove the 5y swap. I have QL_NEGATIVE_RATES in userconfig.hpp that isn't commented.

the piece of code I'm using is here.

thanks

import QuantLib as ql
import datetime

calendar = ql.TARGET()
settlementDays = 2
now = datetime.datetime.now()
today = calendar.adjust(ql.Date(now.day, now.month, now.year))
ql.Settings.instance().evaluationDate = today
settlementDate = calendar.advance(today, settlementDays, ql.Days)

# market quotes
deposits = {(1, ql.Weeks): -0.141,
            (1, ql.Months): -0.107,
            (2, ql.Months): -0.066,
            (3, ql.Months): -0.039,
            (6, ql.Months): 0.033,
            (9, ql.Months): 0.083,
            (12, ql.Months): 0.147}

futures = {ql.Date(16, 3, 2016): 100.045,
           ql.Date(15, 6, 2016): 100.055,
           ql.Date(21, 9, 2016): 100.06,
           ql.Date(21, 12, 2016): 100.055,
           ql.Date(15, 3, 2017): 100.04}

swaps = {(2, ql.Years): 0.0557,
         (3, ql.Years): 0.1275,
         (4, ql.Years): 0.2331,
         #(5, ql.Years): 0.3523
         }

# convert them to Quote objects
for n, unit in deposits.keys():
    deposits[(n, unit)] = ql.SimpleQuote(deposits[(n, unit)])
for d in futures.keys():
    futures[d] = ql.SimpleQuote(futures[d])
for n, unit in swaps.keys():
    swaps[(n, unit)] = ql.SimpleQuote(swaps[(n, unit)])

dayCounter = ql.Actual360()

depositHelpers = [
    ql.DepositRateHelper(ql.QuoteHandle(deposits[(n, unit)]), ql.Period(n, unit), settlementDays, calendar,
                         ql.ModifiedFollowing, False, dayCounter) for n, unit in sorted(deposits.iterkeys())]

dayCounter = ql.Actual360()

futuresHelpers = [
    ql.FuturesRateHelper(ql.QuoteHandle(futures[d]), d, 3, calendar, ql.ModifiedFollowing, True, dayCounter,
                         ql.QuoteHandle(ql.SimpleQuote(0.0))) for d in sorted(futures.keys())]

settlementDays = 2
fixedLegFrequency = ql.Annual
fixedLegTenor = ql.Period(1, ql.Years)
fixedLegAdjustment = ql.Unadjusted
fixedLegDayCounter = ql.Thirty360()
floatingLegFrequency = ql.Semiannual
floatingLegTenor = ql.Period(6, ql.Months)
floatingLegAdjustment = ql.ModifiedFollowing

swapHelpers = [ql.SwapRateHelper(ql.QuoteHandle(swaps[(n, unit)]), ql.Period(n, unit), calendar, fixedLegFrequency,
                                 fixedLegAdjustment, fixedLegDayCounter, ql.Euribor6M()) for n, unit in
               swaps.keys()]

# term structure handles

discountTermStructure = ql.RelinkableYieldTermStructureHandle()
forecastTermStructure = ql.RelinkableYieldTermStructureHandle()


def printHelper(x):
    print('{} | {}'.format(x.latestDate(), x.quote().value()))


def printH(t):
    print('\n======')
    print t
    for i in list(t):
        printHelper(i)

printH(depositHelpers)
printH(futuresHelpers)
printH(swapHelpers)

helpers = depositHelpers[:-2] + futuresHelpers + swapHelpers
printH(helpers)

depoFuturesSwapCurve = ql.PiecewiseFlatForward(settlementDate, helpers, ql.Actual360())

print depoFuturesSwapCurve.dates()

for c in depoFuturesSwapCurve.dates():
    print depoFuturesSwapCurve.discount(c)
$\endgroup$
5
  • $\begingroup$ I recompiled with error lines in order maye to get a better understanding, but I still fail on seeing why the bootstraping fails. $\endgroup$
    – euri10
    Sep 24, 2015 at 16:21
  • $\begingroup$ As @Luigi Ballabio's answer below points out, you REALLY shouldn't be building swap curves like this any more... Please read about modern multi-curve approaches to yield curve construction. $\endgroup$
    – Helin
    Sep 25, 2015 at 0:06
  • $\begingroup$ @haginile what do you mean more precisely by that? I only see an issue of "format" in Luigi answer but using the Android app. $\endgroup$
    – euri10
    Sep 25, 2015 at 3:17
  • $\begingroup$ I interpreted his comment that the "example is from a different era" to mean that the method you're using is outdated... After the financial crisis, the world has moved to OIS discounting. You should use LIBOR curves for cash flow projection, but OIS curve for discounting. Additionally, you shouldn't have 1m, 3m, 6m, etc. mixed up in a single curve, since they represent different risks. Simply put, 1m forward curve, 3m forward curve, etc. all have to be built as their own curves. $\endgroup$
    – Helin
    Sep 25, 2015 at 4:31
  • $\begingroup$ oO yes, plan is for the OIS curve to use Eonia ON, TN, SN, then spot Eonia OIS up to 2y, then infer Eonia OIS from 6m Euribor swaps using the quoted basis. hopefully that will make sense :) $\endgroup$
    – euri10
    Sep 25, 2015 at 6:49

1 Answer 1

6
$\begingroup$

You're not the first to trip on this, and unfortunately the fact that the provided example is from a different era doesn't help.

Quite simply, you're not writing rates correctly. The 5-years swap rate, 0.3523%, must be written in decimal form as 0.003523. The same goes for the deposit rates.

As your code is now, you're writing that the 4-years rate is 23.31% and the 5-years rate is 35.23%, and the bootstrap code fails to find a solution that accounts for the extreme variation.

Writing the rates correctly should allow you to bootstrap the curve as expected.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.