Second Fixing Different to Second Rate

classic Classic list List threaded Threaded
2 messages Options
KK
Reply | Threaded
Open this post in threaded view
|

Second Fixing Different to Second Rate

KK
Hi

Apologies for repost, but the last comment by Pascal was extremely helpful and made the problem easier to explain.

Is there any reason why when I cast the floating leg to coupons, I get a rate that is different from the second fixing. This code extracts all the elements of the calc - eg day count/period etc and the second fixing is listed as

0.0360560874576

while the rate used to calculate the second cashflow is

0.0360614343399

For what it is worth, the second number looks right if you bootstrap by hand.

basically index.fixing(floatingSchedule[1]) does not equal as_coupon(cashflow).rate()


from QuantLib import *
from datetime import date
def makeQLdatePydate(s_date):
    return date(s_date.year(),s_date.month(),s_date.dayOfMonth())

calendar = UnitedKingdom()
todaysDate = Date(7,January,2013);
Settings.instance().evaluationDate = todaysDate
settlementDate = Date(7,January,2013);

# market quotes
deposits = { (3,Months): 0.0363,
             (6,Months): 0.0353,
             (12,Months): 0.036,
             (18,Months): 0.036 }




for n,unit in deposits.keys():
    deposits[(n,unit)] = SimpleQuote(deposits[(n,unit)])


dayCounter = Actual365Fixed()
settlementDays = 0
depositHelpers = [ DepositRateHelper(QuoteHandle(deposits[(n,unit)]),
                                     Period(n,unit), settlementDays,
                                     calendar, ModifiedFollowing,
                                     False, dayCounter)
                   for n, unit in  deposits.keys()  ]



settlementDays = 0
#fixedLegFrequency = Semiannual
#fixedLegTenor = Period(6,Months)
#fixedLegAdjustment = Unadjusted
#fixedLegDayCounter = Actual365Fixed()

floatingLegFrequency = Semiannual
floatingLegTenor = Period(6,Months)
floatingLegAdjustment = ModifiedFollowing




discountTermStructure = RelinkableYieldTermStructureHandle()
forecastTermStructure = RelinkableYieldTermStructureHandle()


helpers = depositHelpers

depoSwapCurve = PiecewiseFlatForward(settlementDate, helpers,Actual365Fixed())


swapEngine = DiscountingSwapEngine(discountTermStructure)

discountTermStructure.linkTo(depoSwapCurve)
forecastTermStructure.linkTo(depoSwapCurve)



nominal=1000000
length = 1
maturity = calendar.advance(settlementDate,length,Years)

#
index = GBPLibor(floatingLegTenor,forecastTermStructure)

floatingLegDayCounter = index.dayCounter()


floatingSchedule = Schedule(settlementDate, maturity,
                            floatingLegTenor, calendar,
                            floatingLegAdjustment, floatingLegAdjustment,
                            DateGeneration.Backward, False)


nominals =[nominal for x in floatingSchedule]
 
   

floatingrates = IborLeg(nominals[:-1],floatingSchedule,index,dayCounter)


print "Reset for calculating second cashflow"
print index.fixing(floatingSchedule[1])
print "Start date for calculating second cashflow"
print floatingSchedule[1]
print "End date for calculating second cashflow"
print floatingSchedule[2]
print "Days"
print float((makeQLdatePydate(floatingSchedule[2])-makeQLdatePydate(floatingSchedule[1])).days)
print "Days/365"
print float((makeQLdatePydate(floatingSchedule[2])-makeQLdatePydate(floatingSchedule[1])).days)/365.0
print "Second Cashflow from floatingSchedule = nominal * rate * Days/365"
print nominal*index.fixing(floatingSchedule[1])* float((makeQLdatePydate(floatingSchedule[2])-makeQLdatePydate(floatingSchedule[1])).days)/365.0

print "Second cashflow from IborLeg and from simple bootstrapping"
print floatingrates[1].date(),floatingrates[1].amount()


for cashflow in floatingrates:
        coupon = as_coupon(cashflow)
        print "Date: " + str(coupon.date()) +", Amount: " + str(coupon.amount()) +    ", Accrual period: " + str(coupon.accrualPeriod())
        print "Date: " + str(coupon.date()) +", accrualStartDate: " + str(coupon.accrualStartDate()) +    ", accrualEndDate: " + str(coupon.accrualEndDate())
        print "Date: " + str(coupon.date()) +", rate: " + str(coupon.rate())
        print "Date: " + str(coupon.date()) +", nominal: " + str(coupon.nominal())
        print "Date: " + str(coupon.date()) +", referencePeriodStart: " + str(coupon.referencePeriodStart()) +    ", referencePeriodEnd: " + str(coupon.referencePeriodEnd())
        print "Date: " + str(coupon.date()) +", accrualDays: " + str(coupon.accrualDays())
Reply | Threaded
Open this post in threaded view
|

Re: Second Fixing Different to Second Rate

Luigi Ballabio
Hello,
    as a default, the library is using par coupons.  Starting from
where your script leaves off, try:

coupon = as_floating_rate_coupon(floatingrates[1])  # your second coupon.

print coupon.fixingDate()    # Date(8,7,2013)
print index.fixing(coupon.fixingDate())     # 0.0360560874576

The fixing above is calculated as the forward rate between:

startDate = index.valueDate(coupon.fixingDate())
endDate = index.maturityDate(startDate)
print startDate, endDate    # Date(8,7,2013), Date(8,1,2014)

and in fact,

forecast_curve = index.forwardingTermStructure()
print forecast_curve.forwardRate(startDate, endDate,
coupon.dayCounter(), Simple)  # 3.605609%, as above

However, the coupon calculates its rate at par: since the dates reset
on the 7th of the month, this means that it's the rate between

couponStart = coupon.accrualStartDate()
couponEnd = coupon.accrualEndDate()
print couponStart, couponEnd    # Date(8,7,2013), Date(7,1,2014) <-
one day earlier than endDate above

Lo and behold,

print forecast_curve.forwardRate(couponStart, couponEnd,
coupon.dayCounter(), Simple)  # 3.606143%

which equals

print coupon.rate()   # 0.0360614343399

If you want the coupon to use the actual index fixing, you'll have to
flip a compilation switch (see
<http://quantlib.org/reference/config.html> for instructions: look for
"indexed coupons") and recompile both QuantLib and QuantLib-Python.

Luigi






On Mon, Oct 6, 2014 at 7:17 PM, KK <[hidden email]> wrote:

> Hi
>
> Apologies for repost, but the last comment by Pascal was extremely helpful
> and made the problem easier to explain.
>
> Is there any reason why when I cast the floating leg to coupons, I get a
> rate that is different from the second fixing. This code extracts all the
> elements of the calc - eg day count/period etc and the second fixing is
> listed as
>
> 0.0360560874576
>
> while the rate used to calculate the second cashflow is
>
> 0.0360614343399
>
> For what it is worth, the second number looks right if you bootstrap by
> hand.
>
> basically index.fixing(floatingSchedule[1]) does not equal
> as_coupon(cashflow).rate()
>
>
> from QuantLib import *
> from datetime import date
> def makeQLdatePydate(s_date):
>     return date(s_date.year(),s_date.month(),s_date.dayOfMonth())
>
> calendar = UnitedKingdom()
> todaysDate = Date(7,January,2013);
> Settings.instance().evaluationDate = todaysDate
> settlementDate = Date(7,January,2013);
>
> # market quotes
> deposits = { (3,Months): 0.0363,
>              (6,Months): 0.0353,
>              (12,Months): 0.036,
>              (18,Months): 0.036 }
>
>
>
>
> for n,unit in deposits.keys():
>     deposits[(n,unit)] = SimpleQuote(deposits[(n,unit)])
>
>
> dayCounter = Actual365Fixed()
> settlementDays = 0
> depositHelpers = [ DepositRateHelper(QuoteHandle(deposits[(n,unit)]),
>                                      Period(n,unit), settlementDays,
>                                      calendar, ModifiedFollowing,
>                                      False, dayCounter)
>                    for n, unit in  deposits.keys()  ]
>
>
>
> settlementDays = 0
> #fixedLegFrequency = Semiannual
> #fixedLegTenor = Period(6,Months)
> #fixedLegAdjustment = Unadjusted
> #fixedLegDayCounter = Actual365Fixed()
>
> floatingLegFrequency = Semiannual
> floatingLegTenor = Period(6,Months)
> floatingLegAdjustment = ModifiedFollowing
>
>
>
>
> discountTermStructure = RelinkableYieldTermStructureHandle()
> forecastTermStructure = RelinkableYieldTermStructureHandle()
>
>
> helpers = depositHelpers
>
> depoSwapCurve = PiecewiseFlatForward(settlementDate,
> helpers,Actual365Fixed())
>
>
> swapEngine = DiscountingSwapEngine(discountTermStructure)
>
> discountTermStructure.linkTo(depoSwapCurve)
> forecastTermStructure.linkTo(depoSwapCurve)
>
>
>
> nominal=1000000
> length = 1
> maturity = calendar.advance(settlementDate,length,Years)
>
> #
> index = GBPLibor(floatingLegTenor,forecastTermStructure)
>
> floatingLegDayCounter = index.dayCounter()
>
>
> floatingSchedule = Schedule(settlementDate, maturity,
>                             floatingLegTenor, calendar,
>                             floatingLegAdjustment, floatingLegAdjustment,
>                             DateGeneration.Backward, False)
>
>
> nominals =[nominal for x in floatingSchedule]
>
>
>
> floatingrates = IborLeg(nominals[:-1],floatingSchedule,index,dayCounter)
>
>
> print "Reset for calculating second cashflow"
> print index.fixing(floatingSchedule[1])
> print "Start date for calculating second cashflow"
> print floatingSchedule[1]
> print "End date for calculating second cashflow"
> print floatingSchedule[2]
> print "Days"
> print
> float((makeQLdatePydate(floatingSchedule[2])-makeQLdatePydate(floatingSchedule[1])).days)
> print "Days/365"
> print
> float((makeQLdatePydate(floatingSchedule[2])-makeQLdatePydate(floatingSchedule[1])).days)/365.0
> print "Second Cashflow from floatingSchedule = nominal * rate * Days/365"
> print nominal*index.fixing(floatingSchedule[1])*
> float((makeQLdatePydate(floatingSchedule[2])-makeQLdatePydate(floatingSchedule[1])).days)/365.0
>
> print "Second cashflow from IborLeg and from simple bootstrapping"
> print floatingrates[1].date(),floatingrates[1].amount()
>
>
> for cashflow in floatingrates:
>         coupon = as_coupon(cashflow)
>         print "Date: " + str(coupon.date()) +", Amount: " +
> str(coupon.amount()) +    ", Accrual period: " + str(coupon.accrualPeriod())
>         print "Date: " + str(coupon.date()) +", accrualStartDate: " +
> str(coupon.accrualStartDate()) +    ", accrualEndDate: " +
> str(coupon.accrualEndDate())
>         print "Date: " + str(coupon.date()) +", rate: " + str(coupon.rate())
>         print "Date: " + str(coupon.date()) +", nominal: " +
> str(coupon.nominal())
>         print "Date: " + str(coupon.date()) +", referencePeriodStart: " +
> str(coupon.referencePeriodStart()) +    ", referencePeriodEnd: " +
> str(coupon.referencePeriodEnd())
>         print "Date: " + str(coupon.date()) +", accrualDays: " +
> str(coupon.accrualDays())
>
>
>
> --
> View this message in context: http://quantlib.10058.n7.nabble.com/Second-Fixing-Different-to-Second-Rate-tp15938.html
> Sent from the quantlib-users mailing list archive at Nabble.com.
>
> ------------------------------------------------------------------------------
> Slashdot TV.  Videos for Nerds.  Stuff that Matters.
> http://pubads.g.doubleclick.net/gampad/clk?id=160591471&iu=/4140/ostg.clktrk
> _______________________________________________
> QuantLib-users mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/quantlib-users



--
<https://implementingquantlib.blogspot.com>
<https://twitter.com/lballabio>

------------------------------------------------------------------------------
Comprehensive Server Monitoring with Site24x7.
Monitor 10 servers for $9/Month.
Get alerted through email, SMS, voice calls or mobile push notifications.
Take corrective actions from your mobile device.
http://p.sf.net/sfu/Zoho
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users