Skip to content
All library documents

Pricing a Fixed-Rate Bond from a QuantLib Yield Curve

Article Quant Q&A · Author: TRex

Summary

This document shows how to price a hypothetical fixed-rate bond after constructing a yield curve in QuantLib. The example creates a semiannual coupon bond with specified start and end dates, face value, coupon rate, calendar, and day-count convention. It then wraps the curve in a yield-term-structure handle and attaches a discounting bond engine to the instrument.

The example retrieves the bond’s net present value, clean price, accrued interest, and remaining cash flows. These outputs illustrate how the pricing engine applies the curve to the bond’s payment schedule. The post is a coding example rather than a discussion of valuation theory or market calibration. Its sample dates and conventions may need adjustment for a real instrument, and the displayed code uses a start date that differs from the hypothetical date in the question. It provides no independent valuation checks or market results beyond the QuantLib outputs it instructs the user to print.

Key ideas

  • Construct the bond with its coupon schedule, dates, notional, and day-count convention.
  • Pass the yield curve to a discounting bond engine through a term-structure handle.
  • Attach the engine to the bond before requesting valuation results.
  • Net present value, clean price, accrued interest, and cash flows are distinct useful outputs.

Tags

Full text
# Quantlib: How do I price a bond after having built a term structure


# Quantlib: How do I price a bond after having built a term structure












I below are my codes using QuantLib to build a term structure What I would like to do is use that to price any hypothetical bond lets say

startdate : 8 Feb 2016 end date : 8 Feb 2021 coupons : 10% semi

How do I do that?

```
import matplotlib
matplotlib.use('macosx')
import matplotlib.pyplot as plt
import QuantLib as ql
import pandas as pd

# Deposit rates
depo_maturities = [ql.Period(1,ql.Months),ql.Period(3,ql.Months),ql.Period(6,ql.Months)]
depo_cpn = [.149,.165,.155] #yields they are trading at

maturity_days = [299,845,1210,1485,1895,2306,2671,3128,3494,3904,4453,5275,7101,8699,10526,13629,18834]

# Coupon Bonds
bond_maturities = [ql.Period(i, ql.Days) for i in maturity_days]
bond_cpn = [1.5,.5,.75,1,.625,1.5,1.25,1.625,.875,4.75]
bond_rates = [.106,.114,.151,.187,.252,.214,.272,.311,.4089,.474]
bond_quotes = [101.161,100.896,101.987,103.301,101.926,108.078,107.088,111.111,104.374,144.568]

bond_long_cpn = [4.25, 4.5, 4.25, 3.25, 1.75, 1.75, 1.625]  # coupons
bond_long_rates = [.593, .667, .767, .858, .848, .669, .543]  # yields
bond_long_quotes = [142.974, 152.719, 162.806, 151.432, 123.016, 135.634, 148.58]

'''####### Depo Helpers #########'''

calc_date = ql.Date(24, 3, 2020)
ql.Settings.instance().evaluationDate = calc_date

calendar = ql.UnitedKingdom()
business_convention = ql.Unadjusted
day_count = ql.Thirty360()
end_of_month = True
settlement_days = 0
face_amount = 100
coupon_frequency = ql.Period(ql.Annual)

# Create depo helpers
depo_helpers = [ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(r / 100.0)),
                                     m,
                                     settlement_days,
                                     calendar,
                                     business_convention,
                                     end_of_month,
                                     day_count)
                for r, m in zip(depo_cpn, depo_maturities)]

'''####### Bonds Helpers #########'''

# day_count = ql.Thirty360()
day_count = ql.Actual365Fixed()
end_of_month = True
settlement_days = 2

# create fixed rate bond helpers from fixed rate bonds
bond_cpn += bond_long_cpn
# bond_maturities += bond_long_maturities
bond_quotes += bond_long_quotes
bond_rates += bond_long_rates

bond_helpers = []
for r, m, q in zip(bond_cpn, bond_maturities, bond_quotes):
    termination_date = calc_date + m
    quote = ql.QuoteHandle(ql.SimpleQuote(q))
    schedule = ql.MakeSchedule(calc_date, termination_date, frequency=ql.Annual)
    helper = ql.FixedRateBondHelper(quote, settlement_days, face_amount, schedule, [r / 100.0], day_count,
                                    business_convention)
    bond_helpers.append(helper)

# The yield curve is constructed by putting the two helpers together.
rate_helpers = depo_helpers + bond_helpers
yieldcurve = ql.PiecewiseLogCubicDiscount(calc_date, rate_helpers, day_count)

# The spot cpn is obtined from yieldcurve object using the zeroRate method.
spots = []
tenors = []
for d in yieldcurve.dates():
    yrs = day_count.yearFraction(calc_date, d)
    compounding = ql.Compounded
    freq = ql.Annual
    zero_rate = yieldcurve.zeroRate(yrs, compounding, freq)
    tenors.append(yrs)
    eq_rate = zero_rate.equivalentRate(day_count, compounding, freq, calc_date, d).rate()
    spots.append(100 * eq_rate)
```

## Answer by StackG (score 0, accepted)

https://quant.stackexchange.com/a/55997

You're 90% of the way there. From here, you just need to set up a bond product, pass your yield curve into a pricing engine, and then you can price the bond using the engine

```
# Create a bond instrument
start_date, end_date = ql.Date(8, 2, 2020), ql.Date(8, 2, 2021)
coupons = [0.10]
coupon_freq = ql.Period(ql.Semiannual)

semiannual_bond = ql.FixedRateBond(settlement_days, calendar, 100, start_date, end_date, coupon_freq, coupons, day_count)

# Put the yield curve into a curve handler, pass to a bond pricing engine
rates_ts = ql.YieldTermStructureHandle(yieldcurve)
bond_engine = ql.DiscountingBondEngine(rates_ts)

# Pair the bond engine and the bond, and price!
semiannual_bond.setPricingEngine(bond_engine)

print(semiannual_bond.NPV())
print(semiannual_bond.cleanPrice())
print(semiannual_bond.accruedAmount())

print()
print("Cashflows remaining: ")
for c in semiannual_bond.cashflows():
    print('%20s %12f' % (c.date(), c.amount()))
```

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.