I'm trying to use SABR to model volatility smile using QuantLib in python. Can someone provide an easy example of optimising SABR parameters using quantlib and returning a quantlib sabr smile?
I've added some further details and my attempted solution
Options data is as follows:
data = pd.DataFrame(
{
'date': dt.date(2024, 9, 10),
'contract_code': 'SFR',
'expiry_code': 'Z25',
'strike': [94.125, 94.25, 94.375, 94.5, 94.625, 94.75, 94.875, 95.0, 95.125, 95.25, 95.375, 95.5, 95.625, 95.75, 95.875, 96.0, 96.125,
96.25, 96.375, 96.5, 96.625, 96.75, 96.875, 97.0, 97.125, 97.25, 97.375, 97.5, 97.625, 97.75, 97.875, 98.0, 98.125, 98.25,
98.375, 98.5, 98.625, 98.75, 98.875, 99.0, 99.125, 99.25, 99.375, 99.5, 99.625, 99.75, 99.875, 100.0, 100.125],
'price': [0.01, 0.0125, 0.015, 0.0175, 0.02, 0.0225, 0.0275, 0.0325, 0.0375, 0.045, 0.0525, 0.0625, 0.0725, 0.085, 0.1025, 0.1225,
0.145, 0.1725, 0.205, 0.24, 0.28, 0.3225, 0.37, 0.425, 0.485, 0.5, 0.4475, 0.4, 0.355, 0.315, 0.2775, 0.245, 0.2175, 0.1925,
0.17, 0.15, 0.1325, 0.1175, 0.1025, 0.09, 0.0775, 0.0675, 0.0575, 0.05, 0.0425, 0.0375, 0.0325, 0.0275, 0.025],
'expiry_date': dt.date(2025, 12, 12),
'underlying': 97.2,
'discount': 0.954263,
'strike_rate': [0.05875, 0.0575, 0.05625, 0.055, 0.05375, 0.0525, 0.05125, 0.05, 0.04875, 0.0475, 0.04625, 0.045, 0.04375, 0.0425,
0.04125, 0.04, 0.03875, 0.0375, 0.03625, 0.035, 0.03375, 0.0325, 0.03125, 0.03, 0.02875, 0.0275, 0.02625, 0.025, 0.02375,
0.0225, 0.02125, 0.02, 0.01875, 0.0175, 0.01625, 0.015, 0.01375, 0.0125, 0.01125, 0.01, 0.00875, 0.0075, 0.00625, 0.005,
0.00375, 0.0025, 0.00125, 0.0, -0.00125],
'underlying_rate': 0.028,
'iv': [132.69826311096224, 132.6135998674864, 131.74391649530892, 130.2713933900565, 128.3101954353009, 125.93667550873326, 125.56317516483074,
124.40993955031576, 122.62840728809596, 121.96250429167836, 120.53097623805455, 119.77806107150022, 118.23800214789529, 117.10953251807356,
117.1802345710329, 117.15922895760573, 116.9829008238809, 117.36798298135997, 118.13524431159198, 118.49245653666745, 119.09935624508483,
119.271343264066, 119.62504006972723, 120.71994677387485, 121.93816832073068, 122.76110065088719, 123.53032918656201, 124.49442096239669,
125.08718288273084, 125.95250561358881, 126.50962001530628, 127.45924149981506, 128.91910012542854, 130.28270398837554, 131.6082404394893,
132.96538266595968, 134.43958655981677, 136.13652599810882, 137.12827877498975, 138.46836961840881, 139.08198492215723, 140.2211015214183,
140.6247832406773, 141.82579296748509, 142.33243969844253, 144.06330163737894, 145.25016082696825, 145.78344706531442, 148.339319620407],
'atm_vol': 122.76110065088719
}
)
def build_sabr_smile(data: pd.DataFrame):
date = pd.to_datetime(data['date']).dt.date[0]
ql_date = ql.Date.from_date(date)
ql.Settings.instance().evaluationDate = ql_date
ql_dcc = ql.Actual365Fixed()
expiry_time = ql.Date.from_date(pd.to_datetime(data['expiry_date']).dt.date[0])
forward_rate = data['underlying_rate'].values[0]
strike_prices = data['strike_rate'].values
atm_vol = data['atm_vol'].values[0]/100
market_vols = data['iv'].values/100
sabr_smile = ql.NoArbSabrInterpolatedSmileSection(
expiry_time,
forward_rate,
strike_prices,
True, # hasFloatingStrikes
atm_vol, # atmVolatility (using the at-the-money volatility)
market_vols,
0.4, # alpha (initial guess)
0.5, # beta (initial guess)
0.1, # nu (initial guess)
0.1, # rho (initial guess)
False, # isAlphaFixed
True, # isBetaFixed
False, # isNuFixed
False, # isRhoFixed
True, # vegaWeighted
ql.EndCriteria(1000, 100, 1e-6, 1e-6, 1e-6),
ql.DifferentialEvolution()
)
return sabr_smile
ql_sabr_smile = build_sabr_smile(clean_smile_data)
ql_sabr_smile.alpha()
i run into this error
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_29140\4249249177.py in ?()
----> 1 ql_sabr_smile.alpha()
~\AppData\Local\miniconda3\envs\analytics\Lib\site-packages\QuantLib\QuantLib.py in ?(self)
13297 def alpha(self):
13298 r"""alpha(NoArbSabrInterpolatedSmileSection self) -> Real"""
> 13299 return _QuantLib.NoArbSabrInterpolatedSmileSection_alpha(self)
RuntimeError: rho (0.99) out of bounds
any help would be appreciated