Skip to content
All library documents

Extracting Forward Rates from a QuantLib Zero Curve

Article Quant Q&A · Author: AnonymousJ

Summary

The document shows how to construct a QuantLib yield term structure from dated zero rates and obtain forward rates from it. The answer first corrects an apparent input issue: the example repeats a node date, and the revised curve uses a sequence of annual dates and rates. It then presents two approaches. The first queries the term structure directly for a simple one-month forward rate over successive dates. The second builds a floating-rate leg using a schedule and an Ibor index linked to the curve, then reads the coupon rates as forwards.

The example is aimed at valuing interest rate swaps and illustrates how curve-derived forwards can be inspected or plotted. Its key caveat is that a ZeroCurve interpolates zero rates linearly, which can create discontinuities in the implied forward rates. The snippets are illustrative; the appropriate calendars, conventions, curve nodes, index, and interpolation method depend on the instrument and market setup.

Key ideas

  • A QuantLib ZeroCurve can be wrapped in a yield term structure handle and used to derive forward rates.
  • Forward rates can be queried directly for chosen dates and accrual conventions.
  • A floating-rate leg provides another way to inspect projected index coupon rates.
  • Linear interpolation of zero rates can produce discontinuities in the resulting forward curve.

Tags

Full text
# Zero Rates to Piecewise linear forward rates in Py QuantLib


# Zero Rates to Piecewise linear forward rates in Py QuantLib












How can I extract the piecewise linear forward rates given a term structure of zero rates for a given trade date in Py QuantLib. This is used to price an ir swap.

My attempt is to create a ZeroCurve object with the dates, rates, and day count convention, pass this to a YieldTermStructureHandle, pass this to USDLibor object, and lastly pass it to NonstandardSwap object.

This is what I did for the zero rates.

```
import QuantLib as ql

calendar = ql.UnitedKingdom()    
curve_date = ql.Date(5, 12, 2019)
zcr = [ (calendar.advance(curve_date, 365, ql.Days), 0.02),
        (calendar.advance(curve_date, 730, ql.Days), 0.03),
        (calendar.advance(curve_date, 365, ql.Days), 0.05) ]
dates, rates = zip(*zcr)
forward_term_structure = ql.YieldTermStructureHandle(ql.ZeroCurve(dates, rates, ql.Actual360()))
libor_index = ql.USDLibor(ql.Period(1, ql.Months), forward_term_structure)
```

Is this correct way to do it? Note that there are more nodes in the zcr but for illustration I made up three coordinates. Thank you.

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

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

There is probably a typo in your code because you have two nodes for 365 days, but solving that (and also giving the curve a shorter tenor node):

```
calendar = ql.UnitedKingdom()    
curve_date = ql.Date(5, 12, 2019)
dates = [calendar.advance(curve_date, ql.Period(n, ql.Years)) for n in range(0,4)]
rates = [0.01, 0.02, 0.03, 0.05]
forward_term_structure = ql.YieldTermStructureHandle(ql.ZeroCurve(dates, rates, ql.Actual360()))
forward_term_structure.enableExtrapolation()
```

there are several ways you can go about doing what you want.

1. Get the forward rates directly from the YieldTermStructure

```
    import matplotlib.pyplot as plt
    fwds = [forward_term_structure.forwardRate(date, date + ql.Period('1M'), ql.Actual360(), ql.Simple).rate() for date in dates]     
    plt.plot(rates, 'o-', label="Spot")
    plt.plot(fwds, 'o-', label="1M Forward")
    plt.legend()
```

Here you are extracting the simple 1M forward rate Actual360:

2. Build a floating rate leg and get to rate of the index:

```
    ql.Settings.instance().evaluationDate = curve_date
    start = calendar.advance(curve_date, 2, ql.Days)
    end = calendar.advance(start, 3, ql.Years)
    schedule = ql.MakeSchedule(start, end, ql.Period('1M'))
    index = ql.USDLibor(ql.Period('1M'), forward_term_structure)
    leg = ql.IborLeg([100], schedule, index)
    fwds = [cf.rate() for cf in map(ql.as_coupon, leg)]
    plt.plot(rates, 'o-', label="Spot")
    times = [ql.Actual360().yearFraction(curve_date, cf.date()) for cf in leg]
    plt.plot(times, fwds, 'o-', label="1M Forward")
    plt.legend()
```

This would give you:

Notice that in the case of `ql.ZeroCurve` you are applying linear interpolation to the spot rate which has the known drawback of exhibiting discontinuities in the forwards

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.