I am just starting to get familiar with QuantLib (in particular, fixed rate bond pricing functions). I read a number of examples, from which I am able to calculate bond price and bond yield.
The following script uses an input yield (0.057154825761367800000) to calculate a bond price (96.9073930899788536), using bond.cleanPrice.
I then took that calculated bond price, and fed it back into a bond.bondYield calculation (other inputs unchanged), expecting to get back my original input yield.
I found the back-calculated yield was close, but not as close as I would naively expect (it matched to 8 decimal places). Did I do something wrong? Is this acceptable precision based on the numerical solver max iterations? Something else?
import QuantLib as ql
def calculate_bond_price():
settlementDays = 0
faceValue = 100
issueDate = ql.Date(11, 2, 2020)
maturityDate = ql.Date(11, 2, 2025)
tenor = ql.Period(ql.Quarterly)
calendar = ql.NullCalendar()
businessConvention = ql.Following
dateGeneration = ql.DateGeneration.Backward
monthEnd = False
schedule = ql.Schedule (issueDate, maturityDate, tenor, calendar, businessConvention, businessConvention, dateGeneration, monthEnd)
coupon_rate = 0.05
coupons = [coupon_rate]
dayCount = ql.Thirty360()
bond = ql.FixedRateBond(settlementDays, faceValue, schedule, coupons, dayCount)
## manually specify a yield rate to 16 decimal places
## this is the value I expect to get back from bond.bondYield calculation
yield_rate = 0.057154825761367800000
bond_price = bond.cleanPrice(yield_rate, dayCount, ql.Simple, ql.Quarterly)
print(f'PRICE >> calculated={bond_price:20,.16f}')
# OUTPUTS: PRICE >> calculated= 96.9073930899788536
# feed the calculated bond price back into a bond.bondYield calculation with exact same (dayCount, Simple, Quarterly) inputs
# expect to get back the yield_rate (16 decimal); but only match to 8 decimals
back_calculate_bond_yield = bond.bondYield(bond_price, dayCount, ql.Simple, ql.Quarterly)
print(f'YIELD >> calculated={back_calculate_bond_yield:20,.16f} | expected={yield_rate:20,.16f} | diff={back_calculate_bond_yield-yield_rate:20,.16f}')
# OUTPUTS: YIELD >> calculated= 0.0571548314094543 | expected= 0.0571548257613678 | diff= 0.0000000056480865
if __name__ == '__main__':
calculate_bond_price()