Why a Treasury Bond Quote Differs from a Curve Zero Rate
Summary
The document presents a QuantLib example that builds a US Treasury yield curve from four quoted yields using fixed-rate bond helpers, then compares the ten-year input quote with the curve’s ten-year zero rate. The displayed figures differ, prompting a question about why the rates do not match.
The example highlights that a bond yield quote and a zero rate are different rate measures: the curve is inferred from coupon-bearing bonds, while the zero rate describes discounting to a maturity under specified day-count and compounding conventions. The document does not include an answer or establish which convention or construction detail explains the particular discrepancy, so the figures should be read as a question rather than a general QuantLib rule.
Key ideas
- The example bootstraps a Treasury curve from quoted yields using fixed-rate bond helpers.
- It compares a ten-year bond quote with the zero rate extracted at the corresponding maturity.
- Bond yields and zero rates can differ because they describe different cash-flow and rate conventions.
- The document poses the discrepancy but does not provide a diagnosis or resolution.
Tags
Full text
# Matching the yield on a bond with the zeroRate on a curve in Quantlib
# Matching the yield on a bond with the zeroRate on a curve in Quantlib
I am using QuantLib to generate a US Treasury curve from 1y, 3y, 5y, and 10y yield quotes. However, after building the curve and running `zeroRate` on it, it returns a number that is about 0.012% different to the actual quote (1.972% vs 1.96% quote). What is the difference between these two numbers? Shouldn't they be almost identical?
Thanks in advance!
```
import QuantLib as ql
maturities = [ql.Period('1Y'), ql.Period('3Y'), ql.Period('5Y'), ql.Period('10Y')]
yields = [0.0191, 0.0171, 0.0174, 0.0196]
coupon_frequency = ql.UnitedStates.GovernmentBond
settlement_days = 0
face_amount = 100.0
day_count = ql.ActualActual(ql.ActualActual.Bond)
calendar = ql.UnitedStates()
convention = ql.Unadjusted
generation = ql.DateGeneration.Backward
end_of_month = False
calc_date = ql.Date(5,7,2019)
ql.Settings.instance().evaluationDate = calc_date
bond_helpers = []
for r, m in zip(yields, maturities):
termination_date = calendar.advance(calc_date, m, convention)
schedule = ql.Schedule(calc_date,
termination_date,
ql.Period(coupon_frequency),
calendar,
convention,
convention,
generation,
end_of_month,
)
bond_helper = ql.FixedRateBondHelper(ql.QuoteHandle(ql.SimpleQuote(face_amount)),
settlement_days,
face_amount,
schedule,
[r],
day_count,
convention,
)
bond_helpers.append(bond_helper)
curve = ql.PiecewiseLogCubicDiscount(calc_date, bond_helpers, day_count)
test_maturity = calendar.advance(calc_date, ql.Period('10Y'), convention)
test_maturity, 0.0196, curve.zeroRate(test_maturity, day_count, ql.Compounded, coupon_frequency).rate()
```
```
(Date(5,7,2029), 0.0196, 0.019727996796473413)
```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.