def plot_outofthemoney(): """Plot model-implied out-of-the-money premium. """ nobs = 200 moneyness = np.linspace(-.2, .2, nobs) riskfree, maturity = .1/365, 30/365 call = np.ones_like(moneyness).astype(bool) call[moneyness < 0] = False current_vol = .2**2/365 rho = .9 delta = 1.1 phi = -.5 price_vol = -1000 price_ret = .6 param = ARGparams(mean=current_vol, rho=rho, delta=delta, phi=phi, price_ret=price_ret, price_vol=price_vol) argmodel = ARG(param=param) premium = argmodel.option_premium(vol=current_vol, moneyness=moneyness, maturity=maturity, riskfree=riskfree, call=call) vol = impvol_bisection(moneyness, maturity, premium, call) fig, axes = plt.subplots(nrows=2, ncols=1) axes[0].plot(moneyness, premium, label='premium') axes[1].plot(moneyness, vol, label='impvol') axes[0].legend() axes[1].legend() plt.show()
def test_gbm(self): """Test GBM model.""" price, strike = 100, 110 riskfree, maturity = .01, 30 / 365 call = True put = np.logical_not(call) moneyness = lfmoneyness(price, strike, riskfree, maturity) sigma = .15 model = GBM(GBMParam(sigma=sigma), riskfree, maturity) premium = cosmethod(model, moneyness=moneyness, call=call) premium_true = blackscholes_norm(moneyness, maturity, sigma, call) impvol_model = impvol_bisection(moneyness, maturity, premium, call) self.assertEqual(premium.shape, (1, )) np.testing.assert_array_almost_equal(premium, premium_true, 3) np.testing.assert_array_almost_equal(impvol_model, sigma, 2) moneyness = np.linspace(0, .1, 10) premium = cosmethod(model, moneyness=moneyness, call=call) premium_true = blackscholes_norm(moneyness, maturity, sigma, call) impvol_model = impvol_bisection(moneyness, maturity, premium, call) impvol_true = np.ones_like(impvol_model) * sigma self.assertEqual(premium.shape, moneyness.shape) np.testing.assert_array_almost_equal(premium, premium_true, 2) np.testing.assert_array_almost_equal(impvol_model, impvol_true, 2) riskfree = np.zeros_like(moneyness) premium = cosmethod(model, moneyness=moneyness, call=call) premium_true = blackscholes_norm(moneyness, maturity, sigma, call) impvol_model = impvol_bisection(moneyness, maturity, premium, call) self.assertEqual(premium.shape, moneyness.shape) np.testing.assert_array_almost_equal(premium, premium_true, 3) np.testing.assert_array_almost_equal(impvol_model, sigma, 2) moneyness = np.linspace(-.1, 0, 10) premium = cosmethod(model, moneyness=moneyness, call=put) premium_true = blackscholes_norm(moneyness, maturity, sigma, put) impvol_model = impvol_bisection(moneyness, maturity, premium, put) np.testing.assert_array_almost_equal(premium, premium_true, 2) np.testing.assert_array_almost_equal(impvol_model, impvol_true, 2)
def test_gbm(self): """Test GBM model.""" price, strike = 100, 110 riskfree, maturity = .01, 30/365 call = True put = np.logical_not(call) moneyness = lfmoneyness(price, strike, riskfree, maturity) sigma = .15 model = GBM(GBMParam(sigma=sigma), riskfree, maturity) premium = cosmethod(model, moneyness=moneyness, call=call) premium_true = blackscholes_norm(moneyness, maturity, sigma, call) impvol_model = impvol_bisection(moneyness, maturity, premium, call) self.assertEqual(premium.shape, (1,)) np.testing.assert_array_almost_equal(premium, premium_true, 3) np.testing.assert_array_almost_equal(impvol_model, sigma, 2) moneyness = np.linspace(0, .1, 10) premium = cosmethod(model, moneyness=moneyness, call=call) premium_true = blackscholes_norm(moneyness, maturity, sigma, call) impvol_model = impvol_bisection(moneyness, maturity, premium, call) impvol_true = np.ones_like(impvol_model) * sigma self.assertEqual(premium.shape, moneyness.shape) np.testing.assert_array_almost_equal(premium, premium_true, 2) np.testing.assert_array_almost_equal(impvol_model, impvol_true, 2) riskfree = np.zeros_like(moneyness) premium = cosmethod(model, moneyness=moneyness, call=call) premium_true = blackscholes_norm(moneyness, maturity, sigma, call) impvol_model = impvol_bisection(moneyness, maturity, premium, call) self.assertEqual(premium.shape, moneyness.shape) np.testing.assert_array_almost_equal(premium, premium_true, 3) np.testing.assert_array_almost_equal(impvol_model, sigma, 2) moneyness = np.linspace(-.1, 0, 10) premium = cosmethod(model, moneyness=moneyness, call=put) premium_true = blackscholes_norm(moneyness, maturity, sigma, put) impvol_model = impvol_bisection(moneyness, maturity, premium, put) np.testing.assert_array_almost_equal(premium, premium_true, 2) np.testing.assert_array_almost_equal(impvol_model, impvol_true, 2)
def test_bisection(self): """Test values of implied volatility (bisection method).""" premium = .024 price = 1 strike = 1 riskfree = .02 maturity = 30/365 call = True moneyness = lfmoneyness(price, strike, riskfree, maturity) vol = impvol_bisection(moneyness, maturity, premium, call) self.assertAlmostEqual(float(vol), .2, 2) strike = [1, .95] premium = [.024, .057] moneyness = lfmoneyness(price, strike, riskfree, maturity) vol = impvol_bisection(moneyness, maturity, premium, call) np.testing.assert_array_almost_equal(vol, [.2, .2], 2)
def test_bisection(self): """Test values of implied volatility (bisection method).""" premium = .024 price = 1 strike = 1 riskfree = .02 maturity = 30 / 365 call = True moneyness = lfmoneyness(price, strike, riskfree, maturity) vol = impvol_bisection(moneyness, maturity, premium, call) self.assertAlmostEqual(float(vol), .2, 2) strike = [1, .95] premium = [.024, .057] moneyness = lfmoneyness(price, strike, riskfree, maturity) vol = impvol_bisection(moneyness, maturity, premium, call) np.testing.assert_array_almost_equal(vol, [.2, .2], 2)
def test_bs_prices(self): """Test accuracy of back and forth BS conversion.""" count = int(1e3) maturity = 30/365 call = True sigma = np.random.uniform(.05, .8, count) moneyness = np.random.uniform(-.1, .1, count) premium = blackscholes_norm(moneyness, maturity, sigma, call) vol = impvol_bisection(moneyness, maturity, premium, call) np.testing.assert_array_almost_equal(vol, sigma, 3)
def test_bs_prices(self): """Test accuracy of back and forth BS conversion.""" count = int(1e3) maturity = 30 / 365 call = True sigma = np.random.uniform(.05, .8, count) moneyness = np.random.uniform(-.1, .1, count) premium = blackscholes_norm(moneyness, maturity, sigma, call) vol = impvol_bisection(moneyness, maturity, premium, call) np.testing.assert_array_almost_equal(vol, sigma, 3)
def plot_smiles(fname=None): """Plot model-implied volatility smiles. """ price = 1 nobs = 100 moneyness = np.linspace(-.1, .1, nobs) riskfree, maturity = .0, 30/365 call = np.ones_like(moneyness).astype(bool) call[moneyness < 0] = False current_vol = .2**2/365 rho = .9 delta = 1.1 phi = -.5 price_vol = -1 price_ret = .5 points = 5 sns.set_palette(sns.color_palette("binary_r", desat=.5)) fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(7, 3)) loc = 'upper center' phis = np.linspace(0, -.5, points) for phi in phis: param = ARGparams(mean=current_vol, rho=rho, delta=delta, phi=phi, price_ret=price_ret, price_vol=price_vol) argmodel = ARG(param=param) premium = argmodel.option_premium(vol=current_vol, moneyness=moneyness, maturity=maturity, riskfree=riskfree, call=call) vol = impvol_bisection(moneyness, maturity, premium/price, call) axes[0].plot(moneyness*100, vol*100, label=str(phi)) axes[0].legend(title='Leverage, $\phi$', loc=loc) axes[0].set_xlabel('Log-forward moneyness, $\log(F/S)$, %') axes[0].set_ylabel('Implied volatility, annualized %') maturities = np.linspace(30, 90, points) / 365 phi = 0. for matur in maturities: param = ARGparams(mean=current_vol, rho=rho, delta=delta, phi=phi, price_ret=price_ret, price_vol=price_vol) argmodel = ARG(param=param) premium = argmodel.option_premium(vol=current_vol, moneyness=moneyness, maturity=matur, riskfree=riskfree, call=call) vol = impvol_bisection(moneyness, matur, premium/price, call) axes[1].plot(moneyness*100, vol*100, label=str(int(matur*365))) axes[1].legend(title='Maturity, $T$', loc=loc) axes[1].set_xlabel('Log-forward moneyness, $\log(F/S)$, %') axes[1].set_ylabel('Implied volatility, annualized %') plt.tight_layout() if fname is not None: plt.savefig(fname) plt.show()
import pandas as pd from impvol import (imp_vol, impvol_bisection, lfmoneyness, blackscholes_norm, impvol_table) if __name__ == '__main__': price = 1 strike = 1 riskfree = .02 maturity = 30/365 premium = .057 call = True moneyness = lfmoneyness(price, strike, riskfree, maturity) vol = impvol_bisection(moneyness, maturity, premium, call) count = int(1e2) sigma = np.random.uniform(.05, .8, count) moneyness = np.random.uniform(-.1, .1, count) premium = blackscholes_norm(moneyness, maturity, sigma, call) text = 'Time elapsed: %.2f seconds' time_start = time.time() # Based on SciPy root method vol = imp_vol(moneyness, maturity, premium, call) print(np.allclose(sigma, vol)) print(text % (time.time() - time_start)) time_start = time.time()
import numpy as np import pandas as pd from impvol import (imp_vol, impvol_bisection, lfmoneyness, blackscholes_norm, impvol_table) if __name__ == '__main__': price = 1 strike = 1 riskfree = .02 maturity = 30 / 365 premium = .057 call = True moneyness = lfmoneyness(price, strike, riskfree, maturity) vol = impvol_bisection(moneyness, maturity, premium, call) count = int(1e2) sigma = np.random.uniform(.05, .8, count) moneyness = np.random.uniform(-.1, .1, count) premium = blackscholes_norm(moneyness, maturity, sigma, call) text = 'Time elapsed: %.2f seconds' time_start = time.time() # Based on SciPy root method vol = imp_vol(moneyness, maturity, premium, call) print(np.allclose(sigma, vol)) print(text % (time.time() - time_start)) time_start = time.time()
def impvol(self): """Implied Volatility. """ return impvol_bisection(self.data['moneyness'], self.data['maturity'], self.premium(), self.data['call'])