Bootstrapping Quarterly Forward Rates from Swap Quotes in QuantLib
Summary
The question concerns constructing quarterly forward rates from USD Libor swap quotes spanning maturities from one to fifty years. The accepted answer identifies the main setup problem: the proposed curve contains only two rate helpers, a zero-rate long deposit and a six percent three-month swap, so it does not use the supplied maturity and rate arrays.
The suggested method creates a swap rate helper for every quoted maturity and rate, converting maturities into year periods and rates from percent to decimal form. QuantLib then bootstraps discount factors at the supplied instrument nodes and interpolates log discount factors between them with a piecewise log-cubic discount curve. Forward rates are sampled over a quarterly schedule. The example demonstrates the curve-building workflow, but its accuracy depends on using appropriate market conventions, calendars, dates, and input quotes; the post does not validate those assumptions against a market dataset.
Key ideas
- A term structure uses one rate helper for each supplied swap maturity and quote.
- The original setup ignores the quote arrays because it creates only two helpers with hard-coded rates.
- QuantLib bootstraps discount factors at instrument nodes and interpolates between them.
- Quarterly forwards can be sampled along a schedule after constructing the curve.
- Curve quality depends on correct market conventions and input data.
Tags
Full text
# Getting quarterly forward rates with QuantLib
# Getting quarterly forward rates with QuantLib
I am trying to build a quarterly forward curve with 3 month USD Libor swap rates from 1Y to 50Y as inputs.
From other posts I have looked at, I have managed to come up with this code so far:
```
terms =['1', '2', '3', '4', '5', '6', '7', '8',
'9', '10', '12', '15', '20', '25', '30', '40', '50']
rate = [0.17, 0.17800000000000002, 0.244, 0.364, 0.499,
0.6409999999999999, 0.773, 0.887, 0.987, 1.074, 1.214, 1.355,
1.4809999999999999, 1.5390000000000001, 1.567,
1.527, 1.45]
LIBOR= ql.IborIndex('USDLibor', ql.Period('3M'), 2, ql.USDCurrency(), ql.UnitedStates(), ql.ModifiedFollowing, True, ql.Actual360())
helpers = [] # Helpers
helpers.append( ql.DepositRateHelper(0, ql.USDLibor(ql.Period('50Y')))) # changed from one year
helpers.append( ql.SwapRateHelper(0.06, ql.UsdLiborSwapIsdaFixAm(ql.Period('3m')))
)
curve = ql.PiecewiseLogCubicDiscount(0, ql.TARGET(), helpers, day_count)
curve.enableExtrapolation()
all_days = ql.MakeSchedule(
curve.referenceDate(),
curve.maxDate(),
ql.Period('3M')
)
rates_fwd = [
curve.forwardRate(d, calendar.advance(d,90,ql.Days), day_count, ql.Simple).rate()
for d in all_days
]
```
Not sure if the code above is correct, but it seems to work. The problem is that it's not using my input terms and rate. Anyone know how a way around this?
## Answer by David Duarte (score 3, accepted)
https://quant.stackexchange.com/a/60786
The code is not really correct, because you are only supplying two instruments: a 50Y Deposit with a rate of 0% and a 3m swap with a rate of 6%.
If you plot your fwd rates, this is what you'll see:
What you want to do is supply a helper for each of your swaps. Then QuantLib will bootstrap the discount factors for the nodes you supplied and interpolate the log discount factors using the chosen method (`PiecewiseLogCubicDiscount`) for values that are not curve nodes.
Here is a working example:
```
import QuantLib as ql
import matplotlib.pyplot as plt
terms =['1', '2', '3', '4', '5', '6', '7', '8',
'9', '10', '12', '15', '20', '25', '30', '40', '50']
rate = [0.17, 0.17800000000000002, 0.244, 0.364, 0.499,
0.6409999999999999, 0.773, 0.887, 0.987, 1.074, 1.214, 1.355,
1.4809999999999999, 1.5390000000000001, 1.567,
1.527, 1.45]
index = ql.USDLibor(ql.Period('3M'))
helpers = []
dc = ql.Actual360()
for term, r in zip(terms, rate):
swapIndex = ql.UsdLiborSwapIsdaFixAm(ql.Period(int(term), ql.Years))
helpers.append(ql.SwapRateHelper(r/100, swapIndex))
curve = ql.PiecewiseLogCubicDiscount(0, ql.TARGET(), helpers, dc)
curve.enableExtrapolation()
days = ql.MakeSchedule(curve.referenceDate(), curve.maxDate(), ql.Period('3M'))
fwds = [
curve.forwardRate(d, ql.UnitedStates().advance(d,90,ql.Days), dc, ql.Simple).rate()
for d in days
]
plt.plot([dt.to_date() for dt in days], fwds)
```
## Answer by user35980 (score 1)
https://quant.stackexchange.com/a/60783
Have you looked through Gautham's excellent tutorial on term structures in quantlib python: http://gouthamanbalaraman.com/blog/quantlib-term-structure-bootstrap-yield-curve.html? You can then modify his code to build any other kind of term structure (eg. swap...etc).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.