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?