2
$\begingroup$

I am using Quantlib's FittedBondDiscountCurve in Python 3.7 and setting MaxIterations to 0, and giving a guess_solution, which then turns the routine into an evaluator for the parametric form I choose, according to the documentation.

The problem is that while an optimized spline will allow me to produce discount factors and NPVs for bonds, the evaluated spline will only crash (in pycharm) or return no value (in command line).

Am I calling the evaluated curve wrongly? Should I be treating it differently to the optimized curve?

I include some code below. Some is clearly copied from other YC building examples, but seems to be a minimal amount of code to produce the errors. I get the same problem no matter which parametric form I use.

Thank you in advance.

import numpy as np
import QuantLib as ql

today = ql.Date(8, 2, 2018)
ql.Settings.instance().evaluationDate = today

# Create some bonds

terminationDates = [ql.Date(4, 7, 2044), ql.Date(15, 2, 2028), ql.Date(14, 4, 2023)]
tenors = np.repeat(ql.Period(ql.Semiannual), 3)  
calenders = np.repeat(ql.UnitedStates(), 3)
termDateConvs = np.repeat(ql.Following, 3)
genRules = np.repeat(ql.DateGeneration.Backward, 3)
endOfMonths = np.repeat(False, 3)
firstDates = [ql.Date(27, 4, 2012), ql.Date(10, 1, 2018), ql.Date(2, 2, 2018)]

settlementDays = np.repeat(2, 3)
coupons = [0.025, 0.005, 0.0]
cleanPrices = [126.18, 98.18, 99.73]
faceValues = np.repeat(100.0, 3)
dayCounts = np.repeat(ql.ActualActual(), 3)

schedules = []
bonds = []
bondHelpers = []
for j in range(0, 3):
    schedules.append(ql.Schedule(firstDates[j], terminationDates[j], tenors[j], calenders[j],
                                 int(termDateConvs[j]), int(termDateConvs[j]), int(genRules[j]),
                                 bool(endOfMonths[j])))
    bonds.append(ql.FixedRateBond(int(settlementDays[j]), float(faceValues[j]), schedules[j],
                                  [float(coupons[j])], dayCounts[j]))
    bondHelpers.append(ql.BondHelper(ql.QuoteHandle(ql.SimpleQuote(float(cleanPrices[j]))), bonds[j]))


# Create Two yield Curves- one optimized, one with shifted parameters

curveSettlementDays = 2
curveCalendar = ql.UnitedStates()
curveDaycounter = ql.ActualActual()
curveFittingMethod = ql.ExponentialSplinesFitting()
tolerance = 1.0e-5
iterations = 10000
yieldCurveExp = ql.FittedBondDiscountCurve(curveSettlementDays, curveCalendar,\
 bondHelpers, curveDaycounter, curveFittingMethod, tolerance, iterations)
res = yieldCurveExp.fitResults()
solution = list(res.solution())
print('optimal solution = ', solution)
# Altered value
list_guess = solution.copy()
list_guess[-1] = list_guess[-1] * 1.01    # small shifts?
list_guess[-2] = list_guess[-2] * 1.01
list_guess[0] = list_guess[0] * 1.01
print('altered solution = ', list_guess)
guess = ql.Array(list_guess)
iterations = 0  # evaluate, don't fit

yieldCurveExp2 = ql.FittedBondDiscountCurve(curveSettlementDays, curveCalendar, bondHelpers,
             curveDaycounter, curveFittingMethod, tolerance, iterations, guess)  

YieldCurveHandle = ql.YieldTermStructureHandle(yieldCurveExp)
YieldCurveHandle2 = ql.YieldTermStructureHandle(yieldCurveExp2)
res  = yieldCurveExp.fitResults()
print(res.solution())   # optimization
res2 = yieldCurveExp2.fitResults()
print(res2.solution())  # = [ ]

ql_date = ql.Date(30,5,2018)
ql_date2 = ql.Date(30,6,2022)

print(yieldCurveExp.discount(ql_date2))  # 1.0040129
print(yieldCurveExp2.discount(ql_date2))   # Crash

# use it for pricing
bondEngine = ql.DiscountingBondEngine(YieldCurveHandle)
bondEngine2 = ql.DiscountingBondEngine(YieldCurveHandle2)

pricing_bond = bonds[0]

pricing_bond.setPricingEngine(bondEngine)
print('Fit model NPV =', pricing_bond.NPV())  # 137.2513
pricing_bond.setPricingEngine(bondEngine2)
print('Adjusted model NPV =', pricing_bond.NPV())  # Crash!

$\endgroup$
  • $\begingroup$ Your code is correct, but there's a bug in QuantLib's implementation. Please open an issue at <github.com/lballabio/QuantLib/issues>. $\endgroup$ – Luigi Ballabio Nov 8 at 16:44
  • $\begingroup$ Thanks. I’ve done so. $\endgroup$ – NBF Nov 8 at 18:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.