|
From: quantlib.user <qua...@gm...> - 2018-02-18 23:51:07
|
Hi;
I am trying to do basic priceToYield, duration and convexity calculations
for Inflation linked bonds using the python wrapper of QuantLib. However I
see that the results I get are not what one would expect.
We don't seem to be applying the inflation uplift to the market quoted
clean price of the linker.
Accrued interest seems to be getting the inflation uplift (but not the
correct one see below), as a result of this yield and dirty price which I
get are wrong.
I tried to test the code with baseCPI = 100 and all realized CPI = 100, to
mimic the nominal bond set up and it seems in this setting the results are
fine.
Another thing I observed while pricing for July 2017, I would expect it to
pick CPI's for April and May, linearly interpolate it and then compute the
ration, it seems the inflation uplift applied to the accrued interest is
linearly interpolated between June and July.
I would appreciate if someone could help me with the correct settings
required to get a inflation linked bond working uisng Quantlib.
import QuantLib as ql
import datetime as dt
def getFixings():
from_date = ql.Date(31, ql.January, 2010);
to_date = ql.Date(31, ql.January, 2018);
tenor = ql.Period(1, ql.Months)
calendar = ql.UnitedKingdom()
dayCounter = ql.ActualActual();
convention = ql.ModifiedFollowing
lag = 2
rpiSchedule = ql.Schedule(from_date, to_date, tenor, calendar,
convention, convention,
ql.DateGeneration.Backward, False)
cpiTS = ql.RelinkableZeroInflationTermStructureHandle()
inflationIndex = ql.UKRPI(False,cpiTS)
observationLag = ql.Period(lag, ql.Months)
fixData = [217.9, 219.2, 220.7, 222.8, 223.6, 224.1, 223.6, 224.5,
225.3, 225.8, 226.8, 228.4,
229, 231.3, 232.5, 234.4, 235.2, 235.2, 234.7, 236.1, 237.9, 238,
238.5, 239.4,
238, 239.9, 240.8, 242.5, 242.4, 241.8, 242.1, 243, 244.2, 245.6,
245.6, 246.8,
245.8, 247.6, 248.7, 249.5, 250, 249.7, 249.7, 251, 251.9, 251.9,
252.1, 253.4,
252.6, 254.2, 254.8, 255.7, 255.9, 256.3, 256, 257, 257.6, 257.7,
257.1, 257.5,
255.4, 256.7, 257.1, 258, 258.5, 258.9, 258.6, 259.8, 259.6,
259.5, 259.8, 260.6,
258.8, 260, 261.1, 261.4, 262.1, 263.1, 263.4, 264.4, 264.9,
264.8, 265.5, 267.1,
265.5, 268.4, 269.3, 270.6, 271.7, 272.3, 272.9, 274.7, 275.1,
275.3, 275.8, 278.1, 276]
dte_fixings=[dtes for dtes in rpiSchedule]
for i in range(0,len(fixData)):
inflationIndex.addFixing(rpiSchedule[i], fixData[i])
#I can play wiht making all = 100 and baseCPI = 100 to mimic nominal
#inflationIndex.addFixing(rpiSchedule[i], 100.0)
zciisData =[( ql.Date(1, ql.April, 2018), 0.0 ),
( ql.Date(25, ql.January, 2060), 0.0 )]
zeroSwapHelpers =
[ql.ZeroCouponInflationSwapHelper(rate/100,observationLag,
date, calendar, convention, dayCounter, inflationIndex) for
date,rate in zciisData]
yTS = ql.YieldTermStructureHandle(ql.FlatForward(evaluationDate, 0.0,
dayCounter))
# the derived inflation curve
jj=ql.PiecewiseZeroInflation(
evaluationDate, calendar, dayCounter,
observationLag,
inflationIndex.frequency(),
inflationIndex.interpolated(),
zciisData[0][1],
yTS, zeroSwapHelpers, 1.0e-12, ql.Linear())
cpiTS.linkTo(jj)
return inflationIndex
today = ql.Date(27,7,2017)
evaluationDate = today
ql.Settings.instance().evaluationDate = today
settlementDays = 1
cPrice = 188.37
dayCount = ql.Actual365Fixed()
calendar = ql.UnitedKingdom()
interpolation = ql.Linear()
compounding = ql.Compounded
compoundingFrequency = ql.Semiannual
tp1 = calendar.adjust(today + settlementDays )
inflationIndex = getFixings()
issueDate = ql.Date(30, 7, 2014)
maturityDate = ql.Date(22, 3, 2058)
baseCPI = 256.0
calendar = ql.UnitedKingdom()
dayCounter = ql.ActualActual();
convention = ql.ModifiedFollowing
lag = 3
observationLag = ql.Period(lag, ql.Months)
notional = 100.0
fixedRates = [0.125 / 100.0]
fixedDayCounter = ql.Actual365Fixed()
fixedPaymentConvention = ql.ModifiedFollowing
fixedPaymentCalendar = ql.UnitedKingdom()
contractObservationLag = ql.Period(lag, ql.Months)
observationInterpolation = ql.CPI.Flat
growthOnly = False
fixedSchedule = ql.Schedule(issueDate,
maturityDate,
ql.Period(ql.Semiannual),
fixedPaymentCalendar,
ql.Unadjusted,
ql.Unadjusted,
ql.DateGeneration.Backward,
False)
bond = ql.CPIBond(settlementDays,
notional,
growthOnly,
baseCPI,
contractObservationLag,
inflationIndex,
observationInterpolation,
fixedSchedule,
fixedRates,
fixedDayCounter,
fixedPaymentConvention)
cYield = ql.BondFunctions.bondYield(bond, cPrice,dayCount,ql.Simple,
ql.Annual,tp1)
rePrice = ql.BondFunctions.cleanPrice(bond,cYield,dayCount,ql.Simple,
ql.Annual,tp1)
dur = ql.BondFunctions.duration(bond,cYield,dayCount,ql.Simple, ql.Annual,
ql.Duration.Simple)
conv = ql.BondFunctions.convexity(bond,cYield,dayCount,ql.Simple, ql.Annual)
print(bond.cleanPrice(cYield,dayCount,ql.Simple, ql.Annual,tp1))
print(bond.dirtyPrice(cYield,dayCount,ql.Simple, ql.Annual,tp1))
print(cYield)
print(rePrice)
print(bond.accruedAmount())
print(bond.settlementDate())
print(ql.BondFunctions.accruedDays(bond))
##This is the actual yield
cYield1 = -0.01459583624097
print(bond.cleanPrice(cYield1,dayCount,ql.Simple, ql.Annual,tp1))
print(bond.dirtyPrice(cYield1,dayCount,ql.Simple, ql.Annual,tp1))
--
Sent from: http://quantlib.10058.n7.nabble.com/quantlib-users-f3.html
|