Login  Register

Re: Question: small discrepancy in bond.cleanPrice() versus calling BondFunctions.cleanPrice() ?? help!

Posted by Peter Caspers-4 on Dec 06, 2016; 6:26pm
URL: http://quantlib.414.s1.nabble.com/Question-small-discrepancy-in-bond-cleanPrice-versus-calling-BondFunctions-cleanPrice-help-tp17898p17900.html

Hi Nick,

I am not sure but it might have to do with the way your flat forward
yield term structure and the yield-based bond functions measure the
time between the settlement date and the cashflow payment dates
effectively for the calculation of forward discount factors. The
former does

dayCounter(evalDate, cashflowDate) - dayCounter(evalDate, settlementDate)

whereas the latter

dayCounter(settlementDate, cashflowDate)

which might be different in your case for one or several cashflows. I
don't know the exact market convention for this but apparently the
latter is matching in your case and the former is slightly wrong.

You could check by replacing the day counter with another one for
which the two expressions above are identical for all cashflow dates
(of course the results get "wrong" then, but should be identical for
the different methods then).

Kind Regards
Peter


On 6 December 2016 at 19:39, Nick Pierce <[hidden email]> wrote:

> Hi
>
> I’m very new to Quantlib - about a week in (quite amazed so far!), but I
> have managed to get some bonds working in Python 2.7, using SWIG. QL v 1.9.
>
> I have set up a bond and the schedule is correct. When I calculate the clean
> price by inputting a yield (using BondFunctions.cleanPrice(…pass in yield)),
> this is correct (and yield from clean price), accrued is also correct and
> duration is fine as yield is not far out.
>
> However, when I attach a yield curve (flat forward) with the same yield, I
> get a fractionally different / price yield calc. Dates in the schedule are
> unadjusted, not modified following.
>
> Results:
>
> Clean Price Expected                     : 179.03
> Clean Price BondFunctions.cleanPrice()   : 179.03
> Clean Price bond.cleanPrice()            : 179.09
> Difference                               : 0.0626431535518
>
> Yield Expected                           : -0.0145461
> Yield BondFunctions.BondYield()          : -0.0145461
> Yield bond.bondYield()                   : -0.01455624
> Difference                               : 1.01382016107e-05
>
> Duration Expected                        : 34.52
> Duration BondFunctions.duration()        : 34.52
> Accrued Expected                         : 0.0483425414365
> Accrued BondFunctions.accruedAmount()    : 0.0483425414365
> Accrued bond.accruedAmount()             : 0.0483425414365
> Program ended with exit code: 0
>
> As you can see the calculated clean price from bond.cleanPrice() is 6 cents
> different (incorrect)..and it’s been driving me mad!! The yield is different
> from the 5th decimal place.
>
> This is a real bond and the input numbers have been verified using a manual
> calc in excel, they match the officially published numbers from the UK debt
> management office (negative yield
>  is the real yield for an inflation linked gilt, i.e. the quote of 179.03 is
> the market quote (clean) for the UKTI 52’s, before the index ratio is
> applied).
>
> In this example the price is the closing price for 30th Nov and settlement
> date is 1st Dec, 2016.
>
> If anyone can point out where I have gone wrong it would be much
> appreciated.
>
> Code is below.
>
> Many thanks
>
> Nick
>
> import QuantLib as ql
> import datetime as dt
> calendar = ql.UnitedKingdom()
> coupons=[0.0025]
> exCouponPeriod=ql.Period(6,ql.Days)
> calendarCoupon=ql.UnitedKingdom()
> faceValue=100
> businessConvention = ql.Unadjusted
> businessConventionCoupon=ql.Unadjusted
>
> today = ql.Date(30,11,2016)
> evaluationDate = calendar.adjust(today)
> issue_date = calendar.advance(evaluationDate,-1, ql.Years)
> maturity_date = ql.Date(22,3,2052)
>
> settlementDays=1
> settlementDate=today+1
> dayCount=ql.ActualActual(ql.ActualActual.ISMA)
>
>
> ql.Settings.instance().setEvaluationDate(evaluationDate)
>
> #input values to be checked
> inputYield=-0.014546100
> inputCleanPrice=179.03
> inputDuration=34.52
> inputAccrued=0.0483425414365
>
>
> #create schedule
> fixedSchedule =
> ql.Schedule(issue_date,maturity_date,ql.Period(ql.Semiannual),calendar,ql.Unadjusted,ql.Unadjusted,ql.DateGeneration.Backward,False)
>
> #create bond
> fixed_rate_bond =
> ql.FixedRateBond(settlementDays,faceValue,fixedSchedule,coupons,dayCount,businessConvention,100,issue_date,calendar,exCouponPeriod,calendarCoupon,businessConventionCoupon,False)
>
> #curve
> ts_curve=ql.FlatForward(evaluationDate, inputYield, dayCount, ql.Compounded,
> ql.Semiannual)
>
> #curve handle
> ts_handle = ql.YieldTermStructureHandle(ts_curve)
>
> #create bond engine
> bond_engine = ql.DiscountingBondEngine(ts_handle)#set bond engine
>
> #set pricing engine
> fixed_rate_bond.setPricingEngine(bond_engine)
>
> #calculate yield from clean price
> #calculations using BondFunctions
> bf_gry=ql.BondFunctions.bondYield(fixed_rate_bond,inputCleanPrice,dayCount,ql.Compounded,ql.Semiannual,settlementDate)
> bf_cp=ql.BondFunctions.cleanPrice(fixed_rate_bond,bf_gry,dayCount,ql.Compounded,ql.Semiannual,settlementDate)
> bf_ai=ql.BondFunctions.accruedAmount(fixed_rate_bond,settlementDate)
> bf_md=ql.BondFunctions.duration(fixed_rate_bond,bf_gry,dayCount,ql.Compounded,ql.Semiannual,ql.Duration.Modified,settlementDate)
>
> #Calculations using bond
> b_gry=fixed_rate_bond.bondYield(dayCount,ql.Compounded,ql.Semiannual)
> b_cp=fixed_rate_bond.cleanPrice()
> b_ai=fixed_rate_bond.accruedAmount()
>
> print "Clean Price Expected                     :",inputCleanPrice
> print "Clean Price BondFunctions.cleanPrice()   :",round(bf_cp,2)
> print "Clean Price bond.cleanPrice()            :",round(b_cp,2)
> print "Difference                               :",b_cp-bf_cp
> print ""
> print "Yield Expected                           :",round(inputYield,8)
> print "Yield BondFunctions.BondYield()          :",round(bf_gry,8)
> print "Yield bond.bondYield()                   :",round(b_gry,8)
> print "Difference                               :",bf_gry-b_gry
> print ""
>
> print "Duration Expected                        :",inputDuration
> print "Duration BondFunctions.duration()        :",round(bf_md,2)
>
> print "Accrued Expected                         :", inputAccrued
> print "Accrued BondFunctions.accruedAmount()    :", bf_ai
> print "Accrued bond.accruedAmount()             :", b_ai
>
> ------------------------------------------------------------------------------
> Developer Access Program for Intel Xeon Phi Processors
> Access to Intel Xeon Phi processor-based developer platforms.
> With one year of Intel Parallel Studio XE.
> Training and support from Colfax.
> Order your platform today.http://sdm.link/xeonphi
> _______________________________________________
> QuantLib-users mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/quantlib-users
>

------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today.http://sdm.link/xeonphi
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users