Re: Net yield (after taxes) of a Bond. How to differentiate on cashflow type?

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

Re: Net yield (after taxes) of a Bond. How to differentiate on cashflow type?

Matteo Zandi
On Tue, 2010-12-14 at 15:20 +0100, Martino Fornasa wrote:
> I'm trying to build a function to calculate the net yield (after taxes) 
> of a fixed rate bond. In order to do that, I need to differentiate 
> between coupon-cashflows and, for example, redemption cashflows.

I'm also interested in calculating the net yield of Italian Government fixed rate bonds (BTP), especially I would like to check my own calculations against QuantLib. By using python tests I came up with the following code, for calculating the gross yield (before taxes) for IT0004656275, BTP 3% 01 Nov 2015 with last price of 96,43.
QuantLib gives me 3,69% while Excel's XIRR function returns 3,86% for same cashflows.
What am I doing wrong?
Thanks,
Matteo
#!/usr/bin/python
import QuantLib

settlement_days = 3
face_amount = 100.0
redemption = 100.0
issue_date =  QuantLib.Date(1,11,2000)
maturity_date = QuantLib.Date(1,11,2015)
calendar = QuantLib.Italy(1) # Milan stock exchange
day_counter = QuantLib.ActualActual(QuantLib.ActualActual.Bond)
sched = QuantLib.Schedule(issue_date, maturity_date,
	QuantLib.Period(QuantLib.Semiannual), calendar,
	QuantLib.Unadjusted, QuantLib.Unadjusted,
	QuantLib.DateGeneration.Backward, False)
coupons = [0.03]

bond = QuantLib.FixedRateBond(settlement_days, face_amount,
	sched, coupons, day_counter,
	QuantLib.Following, redemption,
	issue_date)

flat_forward = QuantLib.FlatForward(issue_date+settlement_days*QuantLib.Days,
	coupons[0], day_counter,
	QuantLib.Compounded, QuantLib.Semiannual)
term_structure_handle = QuantLib.RelinkableYieldTermStructureHandle(flat_forward)
bondEngine = QuantLib.DiscountingBondEngine(term_structure_handle)
bond.setPricingEngine(bondEngine)

print bond.bondYield(96.39, day_counter, QuantLib.Compounded, QuantLib.Semiannual, QuantLib.Date(2,1,2010))

Cashflows:
03/01/2011  -96,39
02/05/2011    0,98
01/11/2011    1,5
02/05/2012    1,5
01/11/2012    1,5
02/05/2013    1,5
01/11/2013    1,5
01/05/2014    1,5
01/11/2014    1,5
01/05/2015    1,5
01/11/2015  101,5

------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and,
should the need arise, upgrade to a full multi-node Oracle RAC database
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Net yield (after taxes) of a Bond. How to differentiate on cashflow type?

Luigi Ballabio
On Sun, 2011-01-02 at 14:11 +0100, Matteo Zandi wrote:
> I'm also interested in calculating the net yield of Italian Government fixed rate bonds (BTP), especially I would like to check my own calculations against QuantLib. By using python tests I came up with the following code, for calculating the gross yield (before taxes) for IT0004656275, BTP 3% 01 Nov 2015 with last price of 96,43.
> QuantLib gives me 3,69% while Excel's XIRR function returns 3,86% for same cashflows.
> What am I doing wrong?

Well, to begin with, this...

> flat_forward = QuantLib.FlatForward(issue_date+settlement_days*QuantLib.Days,
> coupons[0], day_counter,
> QuantLib.Compounded, QuantLib.Semiannual)

...doesn't do what you think.  In C++, Days is an enumeration, so it's a
different type and we can overload on it so that 2*Days returns a
Period.  In Python, there's no such thing and QuantLib.Days is just the
integer 0, so you're not setting the date you wanted.  Also, just adding
the settlement days doesn't do the correct thing (even in C++) since it
disregards holidays.  You really want

calendar.advance(issue_date, settlement_days, QuantLib.Days)

instead.

However, that's likely not the problem. One is that, according to the
cashflows you reported, you want to pass Date(2,1,2011) to
bondYield--you're passing 2010 instead.  This brings the yield to 3.82%,
which is more in line with what you're expecting.  
Another issue might be your initial coupons:

03/01/2011  -96,39
02/05/2011    0,98

You're going to receive 1.5 on May 2nd, not 0.98, so that's what the
library will use for that date.  The 0.52 accrued until now should be
included in the clean price passed to the bondYield method.

Luigi


--

Age is an issue of mind over matter. If you don't mind, it doesn't
matter.
-- Mark Twain



------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and,
should the need arise, upgrade to a full multi-node Oracle RAC database
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Net yield (after taxes) of a Bond. How to differentiate on cashflow type?

Matteo Zandi
On Mon, Jan 3, 2011 at 4:31 PM, Luigi Ballabio <[hidden email]> wrote:
You really want
calendar.advance(issue_date, settlement_days, QuantLib.Days)
instead.

ok, thanks for the tip. Maybe it needs to be fixed in python example bond.py also (line 41) where I took it.

However, that's likely not the problem. One is that, according to the
cashflows you reported, you want to pass Date(2,1,2011) to
bondYield--you're passing 2010 instead.  This brings the yield to 3.82%,
which is more in line with what you're expecting.

Hem.. ok for 2011
 
Another issue might be your initial coupons:

03/01/2011  -96,39
02/05/2011    0,98

You're going to receive 1.5 on May 2nd, not 0.98, so that's what the
library will use for that date.  The 0.52 accrued until now should be
included in the clean price passed to the bondYield method.

You're right, the bond works exactly like that but moving 0.52 from the first to the second payment doesn't change the rate of return (according to my calculations and Excel's XIRR function, 3rd decimal accuracy).

Is this what you mean by including the 0.52 accrued to the clean price?
bond.bondYield(96.39+0.52, day_counter, QuantLib.Compounded, QuantLib.Semiannual, QuantLib.Date(3,1,2011))

It lowers the yield to 3,7% which makes sense according to your previous 3,82% (cashflows are diminished by 0.52), but still differs from mine and excel's number (3,86%).

Thanks for the prompt answer and help,
Matteo



------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and,
should the need arise, upgrade to a full multi-node Oracle RAC database
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Net yield (after taxes) of a Bond. How to differentiate on cashflow type?

Luigi Ballabio
On Tue, 2011-01-04 at 09:38 +0100, Matteo Zandi wrote:
> On Mon, Jan 3, 2011 at 4:31 PM, Luigi Ballabio
> <[hidden email]> wrote:
>         You really want
>         calendar.advance(issue_date, settlement_days, QuantLib.Days)
>         instead.
>
>
> ok, thanks for the tip. Maybe it needs to be fixed in python example
> bond.py also (line 41) where I took it.

Is it like this in the example? Sorry, I missed it when it was
contributed.  Yes, it needs to be fixed.  Thanks for the heads-up.



> Is this what you mean by including the 0.52 accrued to the clean
> price?
> bond.bondYield(96.39+0.52, day_counter, QuantLib.Compounded,
> QuantLib.Semiannual, QuantLib.Date(3,1,2011))

No, if 96.39 is your clean price, then the 0.52 is already included.
Seeing it as payment on settlement date, I thought it was the dirty
price.

What do you get from Excel if you pay the clean price plus the accrual
on settlement and receive 1.5 on the first coupon?

Luigi


--

All parts should go together without forcing. You must remember that
the parts you are reassembling were disassembled by you. Therefore, if
you can't get them together again, there must be a reason. By all
means, do not use a hammer.
-- IBM maintenance manual, 1925



------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and,
should the need arise, upgrade to a full multi-node Oracle RAC database
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Net yield (after taxes) of a Bond. How to differentiate on cashflow type?

Matteo Zandi
On Tue, Jan 4, 2011 at 9:56 AM, Luigi Ballabio <[hidden email]> wrote:
No, if 96.39 is your clean price, then the 0.52 is already included.
Seeing it as payment on settlement date, I thought it was the dirty
price.

What do you get from Excel if you pay the clean price plus the accrual
on settlement and receive 1.5 on the first coupon?

Dates Payments
03/01/2011 -96,91 = -(96,39+0,52)
02/05/2011 1,5 
01/11/2011 1,5 
02/05/2012 1,5 
01/11/2012 1,5 
02/05/2013 1,5 
01/11/2013 1,5 
02/05/2014 1,5 
01/11/2014 1,5 
04/05/2015 1,5
01/11/2015 101,5

XIRR = 3,86%

QuantLib gives me 3,82% which is not that different than.

Sorry for the confusion about the example, I was meaning bonds.py under test which the only one I get from the Ubuntu package.

matteo@z2:~$ dpkg -L quantlib-python | grep bonds.py
/usr/share/doc/quantlib-python/examples/test/bonds.py.gz

Thanks again,
Matteo

------------------------------------------------------------------------------
Learn how Oracle Real Application Clusters (RAC) One Node allows customers
to consolidate database storage, standardize their database environment, and,
should the need arise, upgrade to a full multi-node Oracle RAC database
without downtime or disruption
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
QuantLib-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/quantlib-users