5
$\begingroup$

I would want to use QuantLib Python to calculate par rates of a swap curve.

The following code is what I've done so far:

from QuantLib import *

# global data
calendar = TARGET()
todaysDate = Date(6,November,2001);
Settings.instance().evaluationDate = todaysDate
settlementDate = Date(8,November,2001);

# market quotes
deposits = { (1,Weeks): 0.0382,
             (1,Months): 0.0372,
             (3,Months): 0.0363,
             (6,Months): 0.0353,
             (9,Months): 0.0348,
             (1,Years): 0.0345 }

swaps = { (2,Years): 0.037125,
          (3,Years): 0.0398,
          (5,Years): 0.0443,
          (10,Years): 0.05165,
          (15,Years): 0.055175 }

# convert them to Quote objects
for n,unit in deposits.keys():
    deposits[(n,unit)] = SimpleQuote(deposits[(n,unit)])
for n,unit in swaps.keys():
    swaps[(n,unit)] = SimpleQuote(swaps[(n,unit)])

# build rate helpers

dayCounter = Actual360()
settlementDays = 2
depositHelpers = [ DepositRateHelper(QuoteHandle(deposits[(n,unit)]),
                                     Period(n,unit), settlementDays,
                                     calendar, ModifiedFollowing,
                                     False, dayCounter)
                   for n, unit in [(1,Weeks),(1,Months),(3,Months),
                                   (6,Months),(9,Months),(1,Years)] ]

fixedLegFrequency = Annual
fixedLegTenor = Period(1,Years)
fixedLegAdjustment = Unadjusted
fixedLegDayCounter = Thirty360()
floatingLegFrequency = Semiannual
floatingLegTenor = Period(6,Months)
floatingLegAdjustment = ModifiedFollowing
swapHelpers = [ SwapRateHelper(QuoteHandle(swaps[(n,unit)]),
                               Period(n,unit), calendar,
                               fixedLegFrequency, fixedLegAdjustment,
                               fixedLegDayCounter, Euribor6M())
                for n, unit in swaps.keys() ]

# term structure handles

discountTermStructure = RelinkableYieldTermStructureHandle()
forecastTermStructure = RelinkableYieldTermStructureHandle()

# term-structure construction

helpers = depositHelpers + swapHelpers
depoSwapCurve = PiecewiseFlatForward(settlementDate, helpers, Actual360())

ref_date = depoSwapCurve.referenceDate()
yc_day_count = depoSwapCurve.dayCounter()
tenor = Period(10, Years)

# 10Y Swap 

nominal = 1000000
maturity = calendar.advance(settlementDate,10,Years)

fixedRate = 0.04

floatingLegFrequency = Semiannual
spread = 0.0
fixingDays = 2
index = Euribor6M(forecastTermStructure)
floatingLegDayCounter = index.dayCounter()

fixedSchedule = Schedule(settlementDate, maturity,
                         fixedLegTenor, calendar,
                         fixedLegAdjustment, fixedLegAdjustment,
                         DateGeneration.Forward, False)
floatingSchedule = Schedule(settlementDate, maturity,
                            floatingLegTenor, calendar,
                            floatingLegAdjustment, floatingLegAdjustment,
                            DateGeneration.Forward, False)

swap = VanillaSwap(VanillaSwap.Receiver, nominal,
                   fixedSchedule, fixedRate, fixedLegDayCounter,
                   floatingSchedule, index, spread,
                   floatingLegDayCounter)
swap.setPricingEngine(swapEngine)


discountTermStructure.linkTo(depoSwapCurve)
forecastTermStructure.linkTo(depoSwapCurve)


print('original instrument par rate:')
print(swaps[(10, Years)].value())
print
print('calculated swap par rate:')
print(swap.fairRate())
print
print('calculated yield curve par rate:')
print(depoSwapCurve.forwardRate(ref_date, calendar.advance(ref_date, tenor), yc_day_count, Compounded ).rate())

From the code above we can see that swap.fairRate() returns the par rate of the swap which is very similar to the original swap rate used to construct the yield curve object. This is what I want. However, this method of calculating swap par rate is quite cumbersome, because I want to calculate swap par rate not only for 10Y, but also for 11Y, 12Y, 13Y etc... This means that I'll have to create a separate VanillaSwap object for 11Y, 12Y, 13Y etc...

My second way to calculate swap par rate is depoSwapCurve.forwardRate(...). However, from the code above we can see that the value returned by the forwardRate(...) function is quite different from the original swap rate used to construct the yield curve object.

Am I using the forwardRate(...) function correctly to calculate par rate? Or is there a better way to calculate par rate from a yield curve object?

$\endgroup$
3
$\begingroup$

No, you'll have to create different swaps. forwardRate(start, end) returns the rate from start to end without paying coupons in between (the Compounding convention means that the annual interest is reinvested, not paid off).

To make the process less cumbersome, I suggest you define a function parRate that takes the starlt and end dates, creates the corresponding swap, and returns its fair rate. Once you have it, calling it should be only slightly more complex than calling forwardRate.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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