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 F, a coupon rate \alpha, and the coupon frequency m. The relationship between these values can be described by the following equation:

Fr = \frac{F\alpha}{m}.

When the face value equals the redemption amount, F = C, 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 g in terms of the bond redemption amount C:

g = \frac{Fr}{C}.

We can calculate the number of coupons n by multiplying the bond term N in years by the coupon frequency in number of coupons per year m:

n = Nm.

We are often interested in the bond’s yield to the investor, or bondholder, as a rate compounded yearly i, or as a rate j, specified in terms of the coupon period:

j = \frac{I}{m}

where

i = \left(1 + \frac{I}{m}\right)^m - 1.

The price P 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:

P = (Fr)\ax{\angln j} + Cv_j^n

Another property of a bond is called the base amount G, which is the present value of a perpetuity of the coupon payments:

G = \frac{Fr}{j}

We can express the coupon amount using the face amount, redemption value, or base amount:

Fr = Cg = Gj

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 = Cg = Gj:

# 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