Odd coupon periods

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

Odd coupon periods

Mike.Benson
As I am getting the library running for my needs, I thought a good way to figure it all out would be to enter all the examples from Standard Securities Calculation Methods as test cases. Everything was going great until I got to formula 9 page 74, Odd Long First Coupon.
 
There is a difference in the methodology used to calculate odd coupon periods.  After stepping throught the code, it appears that quantlib uses the percent of a year to generate the odd coupon interest. It ends up getting the fraction from DayCounter.yearFraction.
 
In Standard Securities Calculation Methods, the odd coupon is basically calculated as a percent of period.  The difference does not appear until you get to the third decimal of precision on yield / clean price calculations.
 
I am not a real bond person so this may not be an issue but it seems that there is probably a "right" way that matches industry (i.e. bloomberg or IDC data). 
 
Can anyone provide any insight on this?
 
As an additional not I am building my schedule using the issue date and maturity date, and the first / last coupon as the last two arguments to the constructor.  My Pricing engine is the DiscountingBondEngine using a YieldTermStructure for the curve.
 
 

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Odd coupon periods

Ferdinando Ametrano-4
On Tue, Sep 8, 2009 at 4:11 PM, Mike Benson<[hidden email]> wrote:
> As I am getting the library running for my needs, I thought a good way to
> figure it all out would be to enter all the examples from Standard
> Securities Calculation Methods as test cases. Everything was going great
> until I got to formula 9 page 74, Odd Long First Coupon.

I don't have the Mayle's book, so more detail about that specific case
would be appreciated.
As far as I know the only issue might arise with act/act ISMA for
irregular short/long coupon

ciao -- Nando

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Odd coupon periods

Mike.Benson
Thanks for the response, here is what I am using:

Settlement Date: 11/11/1992 (mm/dd/yyyy)
Maturity Date: 03/01/2005 (mm/dd/yyyy)
Issue Date: 06/15/1992 (mm/dd/yyyy)
First Coupon Date: 03/01/1993 (mm/dd/yyyy)
Day Count Basis: Actual/Actual
Mayle:
Rate: 9.35%
Expected Yield: 7.75%
Expected Price: 112.478106
Quantlib (My test case);
Yield  (Given price): 7.7499%
Price (Given Yield) : 112.477135


In the Standard Securities Calculation manual they use "quasi coupon periods" to calculate accrued income.  In a nutshell, you create one or more quasi coupon periods from issue to first coupon and use those quasi periods to calculate the accrued income / price.  
As I said in my original email, I am new to the library so perhaps I am setting something up incorrectly.

My Test Case:


[TestMethod]
        public void Tips_Volume1_Page75_OddLongFirstCoupon()
        {
            Double issuePrice = 100D;
            Double redemptionPrice = 100D;
            Date issueDate = new Date(15, Month.June, 1992);
            Date maturityDate = new Date(01, Month.March, 2005);
            Date firstCoupon = new Date(01, Month.March, 1993);
            Date lastCoupon = new Date(01, Month.September, 2004);
            Date settlementDate = new Date(11, Month.November, 1992);
            Double rate = .0935;
            Double yield = .0775;
            Double price = 112.478106D;
            Schedule schedule = new Schedule(
                issueDate,                          //effectiveDate
                maturityDate,                       //terminationDate
                new Period(6, TimeUnit.Months),     //tenor
                new UnitedStates(),                 //calendar
                BusinessDayConvention.Unadjusted,   //convention
                BusinessDayConvention.Unadjusted,   //termination convention
                DateGeneration.Rule.Forward,        //rule
                false,                              //end of month
                firstCoupon,                        //first date
                lastCoupon);                        //next to last date
            DayCounter counter = new ActualActual(ActualActual.Convention.ISDA);
            DoubleVector coupons = new DoubleVector { .0935D };
            FixedRateBond bond = new FixedRateBond(
                0,              //settlementDays
                issuePrice,     //faceAmount
                schedule,       //schedule
                coupons,        //coupons
                counter,        //paymentDayCounter
                BusinessDayConvention.Unadjusted,   //paymentConvention
                redemptionPrice,//redemption                                          
                issueDate);     //issueDate
            RelinkableYieldTermStructureHandle termstructure = new RelinkableYieldTermStructureHandle();
            FlatForward ff = new FlatForward(issueDate, rate, counter);
            termstructure.linkTo(ff);
            PricingEngine pe = new DiscountingBondEngine(termstructure);
            bond.setPricingEngine(pe);
            double p = bond.cleanPrice(yield, counter, Compounding.Compounded, Frequency.Semiannual, settlementDate);
            double y = bond.yield(price, counter, Compounding.Compounded, Frequency.Semiannual, settlementDate);

            Assert.AreEqual(price, p);  // fails -- p = 112.477135
            Assert.AreEqual(yield, y);  // fails -- y =   0.077499
        }


________________________________________
From: [hidden email] [[hidden email]] On Behalf Of Ferdinando Ametrano [[hidden email]]
Sent: Tuesday, September 08, 2009 8:53 AM
To: Mike Benson
Cc: [hidden email]
Subject: Re: [Quantlib-users] Odd coupon periods

On Tue, Sep 8, 2009 at 4:11 PM, Mike Benson<[hidden email]> wrote:
> As I am getting the library running for my needs, I thought a good way to
> figure it all out would be to enter all the examples from Standard
> Securities Calculation Methods as test cases. Everything was going great
> until I got to formula 9 page 74, Odd Long First Coupon.

I don't have the Mayle's book, so more detail about that specific case
would be appreciated.
As far as I know the only issue might arise with act/act ISMA for
irregular short/long coupon

ciao -- Nando
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Odd coupon periods

Luigi Ballabio
On Tue, 2009-09-08 at 08:40 -0700, Mike Benson wrote:
> Thanks for the response, here is what I am using:
>
> Issue Date: 06/15/1992 (mm/dd/yyyy)
> First Coupon Date: 03/01/1993 (mm/dd/yyyy)
>
> In the Standard Securities Calculation manual they use "quasi coupon
> periods" to calculate accrued income.  In a nutshell, you create one
> or more quasi coupon periods from issue to first coupon and use those
> quasi periods to calculate the accrued income / price.  

Mike,
        just to spell it out---you're saying that instead of

T = yearFraction(issueDate, firstCouponDate)

one should use

T = yearFraction(issueDate, d) + yearFraction(d, firstCouponDate)

with d being one regular coupon after the issue, i.e., 12/15/1992 or
something like it?

Luigi


--

Ogden's Law:
The sooner you fall behind, the more time you have to catch up.



------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Odd coupon periods

Mike.Benson
Thats not quite correct

Short first coupon:
T = yearFraction(issueDate, settlementDate) / yearFraction(d, firstCoupon)
d = The date a normal coupon would have paid prior to the first coupon date.

Short last coupon:
T = yearFraction(lastcoupon, settlement) / yearFraction(lastCoupon, d)
d = The date a normal coupon would have paid after last coupon date.

Long coupons are a bit more complicated, you have to turn this into two quasi coupon periods and add them together.
Long first coupon:
T = (yearFraction(issueDate, d1) / yearFraction(d2, d1)) + (yearFraction(d1, settlement) / yearFraction(firstCoupon))
d1 = The date a normal coupon would have paid prior to the first coupon date
d2 = The date a second normal coupon would have paid prior to d1

My C++ is way to rusty to substitue and test this, but if we have a volunteer, I could put together 30-40 sets of test case data to check.  Its also worth a note the Municipal bonds ignore this for price / yield calcualtions but not accrued interest.  Since I am wrapping the library I just dont set the coupons for first / last on munis when calculating price / yield.


Here are the explanations from Standard Securities Calculation Methods (SCCM).

>From SCCM volume 1 page 30 - Short Coupon Formula
To determine the accrued interest in a short coupon period, that coupon period's length must be adjusted to represent a normal length (NL) or quasi-coupon* period (NL replaces D in the standard formula). This is done in one of the tow following ways;  Odd first coupon: by working backwards in time from the short coupon's interest payment date (first coupon date) to a date representing the first day of teh quasi coupon period; Odd lat coupon: by working forward in time from the short coupon's interest payment date (last coupon date before redemption) to a date representing the last day of the quasi coupon period.  .....

Accrued Interest = P * R/M * A/NL
A = Accrued days
M = Number of coupon periods per year
NL = Number of days representing the quasi-coupon period
P = Par Value
R = Annual coupon rate
* The term "quasi-coupon period" is used to represent the length of the coupon period that is standard for the security (semi-annual, annual, etc.).  Thus, a semi-annual corporate bond with three months for its first coupon period has one quasi-coupon period of 180 days.

Example:
Day Count 30/360
Issue 07/01/1992
First Interest Date: 10/01/1992
Settlement Date: 08/18/1992
M = 2  Semi-annual coupon payments
NL = 180 Since day count basis is 30/360 and the number of coupons per year is 2 (360/2 =180)
P = 1000
R = .05
A = 47 accrued days are found by determining the number of days from issue date to settlemetn date (07/01/1992 to 08/18/1992)

Thus:
Accrued Interest = 1000 * (.05/2) * (47/180) = 6.53


>From SCCM volume 1 page 32 - Long Coupon Formula
To determine the accrued interest for long coupon periods, the number (NC) of quasi-coupon* periods must be calculated.  This is done in one of the two following ways; Odd long first coupon: by working backwards in time fromt eh long coupon's interest payment dare (first coupon date) and adding together the number of standard coupon periods that would fist in the long coupon, round up to the next whole number;  Odd long last coupon: by working forward in time from the long coupon's interest payment date (last coupon date before redemption) and adding together the number of standard coupon periods that would fit in the long coupon founding up to the next whole number.  For example, between the issue date of 07/01/199 and the first coupon date of 04/01/1993 there are 1 1/2 six month periods or 2(NC=2) quasi coupon periods.

Accured Interest = P * (R/M) * ( Sum 1 to NC(Ai/NLi))
Ai = number of accruded days for the ith quasi coupon period within odd period
M = number of coupon periods per year
NC = Number of quasi-coupon periods that fit in odd period.  If this number contains a fractional part, raise it to the the next whole number.  
NLi= Normal length in days of the ith quasi-coupon period within odd period
P = Par Value
R = Annual interest rate

* The term "quasi-coupon period" is used to represent the length of the coupon period that is standard for the security (semi-annual, annual, etc.).  Thus, a semi-annual municipal bond with nine months for its first coupon period has two quasi-coupon periods, each with a length of 180 days

Example:
Day Count Basis: Acutual/Actual
Issue Date: 07/01/1992
First Interest Date: 04/01/1993
Settlement Date: 02/01/1993
M = 2
A1 = 123  (10/01/1992-02/01/1993)
A2 = 92  (07/01/1992-10/01/1992)
NC = 2  (10/01/1992-04/01/1993) (04/01/1992-10/01/1992)
NL1 = 182  (10/01/1992-04/01/1993)
NL2 = 183  (04/01/1992-10/01/1992)
P = 10000
R = .075
Accrued Interest = 10000 * (.075/2) * (123/182 + 92/183) = 441.96
Visually:
               |---A2-----|-----A2------|
04/01/92---07/01/92---10/01/1992----02/01/92--04/01/93
   |--------NL2-----------|-----------NL1---------|
   
--- My notes
NC in this case are the quasi coupon periods.  The first coupon date is 04/01/1993 you have to work backwards until you cross the issue date.  Going back from 04/01/1993, the prior normal coupon would have been 10/01/1992 (not before issue date).  Go back again, 04/01/1992, since this is before the issue date, you have to use two quasi coupon periods.


________________________________________
From: Luigi Ballabio [[hidden email]]
Sent: Friday, September 11, 2009 8:09 AM
To: Mike Benson
Cc: [hidden email]
Subject: Re: [Quantlib-users] Odd coupon periods

On Tue, 2009-09-08 at 08:40 -0700, Mike Benson wrote:
> Thanks for the response, here is what I am using:
>
> Issue Date: 06/15/1992 (mm/dd/yyyy)
> First Coupon Date: 03/01/1993 (mm/dd/yyyy)
>
> In the Standard Securities Calculation manual they use "quasi coupon
> periods" to calculate accrued income.  In a nutshell, you create one
> or more quasi coupon periods from issue to first coupon and use those
> quasi periods to calculate the accrued income / price.

Mike,
        just to spell it out---you're saying that instead of

T = yearFraction(issueDate, firstCouponDate)

one should use

T = yearFraction(issueDate, d) + yearFraction(d, firstCouponDate)

with d being one regular coupon after the issue, i.e., 12/15/1992 or
something like it?

Luigi


--

Ogden's Law:
The sooner you fall behind, the more time you have to catch up.
------------------------------------------------------------------------------
Come build with us! The BlackBerry&reg; Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9&#45;12, 2009. Register now&#33;
http://p.sf.net/sfu/devconf
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users