Skip to content
All library documents

QuantLib Bond Yields Require Decimal Coupon Rates

Article Quant Q&A · Author: Max

Summary

The discussion diagnoses a municipal bond yield calculation that differs substantially from a listed yield. The bond schedule and day-count setup are shown, but the key issue is the coupon input convention: QuantLib expects rates in decimal form rather than percentage points. Entering 5.0 therefore represents a 500% coupon, not a 5% coupon.

Changing the coupon input to 0.05 produces a yield close to the comparison figure. The example shows how a unit mismatch can distort bond pricing outputs even when the calculation structure appears reasonable. It focuses on the coupon-rate scale; it does not establish that the other bond conventions or market data are appropriate for every municipal bond, so those still need to be checked in a real valuation.

Key ideas

  • QuantLib represents coupon rates as decimals rather than percentage-point values.
  • A coupon input of 5.0 is interpreted as a 500% rate.
  • Using 0.05 for a 5% coupon brings the calculated yield close to the cited comparison.
  • Check rate units before investigating more complex bond-model differences.

Tags

Full text
# Price and Yield Calculations for Municipal Bonds with QuantLib


# Price and Yield Calculations for Municipal Bonds with QuantLib












I'm currently trying to calculate yield to maturity for a given municipal bond using quantlib for maven, and am comparing the result to the calculated yield listed on EMMA. However, I keep ending up with a substantially-different yield than expected (in this case, I got `3.639%`, as opposed to `2.895%`).

I've extracted the code from my microservice and have defined each of the variables directly as to maximize comprehension:

```
Double price = 106.365;

Schedule schedule = new MakeSchedule()
  .from(new Date(
      15,
      Month.swigToEnum(01),
      2022
    )) // 2022-01-15 -> quantlib date
  .to(new Date(
      15,
      Month.swigToEnum(07),
      2028
    )) // 2028-07-15 -> quantlib date
  .withFrequency(Frequency.Semiannual)
  // TODO: sifma calendar?
  .withCalendar(new UnitedStates(UnitedStates.Market.GovernmentBond))
  .withConvention(BusinessDayConvention.Following)
  .schedule(); // build final schedule

DoubleVector fixedRateCoupons = new DoubleVector();
fixedRateCoupons.add(5.0);

Bond givenBond = new FixedRateBond(
  1,
  100.0,
  schedule,
  fixedRateCoupons,
  new Thirty360(Thirty360.Convention.USA)
);

public Double getYield(Double price, Date evaluationDate) {
  return BondFunctions.yield(
    givenBond,
    price,
    new Thirty360(Thirty360.Convention.USA),
    Compounding.Compounded,
    Frequency.Semiannual,
    new Date(
      07,
      Month.swigToEnum(05),
      2025
    ) // 2025-05-07 -> quantlib date
  );
}

public Double getYieldToMaturity(Double price) {
  return getYield(price, Date.todaysDate());
}
```

I don't have a background in finance, so it's possible I'm misunderstanding something. Any help would be sincerely appreciated.

## Answer by Luigi Ballabio (score 3, accepted)

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

QuantLib specifies rates in decimal format, not as percentages. By writing `fixedRateCoupons.add(5.0);` you're not using a 5% coupon, but a 500% one, and you're getting back a 363% yield.

You need to use 0.05 for the coupon instead, which will give you a yield of 0.02898, or 2.898%.

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.