|
From: Aleksis A. R. <ale...@go...> - 2020-06-09 11:38:30
|
Thanks Peter - that makes sense: the linear interpolation in strike direction explains it. Btw, this isn’t the case for capfloor vol surfaces so i assume they’re using a different interpolation in strike.
> On 9 Jun 2020, at 12:01, Peter Caspers <pca...@gm...> wrote:
>
> Hi Aleksis, I am just guessing, but from SwaptionVolCube2 you get “sticky moneyness” deltas: If you shift the rates input, the ATM levels in the cube will change. Since the volatilities are set up relative to these ATM levels, the volatility for a given fixed strike (the one from the trade you price) changes under the rate shift as well. Since SwaptionVolCube2 uses a linear interpolation in strike direction, this might cause issues in particular at the points where the vol(strike) - function is non-differentiable.
> Best Regards, Peter
>
>> On 08 Jun 2020, at 21:22, Aleksis Ali Raza <ale...@go... <mailto:ale...@go...>> wrote:
>>
>> Hi Peter. That’s correct - the delta (and vega,gamma, etc) all smoothen out to normal when I zero out the skew in the volcube.
>>
>> Btw, the jags are still present when using ’Naive’ mode in the GSR calibration.
>>
>> Moreover, what’s more relevant is that they are also present even when just using a simple BachelierSwaptionEngine for the vanilla swaption case so I don’t think it’s model related.
>>
>> FYI, I’m using normal vols throughout (with skew definition essentially a simple +5 normal vols for each 25bp otm - both for payers and recs)
>>
>> In any case, to answer your question reg gsr calibration, I think I'm doing both (a) and (b) - essentially I’ve added a modified NPV attribute to the below-mentioned swaption class. So it’s a simple 'bump up,calc NPV,bump down, calc NPV, take difference’ using this NPV attribute. Maybe i’m missing one of the steps (a) or (b) in this code?
>>
>> def NPV(self):
>> engine = ql.Gaussian1dSwaptionEngine(self.model, 64, 7.0, True, False, self.discount_curve)
>> basket = self.nsswaption.calibrationBasket(self.swapbase, self.swvolcube, 'MaturityStrikeByDeltaGamma')
>> for basket_i in basket:
>> ql.as_black_helper(basket_i).setPricingEngine(engine)
>> method = ql.LevenbergMarquardt()
>> ec = ql.EndCriteria(1000, 10, 1e-8, 1e-8, 1e-8)
>> self.model.calibrateVolatilitiesIterative(basket, method, ec)
>> npv = self.nsswaption.NPV()*self.position
>> return npv
>>
>>
>>
>>> On Jun 8, 2020, at 7:21 PM, Peter Caspers <pca...@gm... <mailto:pca...@gm...>> wrote:
>>>
>>> Hi Aleksis,
>>>
>>> do you get the jags only when using a smile, i.e. does the delta get smoother when you use an ATM matrix only?
>>>
>>> Another question I have is a) whether you recalibrate the GSR model after each bump and b) whether you recalculate the calibration basket after each bump as well?
>>>
>>> Thanks
>>> Peter
>>>
>>>> On 08 Jun 2020, at 17:31, Aleksis Ali Raza via QuantLib-users <qua...@li... <mailto:qua...@li...>> wrote:
>>>>
>>>> Sure, essentially it’s run off this class:
>>>>
>>>> class bermudanswaption():
>>>>
>>>> def __init__(self, calendar,settlement, used_model, swap, ratecurves, index, swvolcube_clean, swapbase,
>>>> mean_reversion,position):
>>>>
>>>> discount_curve = ratecurves.loc['discountcurve', 'ratecurves']
>>>> self.swvolcube = swvolcube_clean
>>>> self.swapbase = swapbase
>>>> self.used_model = used_model
>>>> self.discount_curve = discount_curve
>>>> self.position=position
>>>>
>>>> fixed_schedule=swap.fixedSchedule()
>>>> exerciseDates = [calendar.advance(i, -ql.Period('2D')) for i in fixed_schedule][1:-1]
>>>> exercise = ql.BermudanExercise(exerciseDates)
>>>> stepDates = exerciseDates
>>>> self.exerciseDates=exerciseDates
>>>> sigmas = [ql.QuoteHandle(ql.SimpleQuote(0.01))]*(1+len(exerciseDates))
>>>> self.used_model = used_model
>>>>
>>>> if settlement == 'physical':
>>>> type = 0
>>>> method = 1
>>>> else:
>>>> type = 1
>>>> method = 3
>>>>
>>>> self.nsswaption = ql.NonstandardSwaption(swap, exercise, type, method)
>>>> gsr = ql.Gsr(ratecurves.loc[index, 'ratecurves'],
>>>> stepDates, sigmas, [ql.QuoteHandle(ql.SimpleQuote(mean_reversion))])
>>>> engine = ql.Gaussian1dNonstandardSwaptionEngine(gsr, 64, 7.0, True, False,
>>>> ql.QuoteHandle(ql.SimpleQuote(0)),
>>>> discount_curve, 2)
>>>> self.engine = ql.Gaussian1dSwaptionEngine(gsr, 64, 7.0, True, False, discount_curve)
>>>> self.nsswaption.setPricingEngine(engine)
>>>> self.model = gsr
>>>>
>>>>
>>>>
>>>>
>>>>> On 8 Jun 2020, at 15:50, Christofer Bogaso <bog...@gm... <mailto:bog...@gm...>> wrote:
>>>>>
>>>>> Hi, could you please share your python code? Thanks,
>>>>>
>>>>> On Mon, Jun 8, 2020 at 8:00 PM Aleksis Ali Raza via QuantLib-users <qua...@li... <mailto:qua...@li...>> wrote:
>>>>> Hi. In case anyone has an explanation: I get a jagged behaviour in a my greeks when I define a (what is to my knowledge sensible) swaption smile using swaptionvolcube2.
>>>>>
>>>>> The greeks are being calculated by source bumping (using a 1bp shift for the rate delta, shown below along with the NPV). The behaviour isn’t too sensitive to the bump size.
>>>>>
>>>>> Portfolio 1 consists of a 1y4y otm payer swaption and Portfolio 2 of a same strike 5y otm bermudan swaption with annual calls (both valued using the Hull-White GSR model calibrated to the swaption vol cube with MaturityStrikeByDeltaGamma mode).
>>>>>
>>>>> The code is in Python.
>>>>>
>>>>> Thanks, Aleksis
>>>>>
>>>>>
>>>>> <optionanalysis_rate.png>
>>>>> _______________________________________________
>>>>> QuantLib-users mailing list
>>>>> Qua...@li... <mailto:Qua...@li...>
>>>>> https://lists.sourceforge.net/lists/listinfo/quantlib-users <https://lists.sourceforge.net/lists/listinfo/quantlib-users>
>>>>
>>>> _______________________________________________
>>>> QuantLib-users mailing list
>>>> Qua...@li... <mailto:Qua...@li...>
>>>> https://lists.sourceforge.net/lists/listinfo/quantlib-users <https://lists.sourceforge.net/lists/listinfo/quantlib-users>
>>>
>>
>
|