Skip to content
All library documents

Fitting a Nelson–Siegel Yield Curve from Bond Prices in QuantLib

Article Quant Q&A · Author: Alexander

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.