Fitting a Nelson–Siegel Yield Curve from Bond Prices in QuantLib
Summary
The document explains one way to create a yield curve in QuantLib when the desired curve is described by Nelson–Siegel parameters. Rather than supplying a time function directly, the example constructs fixed-rate bond helpers from market bond prices, maturities, and coupons, then fits a Nelson–Siegel discount curve to those instruments. The fitted curve can be queried for zero rates across a range of times.
The included example sets a valuation date, settlement conventions, calendars, day-count rules, and bond schedules before fitting the curve and retrieving annual zero rates. This shows how bond pricing inputs and curve conventions work together in a practical implementation. It is an illustrative setup with a small sample of bonds; the document does not discuss fit quality, parameter stability, alternative fitting methods, or extrapolation beyond the available maturities. Those choices matter when using a fitted curve for valuation or risk analysis.
Key ideas
- QuantLib can fit a Nelson–Siegel discount curve to prices of fixed-rate bonds.
- Bond helpers encode coupons, maturities, schedules, settlement, and market prices.
- The fitted curve can return zero rates at selected times.
- Calendar, day-count, and settlement conventions are part of the curve setup.
- The example does not assess fit quality or extrapolation behavior.
Tags
Full text
# Quantlib Yield Curve
# Quantlib Yield Curve
Is it possible to create yield curve object in Quantlib given some function of time? For example, given Nelson-Siegel parameters, create yield curve which can compute zero yield for any date >= reference date.
## Answer by David Duarte (score 1)
https://quant.stackexchange.com/a/50476
Yes, it is possible. You can feed bond instruments with prices and fit Nelson-Siegel parameters.
Try this simple example:
```
import QuantLib as ql
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
today = ql.Date(30,12,2019)
ql.Settings.instance().evaluationDate = today
bonds = pd.DataFrame({
'maturity': ['30-03-2020','30-12-2020', '15-06-2021', '17-10-2022', '17-04-2023'],
'coupon': [0,1.25, 3.40, 6.40, 2.25],
'price': [99.88, 99.75, 101.98, 108.70, 96.46]
})
calendar = ql.TARGET()
bondSettlementDays = 2
bondSettlementDate = calendar.advance(today, ql.Period(2, ql.Days))
frequency = ql.Annual
dc = ql.ActualActual(ql.ActualActual.ISMA)
accrualConvention = ql.ModifiedFollowing
convention = ql.ModifiedFollowing
redemption = 100.0
instruments = []
for idx, row in bonds.iterrows():
schedule = ql.Schedule(
bondSettlementDate,
ql.Date(row.maturity, '%d-%m-%Y'),
ql.Period(frequency),
calendar,
accrualConvention,
accrualConvention,
ql.DateGeneration.Backward,
False)
helper = ql.FixedRateBondHelper(
ql.QuoteHandle(ql.SimpleQuote(row.price)),
bondSettlementDays,
100.0,
schedule,
[row.coupon / 100],
dc,
convention,
redemption)
instruments.append(helper)
curveSettlementDays = 2
curveFittingMethod = ql.NelsonSiegelFitting()
tolerance = 1.0e-5
iterations = 1000
curve_ns = ql.FittedBondDiscountCurve(curveSettlementDays, calendar, instruments,
dc, curveFittingMethod, tolerance, iterations)
t = np.linspace(1,3.25)
rates_ns = [curve_ns.zeroRate(n, ql.Annual).rate() for n in t]
plt.figure(figsize=(15,5)),
plt.plot(t, rates_ns);
```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.