I would like to calculate the price of a 5-year zero-coupon bond at 10% interest with a face value of $1000. I expect such a bond to be priced at $620.92 since $620.92 = 1000/((1.10)^5).
Here's my attempt in Python (Version 3.9.12) using QuantLib (Version 1.29), which returns a price of $60.67, not $620.92.
import QuantLib as ql
# Set up the bond parameters
face_value = 1000
interest_rate = 0.10
maturity_date = ql.Date(9, 3, 2028) # Maturity in 5 years
issue_date = ql.Date(9, 3, 2023) # Issue date today
# Create a bond object
bond = ql.ZeroCouponBond(0, ql.NullCalendar(), face_value, maturity_date)
# Set up the bond engine
spot_curve_handle = ql.YieldTermStructureHandle(ql.FlatForward(issue_date, interest_rate, ql.Actual365Fixed()))
bond_engine = ql.DiscountingBondEngine(spot_curve_handle)
# Assign the bond engine to the bond object
bond.setPricingEngine(bond_engine)
# Calculate the bond price
price = bond.cleanPrice()
print(f"The price of the bond is: {price:.2f}")
I also see that
bond.NPV()
returns $606.20, not $620.92.
How can I modify the code above so that it returns that "textbook" bond price of $620.92?
Change the bond set up including compounding
qflatforw = ql.FlatForward(issue_date, interest_rate, ql.ActualActual(ql.ActualActual.ISMA), ql.Compounded,ql.Annual)
spot_curve_handle = ql.YieldTermStructureHandle(qflatforw)
bond.NPV() 620.9213230591549
To get the other prices define settlement date
ql.Settings.instance().evaluationDate = ql.Date(9, 3, 2023)
price = bond.cleanPrice()
print(f"The price of the bond is: {price:.2f}")
The price of the bond is: 62.09
bond.dirtyPrice()
62.0921323059155