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")