0
$\begingroup$

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?

$\endgroup$

2 Answers 2

3
$\begingroup$

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:

enter image description here

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)

enter image description here

$\endgroup$
1
  • $\begingroup$ Thanks David! Worked a charm! $\endgroup$
    – Mike Lukos
    Feb 5, 2021 at 10:53
1
$\begingroup$

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).

$\endgroup$
1
  • $\begingroup$ Thanks, will take a look! $\endgroup$
    – Mike Lukos
    Feb 5, 2021 at 10:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.