def plot(underlying, ivs, params, date): time = pd.to_datetime(f"{date} 12:15:00") ivs.columns.name = 'Side' groups = ivs.xs(time, level='Time').stack().groupby('Expiry') fig, axs = plt.subplots(len(groups), sharex=True, figsize=(8, 10)) strike_min = np.min(ivs.index.get_level_values('Strike').values) strike_max = np.max(ivs.index.get_level_values('Strike').values) strike_grid = np.linspace(strike_min, strike_max, 20) for ax, (e, g) in zip(axs, groups): g.index = g.index.droplevel(['Expiry', 'Side']) g.xs('C').plot(ax=ax, linewidth=0, marker='_', markersize=3) g.xs('P').plot(ax=ax, linewidth=0, marker='_', markersize=3, color='g') heston_prices = heston.formula(underlying.loc[time], strike_grid, _years_to_expiry(date, e), *params) heston_ivs = pd.Series( blackscholes.implied_vol(underlying.loc[time], strike_grid, _years_to_expiry(date, e), heston_prices), strike_grid) heston_ivs.plot(ax=ax, color='gray').set_ylabel('Implied volatility') ax.set_title("Expiry: {}".format(e.strftime('%Y-%m-%d'))) return fig
def test_blackscholes_impliedvol(): sigma = 0.2 underlying_price = 100. strike = 90. expiry = 0.5 option_price = blackscholes.formula(underlying_price, strike, expiry, sigma) iv = blackscholes.implied_vol(underlying_price, strike, expiry, option_price) assert abs(sigma - iv) < 1e-8 option_price = blackscholes.formula(underlying_price, strike, expiry, sigma, True) iv = blackscholes.implied_vol(underlying_price, strike, expiry, option_price, True) assert abs(sigma - iv) < 1e-8
def test_blackscholes_impliedvol_exception(): underlying_price = 100. strike = 90. expiry = 0.5 option_price = 9. with raises(ValueError): blackscholes.implied_vol(underlying_price, strike, expiry, option_price) option_price = 101. with raises(ValueError): blackscholes.implied_vol(underlying_price, strike, expiry, option_price) option_price = np.array([0.9, 20, np.nan]) with np.testing.suppress_warnings() as sup: sup.filter(RuntimeWarning) ivs = blackscholes.implied_vol(underlying_price, strike, expiry, option_price, assert_no_arbitrage=False) assert np.isnan(ivs[0]) and not np.isnan(ivs[1]) and np.isnan(ivs[2])
def build(bbo, underlying, discount, date): return bbo.transform( lambda side: side.groupby(['Class', 'Expiry', 'Strike']).transform( lambda o: blackscholes.implied_vol( underlying, discount[o.name[1]]*o.name[2], _years_to_expiry(date, o.name[1]), o, o.name[0] == 'P')))
import numpy as np import pandas as pd from fyne import blackscholes, heston underlying_price = 100. vol, kappa, theta, nu, rho = 0.0457, 5.07, 0.0457, 0.48, -0.767 strikes = pd.Index(np.linspace(80., 120., 40), name='Strike') expiries = pd.Index([0.1, 0.3, 1.0], name='Expiry') option_prices = heston.formula(underlying_price, strikes[:, None], expiries, vol, kappa, theta, nu, rho) implied_vols = pd.DataFrame( blackscholes.implied_vol(underlying_price, strikes[:, None], expiries, option_prices), strikes, expiries) implied_vols.plot().set_ylabel('Implied volatility')