## Features of Fixed Income Securities

**Fixed-income instruments** are debt instruments, such as loans and bonds. Loans are debt instruments formed and governed by a private agreement usually between an individual or company and a financial intermediary, such as a bank. Bonds or fixed-income securities are more standardized contractual agreements between larger issuers and investors. A bond issuer borrows money most often to fund operations or capital expenditures. Bond investors are lenders who provide funds to the issuer in exchange for interest payments and future repayment of principal. Not all liabilities are fixed-income instruments (or “debt”), but all fixed-income instruments are liabilities. In this work, from the perspective of a corporate issuer, we are focused only on loans and bonds: instruments that can be settled in cash and for which the counterparty is an investor or a bank.

Issuer |
Bright Wheels Automotive Corporation |

Settlement Date |
T + 3 Business Days |

Maturity Date |
Five Years from Settlement Date |

Principal Amount |
US$ 300 million |

Interest |
3.2% fixed coupon |

Interest Payment |
Commencing six months from Settlement Date to be paid semiannually with final payment on Maturity Date |

Seniority |
The Notes are unsecured and unsubordinated obligations of BRWA Corporation and will rank pari passu with all other unsecured and unsubordinated indebtedness |

Business Days |
New York |

### Issuer

A bond issuer can be any legal entity and is liable for all interest and principal payments.

### Maturity

A bond’s **maturity** is the date of the final payment the issuer makes to investors, and the tenor refers to the remaining time to maturity. Fixed-income securities with a tenor one year or less at issuance are known as **money market securities**. Bonds with tenors longer than one year at issuance are called **capital market securities**.

### Principal (Par or Face Value)

The principal, par value, or face value is the amount an issuer agrees to repay to investors at maturity. In the BRWA Corporation example, the principal amount of USD300 million is repaid at maturity, which is five years from issuance.

### Coupon Rate and Frequency

A bond’s interest can be paid as

■ a fixed coupon paid on specified dates,

■ a variable coupon determined and paid on specified dates, or

■ part of a single payment with the principal at maturity.

Fixed-coupon bond payments usually involve uniform payments at monthly, quarterly, semi-annual, or annual intervals. Corporate bonds tend to pay semiannually. Bonds with variable interest payments are called **floating-rate notes (FRNs)**. An FRN coupon is determined as a combination of a **market reference rate (MRR)** and an issuer-specific spread referred to as the **credit spread**. Bonds that do not pay periodic interest and instead pay interest as part of a single payment with principal at maturity are termed zero-coupon bonds or pure discount bonds. Zero-coupon bonds are typically issued at a discount to par; the difference between the issuance price and par value represents a cumulative interest payment at maturity.

### Seniority

A debt issue’s seniority or priority of repayment among all issuer obligations is an important determinant of risk. Senior debt has priority over other debt claims in the case of bankruptcy or liquidation. Junior debt, or subordinated debt, claims have a lower priority than senior debt and are paid only once senior claims are satisfied.

### Contingency Provisions

A contingency provision is a clause in a legal agreement that allows for an action if an event or circumstance occurs. The most common contingency provision for bonds involves embedded options—specifically, call, put, and conversion to equity options. These resemble option contracts but cannot be traded separately from the bond itself. However, the value of these embedded options may be established by comparing the value of a bond with a contingency provision with that of an otherwise similar standard bond from the same issuer.

At the time of issuance, investors purchase the bond and pay cash to BRWA Corporation equal to the USD300 million in par value. BRWA investors receive periodic interest payments as follows:

Annual interest expense = Bond par value \(\times\) Coupon rate = USD300,000,000 \(\times\) 3.2% = USD9,600,000.

Semiannual interest expense = USD9,600,000/2 = USD4,800,000.

At the end of the fifth year on the maturity date, BRWA Corporation pays investors the final semiannual coupon payment plus the par value of USD300 million for a total of USD304.8 million.

## Yield Measures

Given a bond’s expected cash flows and its price, return or yield measures can be calculated. One simple measure is the **current yield (CY)**, equal to the bond’s annual coupon divided by the bond’s price and expressed as a percentage. For example, if the five-year BRWA bond were trading at a price of USD101 per USD100 in face value at time \(t\), its current yield would be

\(CY_{t}\) = \(Annual\ coupon_{t}\) / \(Bond\ price_{t}\) = \(\frac{3.2\%}{1.01} = 3.168\%\).

The current yield is analogous to the dividend yield for an equity security. A more complex but far more common yield measure is the yield-to-maturity (YTM), which is the internal rate of return (IRR) calculated using the bond’s price and its expected cash flows to maturity. YTM is usually quoted as an annual rate. An investor’s rate of return on a bond will equal the bond’s YTM at the time of purchase as long as the investor

receives all promised interest and principal payments as scheduled (i.e., no default),

holds the bond until maturity, and

reinvests all periodic cash flows at the YTM.

If any of these assumptions do not hold, the investor’s rate of return on the bond investment will differ from the YTM. If the five-year BRWA bond were trading at a price of USD101 per USD100 in face value immediately after issuance, its YTM is the rate, \(r\), in the following equation (recall that the 3.2% coupon is paid semiannually, or 1.6 in each of 10 periods per USD100 in face value): \(101 = 1.6/(1 + r)^1 + 1.6/(1 + r)^2 + ... + 101.6/(1 + r)^10.\) \(r = 1.49\%\) on a semiannual basis, or \(1.49\% \times 2 = 2.98\%\) annualized. The Quantlib code to calculate YTM is given below:

```
import QuantLib as ql
# Market conventions
= ql.UnitedStates(ql.UnitedStates.NYSE)
calendar = 2
settlement_days = ql.Thirty360(ql.Thirty360.BondBasis) # Using the Bond Basis variant
day_count = 100
face_value
# Bond details
= ql.Date(1, 1, 2020)
issue_date = ql.Date(1, 1, 2025)
maturity_date = 0.032
coupon_rate = ql.Semiannual
frequency = 101 # Current bond price
price
# Create the bond
= ql.Schedule(issue_date, maturity_date, ql.Period(frequency), calendar,
schedule False)
ql.Unadjusted, ql.Unadjusted, ql.DateGeneration.Backward, = ql.FixedRateBond(settlement_days, face_value, schedule, [coupon_rate], day_count)
bond
= bond.bondYield(price, day_count, ql.Compounded, ql.Semiannual, issue_date)
yield_rate print(yield_rate)
```

## Fixed Income Cash Flow Structures

The most common bond cash flow structure is that of a standard fixed-coupon bond, often referred to as a bullet bond. The bond issuer receives the principal at settlement, makes periodic, fixed coupon payments, and repays the principal at maturity.

The Quantlib code to calculate cashflows is given below:

```
import QuantLib as ql
import pandas as pd
# Define the bond and its attributes as before:
= ql.UnitedStates(ql.UnitedStates.NYSE)
calendar = 2
settlement_days = ql.Thirty360(ql.Thirty360.BondBasis)
day_count = 300000000
face_value = ql.Date(1, 1, 2020)
issue_date = ql.Date(1, 1, 2025)
maturity_date = 0.032
coupon_rate = ql.Semiannual
frequency
= ql.Schedule(issue_date, maturity_date, ql.Period(frequency), calendar,
schedule False)
ql.Unadjusted, ql.Unadjusted, ql.DateGeneration.Backward, = ql.FixedRateBond(settlement_days, face_value, schedule, [coupon_rate], day_count)
bond
# Extracting the cash flows:
= list(bond.cashflows())
cashflows
= [cf.date() for cf in cashflows]
dates = [cf.amount() for cf in cashflows]
amounts
# Convert the dates and amounts to a pandas DataFrame:
= pd.DataFrame({
df 'Date': dates,
'Amount': amounts
})print(df)
```

## Amortizing Debt

Fixed-income instruments that periodically retire a portion of principal outstanding prior to maturity offer a borrower the ability to spread payments more evenly over the life of the instrument. Examples include commercial or residential real estate mortgage loans. Investors receive higher near-term cash flows on this amortizing debt relative to bullet bonds and face lower credit risk because the borrower’s liability is reduced over time. However, investors also face the risk of reinvesting the higher cash flows at prevailing market interest rates over the life of the instrument, which could decline.

```
import QuantLib as ql
import pandas as pd
import math
def calculate_periodic_payment(face_value, rate, frequency, n_periods, balloon_payment=0):
if frequency == ql.Annual:
= rate
adjusted_rate elif frequency == ql.Semiannual:
= rate / 2
adjusted_rate elif frequency == ql.Quarterly:
= rate / 4
adjusted_rate else:
raise ValueError("Unsupported frequency")
if balloon_payment > 0:
= (face_value - (balloon_payment/math.pow(1 + adjusted_rate, n_periods)))*adjusted_rate/(1 - math.pow(1 + adjusted_rate, -n_periods))
annuity else:
= face_value * adjusted_rate / (1 - math.pow(1 + adjusted_rate, -n_periods))
annuity return annuity
def create_amortized_cashflows(face_value, coupon_rate, issue_date, maturity_date, frequency, calendar, day_count, settlement_days, balloon_payment=0):
= ql.Schedule(issue_date, maturity_date, ql.Period(frequency), calendar,
schedule False)
ql.Unadjusted, ql.Unadjusted, ql.DateGeneration.Backward,
= len(set(schedule))-1
n_periods = calculate_periodic_payment(face_value, coupon_rate, frequency, n_periods, balloon_payment)
periodic_payment = []
cashflows = face_value
principal_remaining
for i in range(n_periods):
= principal_remaining * (coupon_rate / (2 if frequency == ql.Semiannual else (1 if frequency == ql.Annual else 4)))
interest_payment = periodic_payment - interest_payment
principal_payment
cashflows.append(periodic_payment)-= principal_payment
principal_remaining
-1] += balloon_payment
cashflows[= pd.DataFrame({
df 'Date': [date for date in schedule][1:],
'Amount': cashflows
})return df
# Define the bond attributes:
= ql.UnitedStates(ql.UnitedStates.NYSE)
calendar = 2
settlement_days = ql.Thirty360(ql.Thirty360.BondBasis)
day_count = 300000000
face_value = ql.Date(1, 1, 2020)
issue_date = ql.Date(1, 1, 2025)
maturity_date = 0.032
coupon_rate = ql.Semiannual
frequency = 100000000 # Example value
balloon_payment
= create_amortized_cashflows(face_value, coupon_rate, issue_date, maturity_date, frequency, calendar, day_count, settlement_days, balloon_payment=150000000)
cashflows
print(cashflows)
```

The cash flows are as follows:

Date |
Bullet Bond |
Partially Amortizing Bond |
Fully Amortizing Bond |

July 1st, 2020 | 4800000.0 | 1.875142e+07 | 3.270283e+07 |

January 4th, 2021 | 4800000.0 | 1.875142e+07 | 3.270283e+07 |

July 1st, 2021 | 4800000.0 | 1.875142e+07 | 3.270283e+07 |

January 3rd, 2022 | 4800000.0 | 1.875142e+07 | 3.270283e+07 |

July 1st, 2022 | 4800000.0 | 1.875142e+07 | 3.270283e+07 |

January 3rd, 2023 | 4800000.0 | 1.875142e+07 | 3.270283e+07 |

July 3rd, 2023 | 4800000.0 | 1.875142e+07 | 3.270283e+07 |

January 2nd, 2024 | 4800000.0 | 1.875142e+07 | 3.270283e+07 |

July 1st, 2024 | 4800000.0 | 1.875142e+07 | 3.270283e+07 |

January 2nd, 2025 | 4800000.0 | 1.875142e+07 | 3.270283e+07 |

January 2nd, 2025 | 300000000.0 | 1.687514e+08 | 3.270283e+07 |

## Fixed Income Bond Valuation: Prices and Yields

Bond pricing is an application of discounted cash flow analysis that depends on a bond’s cash flow features and the rate (or rates) used for discounting. Recall from an earlier lesson that the price of the bond at issuance is the present value of the promised interest and principal cash flows. The market discount rate is used in the time-value-of-money calculation to obtain the present value. The market discount rate is the rate of return required by investors given the risk of the bond investment. It is also called the required yield, or the required rate of return.

The code for calculating the bond price using a fixed market rate of return (1.2% semi annual) is given below:

```
import QuantLib as ql
# Market conventions
= ql.UnitedStates(ql.UnitedStates.NYSE)
calendar = 0
settlement_days = ql.Thirty360(ql.Thirty360.BondBasis) # Using the Bond Basis variant
day_count = 100
face_value
# Bond details
= ql.Date(1, 1, 2020)
issue_date = ql.Date(1, 1, 2025)
maturity_date = 0.032
coupon_rate = ql.Semiannual
frequency
# Create the bond
= ql.Schedule(issue_date, maturity_date, ql.Period(frequency), calendar,
schedule False)
ql.Unadjusted, ql.Unadjusted, ql.DateGeneration.Backward, = ql.FixedRateBond(settlement_days, face_value, schedule, [coupon_rate], day_count)
bond = ql.FlatForward(ql.Date(1, 1, 2020), 0.024, day_count)
yield_curve = ql.YieldTermStructureHandle(yield_curve)
handle
bond.setPricingEngine(ql.DiscountingBondEngine(handle))print(bond.NPV())
```

### Flat Price, Accrued Interest, and the Full Price

When a bond is priced between coupon payment dates, its price has two components: the flat price (\(PV^{Flat}\)) and the accrued interest (AI). The sum of the parts is the full price (\(PV^{Full}\)), which also is known as the invoice or “dirty” price. \[PV^{Full} = PV^{Flat} + AI\] The flat price, which is the full price minus the accrued interest, is also called the quoted or “clean” price and is the type of price usually quoted by bond dealers. If a trade takes place, the accrued interest is added to the flat price to obtain the full price paid by the buyer and received by the seller on the trade settlement date. The trade settles when the bond buyer pays and the seller delivers the security. The flat price is used for quotations to avoid misleading investors about a bond’s market price trend. If full prices were quoted by dealers, investors would see price rises each day even if the YTM did not change due to the accrual of interest. The accrued interest is the portion of the next coupon payment owed to the seller of a bond, because although the seller held the bond for a partial coupon period, the full coupon will be received by the buyer. To calculate accrued interest, we determine the fractional amount by counting the days in the period. If the coupon period has \(T\) days between payment dates and t days have passed since the last payment, the accrued interest is calculated using the equation below: \[AI = \frac{t}{T} \times PMT\] where

\(t\) = number of days from the prior coupon payment to the settlement date

\(T\) = number of days in the coupon period

\(\frac{t}{T}\) = fraction of coupon period that has passed since the prior payment

\(PMT\) = coupon payment per period

Note that the accrued interest portion of the full price does not depend on the yield-to-maturity. Therefore, it is only the flat price that is affected by a change in interest rates. There are multiple approaches for day counting (or “day counts”). The day count is specified by two parameters: how days are counted within a given period and the number of days assumed per period. Two common day count conventions are **30/360** and **actual/actual**. The 30/360 day count assumes each month has exactly 30 days (although most don’t) and each year has exactly 360 days (although none do). In contrast, the actual/actual day count convention assumes the actual number of days in each month and the actual number of days in a year.

Consider two otherwise identical bonds that pay 4.375% semiannual interest on 15 May and 15 November of each year. One is a government bond with an actual/actual day count and the other is a corporate bond with a 30/360 day count. The actual/actual method uses the actual number of days, including weekends, holidays, and leap days. The 30/360 method assumes 30 days in a month and 360 days in each year. Calculate accrued interest for settlement on 27 June for both bonds.

The code to calculate the accrued interest in both the above scenarios is given below:

```
import QuantLib as ql
# Define parameters
= 100 # Typically 100 or 1000 for bonds
face_value = 0.04625 # Example coupon rate of 5%
coupon_rate = ql.Date(15, 5, 2020)
start_date = ql.Date(15, 11, 2020)
end_date = ql.Date(27, 6, 2020)
settlement_date
def actual_actual_bond_year_fraction(start_date, end_date, frequency):
# Getting the previous and next coupon dates relative to the start_date
= ql.Period(frequency)
period = start_date - period
previous_coupon_date = start_date + period
next_coupon_date
# If end_date is within the current coupon period
if end_date <= next_coupon_date:
= next_coupon_date - previous_coupon_date
days_in_period = end_date - start_date
days_elapsed return days_elapsed/days_in_period
# If end_date spans multiple coupon periods
else:
# Days in the first partial coupon period
= (next_coupon_date - start_date) / (next_coupon_date - previous_coupon_date)
first_period_fraction
# Days in the last partial coupon period
= (end_date - next_coupon_date) / period.length()
last_period_fraction
# Full periods between start_date and end_date
= (end_date - next_coupon_date) // period.length()
full_periods
return first_period_fraction + full_periods + last_period_fraction
# Accrued Interest using Actual/Actual day count
= ql.ActualActual(ql.ActualActual.ISDA)
actual_actual_day_count = actual_actual_day_count.yearFraction(start_date, settlement_date)
t = actual_actual_day_count.yearFraction(start_date, end_date)
T = (t/T) * (coupon_rate/2) * face_value
actual_actual_accrued_interest
= actual_actual_bond_year_fraction(start_date, settlement_date, frequency)
t = actual_actual_bond_year_fraction(start_date, end_date, frequency)
T = (t/T) * (coupon_rate/2) * face_value
actual_actual_accrued_interest2
# Accrued Interest using 30/360 day count
= ql.Thirty360(ql.Thirty360.USA)
thirty_360_day_count = thirty_360_day_count.yearFraction(start_date, settlement_date)
t = thirty_360_day_count.yearFraction(start_date, end_date)
T = (t/T)* (coupon_rate/2) * face_value
thirty_360_accrued_interest
print(f"Accrued Interest (Actual/Actual): {actual_actual_accrued_interest:.6f}")
print(f"Accrued Interest (Actual/Actual)-2: {actual_actual_accrued_interest2:.6f}")
print(f"Accrued Interest (30/360): {thirty_360_accrued_interest:.6f}")
```