Coupon Bonds¶
Coupon bonds are bonds in which the bond issuer makes payments to the bondholder in addition to the redemption amount throughout the life of the bond.
Coupons are calculated specifying a face value , a coupon rate , and the coupon frequency . The relationship between these values can be described by the following equation:
When the face value equals the redemption amount, , we refer to the bond as being a par-value bond.
Sometimes we’d like to specify the coupon rate as a modified coupon rate in terms of the bond redemption amount :
We can calculate the number of coupons by multiplying the bond term in years by the coupon frequency in number of coupons per year :
We are often interested in the bond’s yield to the investor, or bondholder, as a rate compounded yearly , or as a rate , specified in terms of the coupon period:
where
The price of a bond is the present value of the coupons and the redemption amount. Using this information, we arrive at the basic price formula for a bond:
Another property of a bond is called the base amount , which is the present value of a perpetuity of the coupon payments:
We can express the coupon amount using the face amount, redemption value, or base amount:
Examples¶
Suppose we have a 5-year 1,000 5% bond with semiannual coupons, redeemable at par. What is the price of the bond if the yield is 10% compounded annually?
We can use TmVal to solve for the price just like we can with a zero coupon bond, but this time we need to supply the coupon information because this bond pays coupons. We can set the arguments alpha=.05
and cfreq=4
to represent the coupon rate and frequency, respectively. We also need to set the face value, face=1000
:
In [1]: from tmval import Bond
In [2]: bd = Bond(
...: face=1000,
...: red=1000,
...: alpha=.05,
...: cfreq=4,
...: term=5,
...: gr=.10
...: )
...:
In [3]: print(bd.price)
817.4272763857732
Alternatively, we can specify the coupon rate and frequency to the argument cgr
. Since this information is equivalent to a nominal interest rate, you can supply it to cgr
instead of using alpha
and cfreq
:
In [4]: from tmval import Bond, Rate
In [5]: cgr = Rate(
...: rate=.05,
...: pattern="Nominal Interest",
...: freq=4
...: )
...:
In [6]: bd = Bond(
...: face=1000,
...: red=1000,
...: cgr=cgr,
...: term=5,
...: gr=.10
...: )
...:
In [7]: print(bd.price)
817.4272763857732
Now, let’s examine various properties of this bond:
# coupon amount
In [8]: print(bd.fr)
12.5
# number of coupons
In [9]: print(bd.n_coupons)
20
# base amount
In [10]: print(bd.g)
0.0125
# coupon payments
In [11]: print(type(bd.coupons))
<class 'tmval.annuity.Annuity'>
In [12]: print(bd.coupons.amounts)
[12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5]
In [13]: print(bd.coupons.times)
[0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5, 4.75, 5.0]
# yield per coupon period
In [14]: print(bd.j)
0.02411368908444511
Let’s use this information to verify :
# Fr
In [15]: fr = bd.fr
In [16]: print(bd.fr)
12.5
# Cg
In [17]: cg = bd.g * bd.red
In [18]: print(cg)
12.5
# Gj
In [19]: gj = bd.base * bd.j
In [20]: print(gj)
12.5
In [21]: print(fr == cg == gj)
True