Monday, January 12, 2015

QuantLib Python price same swap on different evaluation dates


I want to use QuantLib Python to price a swap at 2 different evaluation dates during the life time of the swap. The following is what I've tried 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)] ]


settlementDays = 2
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
depoFraSwapCurve = PiecewiseFlatForward(settlementDate, helpers, Actual360())

# swaps to be priced

swapEngine = DiscountingSwapEngine(discountTermStructure)

nominal = 1000000

length = 5
maturity = calendar.advance(settlementDate,length,Years)
payFixed = True

fixedLegFrequency = Annual
fixedLegAdjustment = Unadjusted
fixedLegDayCounter = Thirty360()
fixedRate = 0.04

floatingLegFrequency = Semiannual

spread = 0.0
fixingDays = 2
index = Euribor6M(forecastTermStructure)
floatingLegAdjustment = ModifiedFollowing
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)

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


# price on two different evaluation dates

discountTermStructure.linkTo(depoFraSwapCurve)
forecastTermStructure.linkTo(depoFraSwapCurve)

print(Settings.instance().evaluationDate)
print(spot.NPV())
print


Settings.instance().evaluationDate = Date(13,November,2001)
settlementDate = Date(15,November,2001)
depoFraSwapCurve = PiecewiseFlatForward(settlementDate, helpers, Actual360())

discountTermStructure.linkTo(depoFraSwapCurve)
forecastTermStructure.linkTo(depoFraSwapCurve)

print(Settings.instance().evaluationDate)
print(spot.NPV())


I get the following error:


November 6th, 2001
19065.5382172

November 13th, 2001

---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
in ()
145 forecastTermStructure.linkTo(depoFraSwapCurve)

146
--> 147 print(spot.NPV())
148

C:\ProgramData\Anaconda2\lib\site-packages\QuantLib\QuantLib.pyc in NPV(self)
9157
9158 def NPV(self):
-> 9159 return _QuantLib.Instrument_NPV(self)
9160
9161 def errorEstimate(self):


RuntimeError: 2nd leg: Missing Euribor6M Actual/360 fixing for November 6th, 2001

Any idea what I need to do to resolve this error?



Answer



When you set the evaluation date to November 13th, the fixing date of the first Euribor coupon (November 6th) is in the past; therefore, the coupon can't forecast its fixing over the interest-rate curve like it did in the first case (the curve only describes present and future rates, not past ones).


For the pricing to work, you'll have to store the value of the past fixing. You can do it with:


index.addFixing(Date(6,November,2001), rate)

where rate is the Euribor fixing; if you don't have it, you can probably use as a proxy the 6-months deposit fixing you're using to bootstrap the curve.



A couple of notes:




  • the way you wrote the code, on November 13th you'll bootstrap the curve using the same rates you used for November 6th. In real life, they changed. (That's ok if you're aware of what you're doing; I'm mentioning it just in case and for future readers.)




  • if you want the curve to move with the evaluation date, you don't need to recreate it when the date changes. Instead of passing the reference date, as in:


    curve = PiecewiseFlatForward(settlementDate, helpers, Actual360())

    you can tell the curve explicitly that its reference date should be two business days after the evaluation date, as in:



    curve = PiecewiseFlatForward(2, TARGET(), helpers, Actual360())

    This way, you can create the curve just once and have it move automatically when the evaluation date changes.




No comments:

Post a Comment

technique - How credible is wikipedia?

I understand that this question relates more to wikipedia than it does writing but... If I was going to use wikipedia for a source for a res...