Skip to content
All library documents

QuantLib Bond Yield Accuracy and Solver Tolerance

Article Quant Q&A · Author: Roberto

Summary

The document investigates why a fixed-rate bond yield calculated in QuantLib does not exactly match the input yield after the bond price is computed and then used to recover the yield. The example prices a bond from a specified yield, then calls the yield-solving function with the same day-count and compounding conventions. The returned yield matches to about eight decimal places, with a small residual difference.

The accepted answer attributes this to the solver’s default accuracy tolerance of 1e-8, rather than inconsistent pricing inputs. It explains that tighter accuracy and a larger evaluation limit can be supplied to the yield calculation; the example then recovers the input yield to near machine precision. This illustrates that round-trip numerical results depend on solver settings. The tighter tolerance is an option, not a general requirement: acceptable precision depends on the use case and numerical stability.

Key ideas

  • A yield recovered from a bond price may differ slightly from the yield used to produce that price.
  • The document attributes the observed discrepancy to QuantLib’s default solver accuracy setting.
  • The yield calculation accepts an accuracy tolerance and a maximum evaluation count.
  • Tightening the tolerance makes the round-trip result closer to the input yield.
  • Choose solver precision according to the application’s needs rather than assuming every small difference indicates an error.

Tags

Full text
# QuantLib returns slightly different bondYield when backtested


# QuantLib returns slightly different bondYield when backtested












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()
```

## Answer by David Duarte (score 6, accepted)

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

I would start by saying that yes, this is an acceptable precision.

However, the reason you are not getting the same result is because, by default, QuantLib has `accuracy=1.0e-8` and `maxEvaluations=100`.

You can set these parameters like this:

`bond.bondYield(bond_price, dayCount, ql.Simple, ql.Quarterly, ql.Date(), 1.0e-16, 100)`

This will get you much closer...

YIELD >> calculated= 0.0571548257613679 | expected= 0.0571548257613678 | diff= 0.0000000000000001

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.