|
From: <da...@el...> - 2021-11-01 20:28:46
|
Hi, I am undertaking what on the face of it should be a simple Python task:
replicate the ICAP ATMF cash-settled spot swaption premiums, given their
volatility quotes. I get what seems to be a reasonable number, but that
could just be luck (!).
My base swaption is a EUR 1y10y ATMF receiver, as of today, 1st November.
The ATMF is 0.40%, and according to ICAP:
- 'EUR Cash IRR' vol is 187.3
- 'EUR Cash IRR Shifted Black Vol' is 27.2
- 'EUR Shifts' is 2.00
- 'EUR Cash IRR Cal' Normal vol is 65.1
- 'EUR Spot Cash IRR Premium' is 511.0 (for an atmf straddle)
If I use this code (I have created curves which generate an atmf agreeing
with 0.40%):
const_vol =
ql.ConstantSwaptionVolatility(2,calendar,ql.ModifiedFollowing,
ql.QuoteHandle(ql.SimpleQuote(1.873)),
ql.ActualActual(),ql.ShiftedLognormal)
const_vol_handle = ql.SwaptionVolatilityStructureHandle(const_vol)
blackEngine = ql.BlackSwaptionEngine(discount_curve,const_vol_handle)
swaption = ql.Swaption(parSwap, exercise, ql.Settlement.Cash,
ql.Settlement.ParYieldCurve)
swaption.setPricingEngine(blackEngine)
print('Swaption px {0:.1f} cents'.format(100*swaption.NPV()))
with result:
Swaption px 257.4 cents
and price the swaption, I get a premium which is pretty close to ICAP (once
doubled to 514.8), but not quite the same.
However, I am not sure how (if?) to incorporate the shift of 2 (% I assume),
which is an optional parameter to ql.ConstantSwaptionVolatility() to handle
negative strikes. If I pass 0.02 as this parameter, then I get a
non-sensical premium: should I be bumping my entire swap curve by 2% before
pricing?
Or perhaps I should just be taking the market premia and backing out the
vol?
Grateful for any guidance on this.
Best wishes,
David Sansom
|