I'm trying to implement a pricing model for fixed rate bonds with the code below.

import QuantLib as ql
import pandas as pd

todaysDate = ql.Date(31, 8, 2017)
ql.Settings.instance().evaluationDate = todaysDate

spotDates = [ql.Date(1,9,2017), ql.Date(5,9,2017), ql.Date(7,9,2017), ql.Date(14,9,2017),   ql.Date(21,9,2017), ql.Date(2,10,2017), ql.Date(31,10,2017), ql.Date(30,11,2017), ql.Date(2,1,2018), ql.Date(31,1,2018), ql.Date(28,2,2018), ql.Date(3,4,2018), ql.Date(30,4,2018)]
spotRates = [0.066682, 0.067199, 0.067502, 0.068526, 0.069462, 0.070742, 0.072984, 0.073566, 0.073174, 0.072844, 0.072610, 0.072467, 0.072366]

dayCount = ql.Actual365Fixed()
calendar = ql.SouthAfrica()
interpolation = ql.Linear()
compounding = ql.Compounded
compoundingFrequency = ql.Semiannual

spotCurve = ql.ZeroCurve(spotDates, spotRates, dayCount, calendar, 
interpolation, compounding, compoundingFrequency)
spotCurveHandle = ql.YieldTermStructureHandle(spotCurve)

issueDate = ql.Date(20, 4, 2009)
maturityDate = ql.Date(20, 4, 2018)
tenor = ql.Period(ql.Semiannual)
calendar = ql.SouthAfrica()
bussinessConvention = ql.Following
dateGeneration = ql.DateGeneration.Backward
monthEnd = False

schedule = ql.Schedule (issueDate, maturityDate, tenor, calendar, bussinessConvention, bussinessConvention, dateGeneration, monthEnd)

dayCount = ql.Actual365Fixed()
couponRate = 0.0925
coupons = [couponRate]

settlementDays = 3
faceValue = 100
fixedRateBond = ql.FixedRateBond(settlementDays, faceValue, schedule, coupons, dayCount)

bondEngine = ql.DiscountingBondEngine(spotCurveHandle)


for c in fixedRateBond.cashflows():
    print('%20s %12f' % (c.date(), c.amount()))

My cash flow schedule looks a bit strange, I would have expected values of 4.625.

October 20th, 2009     4.637671
April 20th, 2010       4.612329
October 20th, 2010     4.637671
April 20th, 2011       4.612329
October 20th, 2011     4.637671
April 20th, 2012       4.637671
October 22nd, 2012     4.688356
April 22nd, 2013       4.612329
October 21st, 2013     4.612329
April 22nd, 2014       4.637671
October 20th, 2014     4.586986
April 20th, 2015       4.612329
October 20th, 2015     4.637671
April 20th, 2016       4.637671
October 20th, 2016     4.637671
April 20th, 2017       4.612329
October 20th, 2017     4.637671
April 20th, 2018       4.612329
April 20th, 2018     100.000000

Model values produced are:

Actual/365 (Fixed) day counter
September 5th, 2017

The value I get for accrued interest is spot on with the values provided by our internal system, but the prices are a bit off. Clean price expectation is 100.81517 and Dirty price expectation is 104.31243

  • $\begingroup$ QuantLib can't be possibly wrong here. It's 100% correct. Either your internal system is wrong or your inputs are not consistent. Can you show a manual calculation why you think you should have 4.625? $\endgroup$ – SmallChess Oct 20 '17 at 13:01
  • 1
    $\begingroup$ It's correct, given the inputs. For instance, the calculation of the coupons is correct based on the Act/365 day count convention passed during constructions. If your coupons pay 4.625 in real life, it means they're probably using an Act/Act convention and you should pass the latter to the FixedRateBond constructor. $\endgroup$ – Luigi Ballabio Oct 21 '17 at 12:42
  • $\begingroup$ Okay, the coupon value being exact here is not the major concern, since my accrued interest amounts are exactly in line therefore my day count convention must be correct. My main concern would be why the clean price and all in price are not in line with my expectations. Is my use of the zero spot rate curve on the dates I've specified correct? $\endgroup$ – Gregmf90 Oct 23 '17 at 7:52
  • $\begingroup$ If the final coupon amounts are different from what you expect, the accrued amounts will eventually be wrong as well; the conventions might just happen to give the same result on today's date. You might want to try initializing the bond with a different day counter and see what happens to the price. $\endgroup$ – Luigi Ballabio Oct 24 '17 at 11:00
  • $\begingroup$ As for the zero-rate curve: the initialization and usage is correct, as far as syntax and semantics are concerned. You'll have to verify if your system actually uses linear interpolation and semiannually-compounded rates, as for the inputs. It would help if you could retrieve the discounts corresponding to each coupon. $\endgroup$ – Luigi Ballabio Oct 24 '17 at 11:00

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.