|
From: Shaun V. <svi...@ve...> - 2022-12-19 23:11:30
|
Hi All,
First, I want to thank Luigi & the community for all of the work on QuantLib. I'm a new user so apologies if my question is stupid...
I've been trying to get a feel for the mechanics of library-specifically around TermStructures and Interest Rate Swaps. In doing so, I wanted to test a base case:
* Create a simple YieldCurve instance using a 3M Short Rate future + 1Y-10Y Swap Rates
* Create a VanillaSwap on top of this structure
* Evaluate the NPV of this swap & examine the cashflows
* Advance the calendar 10 days [without changing the curve at all]
* Evaluate the NPV of the swap & examine the cashflows]
In the above experiment, given that I am not changing the curve, I would expect the cashflows to remain the same [while the NPVs would change]. However, I am unable get this working, despite running through several tutorials online (DIMA's slides, a couple of Luigi's videos). I have gleaned that this might have something to do with adding fixing days to the indices? But I'm not sure I understand the mechanics of why that would be or how I should think about managing fixings as I advance time in the library.
I'm happy to provide more information.... A messy version of the code is attached below:
import pandas as pd
import QuantLib as ql
from QuantLib import *
def show_cashflows(leg):
for c in leg:
print ('%20s | %s | %.4f%%' % (c.date(), c.amount(),
as_coupon(c).rate()*100))
calendar = TARGET()
tddt = pd.to_datetime('today').date()
todaysDate = ql.Date(tddt.day, tddt.month, tddt.year)
Settings.instance().evaluationDate = todaysDate
settlementDate = calendar.advance(todaysDate, 12, ql.Months)
# market quotes
deposits = { (3,Months): 0.047245}
swaps = {
(1,Years): 0.05876,
(2,Years): 0.045986,
(4,Years): 0.038589,
(5,Years): 0.036954,
(6,Years): 0.035925,
(7,Years): 0.0352,
(8,Years): 0.034683,
(9,Years): 0.03437,
(10,Years): .034186
}
# 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 [(3,Months) ]]
swapHelpers = [ SwapRateHelper(QuoteHandle(swaps[(n,unit)]),
Period(n,unit), calendar,
Annual, Unadjusted,
Actual360(), Euribor6M())
for n, unit in swaps.keys() ]
# term-structure construction
helpers = depositHelpers + swapHelpers
# term structure handles...why do I need both?
discountTermStructure = RelinkableYieldTermStructureHandle()
forecastTermStructure = RelinkableYieldTermStructureHandle()
depoSwapCurve = PiecewiseLogCubicDiscount(settlementDays, TARGET(), helpers, Actual360())
depoSwapCurve.enableExtrapolation()
swapEngine = DiscountingSwapEngine(discountTermStructure)
# 5Y Swap
nominal = 1000000
maturity1 = calendar.advance(settlementDate,5,Years)
fixedRate = 0.036954
spread = 0.0
index = ql.USDLibor(ql.Period(3, ql.Months), forecastTermStructure)
floatingLegAdjustment = ModifiedFollowing
floatingLegDayCounter = index.dayCounter()
fixedSchedule1 = Schedule(settlementDate, maturity1,
Period(1, Years), calendar,
Unadjusted, Unadjusted,
DateGeneration.Forward, False)
floatingSchedule1 = Schedule(settlementDate, maturity1,
Period(6,Months), calendar,
ModifiedFollowing, ModifiedFollowing,
DateGeneration.Forward, False)
# when I create the swap using this method, the cashflows remain fixed upon advancing the day
spot1 = VanillaSwap(VanillaSwap.Receiver, nominal,
fixedSchedule1, fixedRate, Actual360(),
floatingSchedule1, index, spread,
floatingLegDayCounter)
spot1.setPricingEngine(swapEngine)
discountTermStructure.linkTo(depoSwapCurve)
forecastTermStructure.linkTo(depoSwapCurve)
Settings.instance().evaluationDate = todaysDate
print ('Fair Rate: {}'.format(spot1.fairRate()))
print('NPV: {}'.format(spot1.NPV()))
print('fixed cashflows:')
show_cashflows(spot1.fixedLeg())
print('floating cashflows:')
show_cashflows(spot1.floatingLeg())
## AFTER DOING THIS THE FLOATING CASHFLOWS CHANGE AND I WOULD NOT EXPECT THEM TO
Settings.instance().evaluationDate = calendar.advance(todaysDate, 20, Days)
print (spot1.fairRate())
print(spot1.NPV())
print ('Fair Rate: {}'.format(spot1.fairRate()))
print('NPV: {}'.format(spot1.NPV()))
print('fixed cashflows:')
show_cashflows(spot1.fixedLeg())
print('floating cashflows:')
show_cashflows(spot1.floatingLeg())
|