def test_vol_values(self): """Test values of implied volatility.""" premium = .024 price = 1 strike = 1 riskfree = .02 maturity = 30/365 call = True moneyness = lfmoneyness(price, strike, riskfree, maturity) vol = imp_vol(moneyness, maturity, premium, call) self.assertAlmostEqual(float(vol), .2, 2) strike = [1, .95] premium = [.024, .057] moneyness = lfmoneyness(price, strike, riskfree, maturity) vol = imp_vol(moneyness, maturity, premium, call) np.testing.assert_array_almost_equal(vol, [.2, .2], 2)
def test_vol_values(self): """Test values of implied volatility.""" premium = .024 price = 1 strike = 1 riskfree = .02 maturity = 30 / 365 call = True moneyness = lfmoneyness(price, strike, riskfree, maturity) vol = imp_vol(moneyness, maturity, premium, call) self.assertAlmostEqual(float(vol), .2, 2) strike = [1, .95] premium = [.024, .057] moneyness = lfmoneyness(price, strike, riskfree, maturity) vol = imp_vol(moneyness, maturity, premium, call) np.testing.assert_array_almost_equal(vol, [.2, .2], 2)
def test_moneyness(self): """Test conversion to moneyness.""" price, strike, riskfree, time = 1, 1, 0, .5 moneyness = lfmoneyness(price, strike, riskfree, time) self.assertEqual(moneyness, 0) price, riskfree, time = 1, 0, .5 strike = [1, np.e] moneyness = lfmoneyness(price, strike, riskfree, time) np.testing.assert_array_equal(moneyness, np.array([0, 1])) strike, riskfree, time = 1, 0, .5 price = [1, np.e] moneyness = lfmoneyness(price, strike, riskfree, time) np.testing.assert_array_equal(moneyness, np.array([0, -1]))
def import_vol_surface(): """Import volatility surface. Infer risk-free rate directly from data. """ zf = zipfile.ZipFile(path + "SPX_surface.zip", "r") name = zf.namelist()[0] df = pd.read_csv(zf.open(name), converters={"date": convert_dates}) df.loc[:, "weekday"] = df["date"].apply(lambda x: x.weekday()) # Apply some filters df = df[df["weekday"] == 2] df = df[df["days"] <= 365] df = df.drop("weekday", axis=1) surface = df # .set_index(['cp_flag', 'date', 'days']).sort_index() cols = {"impl_volatility": "imp_vol", "impl_strike": "strike", "impl_premium": "premium"} surface.rename(columns=cols, inplace=True) # TODO : who term structure should be imported and merged! riskfree = load_riskfree().reset_index() dividends = load_dividends().reset_index() spx = load_spx().reset_index() surface = pd.merge(surface, riskfree) surface = pd.merge(surface, spx) surface = pd.merge(surface, dividends) # Adjust riskfree by dividend yield surface["riskfree"] -= surface["rate"] # Remove percentage point surface["riskfree"] /= 100 # Replace 'cp_flag' with True/False 'call' variable surface.loc[:, "call"] = True surface.loc[surface["cp_flag"] == "P", "call"] = False # Normalize maturity to being a share of the year surface["maturity"] = surface["days"] / 365 # Rename columns surface.rename(columns={"spx": "price"}, inplace=True) # Compute lf-moneyness surface["moneyness"] = lfmoneyness(surface["price"], surface["strike"], surface["riskfree"], surface["maturity"]) # Compute option Delta normalized by current price surface["delta"] = delta(surface["moneyness"], surface["maturity"], surface["imp_vol"], surface["call"]) # Compute option Vega normalized by current price surface["vega"] = vega(surface["moneyness"], surface["maturity"], surface["imp_vol"]) # Sort index surface.sort_index(by=["date", "maturity", "moneyness"], inplace=True) print(surface.head()) surface.to_hdf(path + "surface.h5", "surface")
def import_vol_surface_simple(): """Import volatility surface. Simple version. """ zf = zipfile.ZipFile(path + "SPX_surface.zip", "r") name = zf.namelist()[0] df = pd.read_csv(zf.open(name), converters={"date": convert_dates}) df.loc[:, "weekday"] = df["date"].apply(lambda x: x.weekday()) # Apply some filters df = df[df["weekday"] == 2] df = df[df["days"] <= 365] surface = df.drop("weekday", axis=1) cols = {"impl_volatility": "imp_vol", "impl_strike": "strike", "impl_premium": "premium"} surface.rename(columns=cols, inplace=True) spx = load_spx().reset_index() standard_options = load_standard_options()[["forward"]].reset_index() surface = pd.merge(surface, standard_options) surface = pd.merge(surface, spx) # Normalize maturity to being a share of the year surface["maturity"] = surface["days"] / 365 surface["riskfree"] = np.log(surface["forward"] / surface["spx"]) surface["riskfree"] /= surface["maturity"] # Remove percentage point # Replace 'cp_flag' with True/False 'call' variable surface.loc[:, "call"] = True surface.loc[surface["cp_flag"] == "P", "call"] = False # Rename columns surface.rename(columns={"spx": "price"}, inplace=True) # Compute lf-moneyness surface["moneyness"] = lfmoneyness(surface["price"], surface["strike"], surface["riskfree"], surface["maturity"]) # Compute option Delta normalized by current price surface["delta"] = delta(surface["moneyness"], surface["maturity"], surface["imp_vol"], surface["call"]) # Compute option Vega normalized by current price surface["vega"] = vega(surface["moneyness"], surface["maturity"], surface["imp_vol"]) # Take out-of-the-money options calls = surface["call"] & (surface["moneyness"] >= 0) puts = np.logical_not(surface["call"]) & (surface["moneyness"] < 0) surface = pd.concat([surface[calls], surface[puts]]) # Sort index surface.sort_index(by=["date", "maturity", "moneyness"], inplace=True) print(surface.head()) surface.to_hdf(path + "surface.h5", "surface")
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)
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))
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))