diff options
Diffstat (limited to 'python/option_trades_et.py')
| -rw-r--r-- | python/option_trades_et.py | 336 |
1 files changed, 0 insertions, 336 deletions
diff --git a/python/option_trades_et.py b/python/option_trades_et.py deleted file mode 100644 index 8b64e7b7..00000000 --- a/python/option_trades_et.py +++ /dev/null @@ -1,336 +0,0 @@ -import analytics.option as opt -import pandas as pd -import numpy as np -import matplotlib.pyplot as plt -import numpy as np -import matplotlib.colors as colors -import math - -from matplotlib import cm -from exploration.option_trades import * -from pandas.tseries.offsets import * -from analytics import Index, ForwardIndex -from db import dbengine, dbconn -from scipy.interpolate import * - -serenitasdb = dbengine('serenitasdb') - -def get_dfs(index="IG"): - df0 = atm_vol(index, datetime.date(2014, 6, 11)) - df = rolling_vol(df0, 'atm_vol', term=[1,2,3,4,5,6]) - df1 = rolling_vol(df0, 'otm_vol', term=[1,2,3,4,5,6]) - return (df,df1) - -def calendar_spread(): - df = get_dfs()[0] - df['cal 3m-1m'] = df['3m']-df['1m'] - df['cal 5m-3m'] = df['5m']-df['3m'] - df = df.sort_index() - df = df.groupby(df.index.date).nth(-1) - df[['cal 3m-1m','cal 5m-3m']].plot() - #last 100,100-200,200-300 days - avg = pd.DataFrame([df[-100:].mean(),df[-200:-100].mean(),df[-300:-200].mean()]) - return (df[-1:], avg) - -def put_spread(index = "IG"): - dfs = get_dfs() - df = pd.concat([dfs[0], dfs[1]], axis = 1, keys=['atm','otm']) - steepness = df['otm'] - df['atm'] - steepness.plot() - #last 100,100-200,200-300 days - avg = pd.DataFrame([steepness[-100:].mean(),steepness[-200:-100].mean(),steepness[-300:-200].mean()]) - return (steepness[-1:], avg) - -def swaption_analysis(): - cal = calendar_spread() - cal_otm = calendar_spread(moneyness = "otm_vol") - vol_df = atm_vol('IG',27).groupby(level = 'quotedate').last().dropna() - -def beta_calc(): - am = arch_model(10000*index_price_returns(index='IG')) - res = am.fit(update_freq=0, disp='off') - - amIG = arch_model(100*index_returns()) - resIG = amIG.fit(update_freq=0, disp='off') - ltvar = lr_var(resIG) - - amHY = arch_model(1000*index_returns(index = 'HY')) - resHY = amHY.fit(update_freq=0, disp='off') - ltvar = lr_var(resHY) - graphit = compute_allocation(all_tenors) - -def build_swaption(index, series, expiry, strike, ref, trade_date, t_range= None, spread_range = None): - index_obj = Index.from_name(index, series, '5yr', trade_date) - swap_obj = opt.Swaption(index_obj, expiry, strike, option_type="payer") - swap_obj.notional = 100000000 - - if t_range is None: - t_range = pd.bdate_range(trade_date, expiry- BDay(), freq = '5B') - if spread_range is None: - spread_range = pd.Series(np.arange(ref - 10, ref +19, 5)) - - vol_range = pd.Series(np.arange(25, 60, 5)) #not inclusive of end point - - df = pd.DataFrame(index = pd.MultiIndex.from_product([t_range, spread_range, vol_range], names = ['date', 'spread', 'vol']), columns = ['pv']) - df = df.reset_index() - - def aux(row, index, swap): - index.spread = row.spread - manual_index_update(index, row.date.date()) - swap.sigma = row.vol/100 - swap._update() - return swap.pv - - df['pv'] = df.apply(aux, axis=1, args=(index_obj, swap_obj)) - - #calculate mapped vol - df['moneyness'] = (strike- df.spread)/df.spread - df['days_to_expiry'] = (expiry - df.date).dt.days - vol_surface = build_vol_surface_functions(trade_date, index, series) - df['mapped_vol'] = df.apply(vol_from_surface, axis = 1, args=(vol_surface[0], vol_surface[1])) - df['mapping_shift'] = pd.to_numeric(df.vol/100 - df.mapped_vol, errors = 'ignore') - df = df.set_index(['date', 'spread', 'vol']) - - return df - -def calc_delta_pnl(index, series, ref, trade_date, notional, t_range, spread_range): - - index_obj = Index.from_name(index, series, '5yr', trade_date) - index_obj.spread = ref - index_obj.notional = notional - startingpv = -index_obj.clean_pv - - index_pv = {} - for date in t_range: - for spread in spread_range: - index_obj.spread = spread - manual_index_update(index_obj, date) - #import pdb; pdb.set_trace() - index_pv[(date, spread)] = -index_obj.clean_pv + notional* (date.date()-trade_date).days/360* index_obj.fixed_rate/10000 - - df = pd.DataFrame.from_dict(index_pv, orient = 'index').reset_index() - df['date'] = df['index'].apply(lambda x: x[0]) - df['spread'] = df['index'].apply(lambda x: x[1]) - del df['index'] - df = df.set_index(['date','spread']).sort_index() - df = (df - startingpv).unstack(-1) - df.columns = df.columns.droplevel() - - return df - -def find_mapped_pv(bought, sold, date): - - sold = sold.xs(date).reset_index() - bought = bought.xs(date).reset_index() - - #Bivariate B-Spline, instead of interp2d. Interp2d doesn't behave well and complains a lot. annoying - x = bought.spread.unique() - y = sorted(bought.mapping_shift.unique()) - grid = np.meshgrid(x,y) - f_buy = SmoothBivariateSpline(bought.spread, bought.mapping_shift, bought.pv, kx = 4, ky = 4) - f_sold = SmoothBivariateSpline(sold.spread, sold.mapping_shift, sold.pv, kx = 4, ky = 4) - intp_buy = f_buy.ev(grid[0],grid[1]) - intp_sold = f_sold.ev(grid[0],grid[1]) - df = pd.DataFrame(intp_buy, index = grid[1][0:,0], columns = grid[0][0]) - df1 = pd.DataFrame(intp_sold, index = grid[1][0:,0], columns = grid[0][0]) - - #Use NDInterpolate - not copmplete - #f_buy = LinearNDInterpolator((bought.spread, bought.mapping_shift), bought.pv) - #f_sold = LinearNDInterpolator((sold.spread, sold.mapping_shift), sold.pv) - - #Use interp2d - #x = bought.spread.unique() - #y = sorted(bought.mapping_shift.unique()) - #f_buy = interp2d(bought.spread, bought.mapping_shift, bought.pv) - #f_sold = interp2d(sold.spread, sold.mapping_shift, sold.pv) - #intp_buy = f_buy(x,y) - #intp_sold = f_sold(x,y) - #df = pd.DataFrame(data = intp_buy, index = y, columns = x) - #df1 = pd.DataFrame(data = intp_sold, index = y, columns = x) - - PNL = df - df1 - - return PNL - -def result_fill(df, date): - - data = df.xs(date).reset_index() - #make df.vol a variable to make this function more general - f = interp2d(data.spread, data.vol, data.pv) - x = np.arange(data.spread.min(), data.spread.max(), .5) - y = np.arange(data.vol.min(), data.vol.max(), .5) - intp_result = f(x,y) - df1 = pd.DataFrame(data = intp_result, index = y, columns = x) - - return df1 - -def plot_color_map(df, val_date): - - #rows are spread, columns are volatility surface shift - fig, ax = plt.subplots() - - #Different ways to do a colormap: imshow and pcolormesh. using imshow here - midpoint = 1 - df.max().max()/(df.max().max() + abs(df.min().min())) - shifted_cmap = shiftedColorMap(cm.RdYlGn, midpoint=midpoint, name='shifted') - - chart = ax.imshow(df, extent=(df.columns.min(), df.columns.max(), df.index.min(), df.index.max()) \ - ,aspect= 'auto', interpolation='bilinear', cmap=shifted_cmap) - - ax.set_xlabel('Spread') - ax.set_ylabel('Parallel Shift of Volatility Surface') - ax.set_title('PV of Trade on ' + str(val_date.date())) - - fig.colorbar(chart, shrink = .8) - - fig.savefig("/home/serenitas/edwin/PythonGraphs/payer_swap_" + str(val_date.date()) + ".png") - -def build_vol_surface_functions(date = datetime.date(2017, 2, 23), index = 'IG', series = '27'): - df1 = pd.read_sql_query('SELECT quotedate, expiry, series, strike, vol ' \ - 'FROM swaption_quotes ' \ - 'WHERE index = %s and series = %s and date(quotedate) = %s', - serenitasdb, - index_col=['quotedate', 'expiry', 'series'], - params=(index.upper(), series, date), parse_dates=['quotedate', 'expiry']) - index_data = pd.read_sql_query( - 'SELECT quotedate, expiry, series, ref, fwdspread FROM swaption_ref_quotes ' \ - 'WHERE index= %s and date(quotedate) = %s', - serenitasdb, index_col=['quotedate', 'expiry', 'series'], - params=(index.upper(), date), parse_dates=['quotedate', 'expiry']) - - df1 = df1.join(index_data) - df1 = df1.groupby(df1.index).filter(lambda x: len(x) >= 2) - df1 = df1.reset_index() - #once the dates are in the columns you need the use .dt to access dates functions - df1['days_to_expiry'] = (df1.expiry - df1.quotedate.dt.normalize().dt.tz_localize(None)).dt.days - df1['moneyness'] = (df1.strike - df1.ref)/df1.ref - df1 = df1.groupby(['days_to_expiry','moneyness']).nth(-1).vol - df1 = df1.reset_index() - f = LinearNDInterpolator((df1.days_to_expiry, df1.moneyness), df1.vol) - g = NearestNDInterpolator((df1.days_to_expiry, df1.moneyness), df1.vol) - return (f,g) - -def vol_from_surface(row, f, g): - vol = f(row.days_to_expiry, row.moneyness) - if math.isnan(vol) is True: - vol = g(row.days_to_expiry, row.moneyness) - return vol - -def calc_and_plot(bought, sold, traded_price, week, lowerbound, upperbound, deltaPNL=None): - - if week > len(bought.index.get_level_values(0).unique()): - week = len(bought.index.get_level_values(0).unique())-1 - - date = bought.index.get_level_values(0).unique()[week] - - PNL = find_mapped_pv(bought, sold, date) - traded_price + deltaPNL.loc[date.date()] - - PNL = PNL[lowerbound:upperbound].sort_index(ascending = False) - - plot_color_map(PNL, date) - - return PNL - -def full_analysis(): - index = 'IG' - series = 27, - buy_expiry = datetime.date(2017, 4, 19) - buy_strike = 65 - sell_expiry = datetime.date(2017, 5, 17) - sell_strike = 72 - ref = 62 - trade_date = datetime.date(2017, 2, 23) - delta_notional = 13000000 - - t_range = pd.bdate_range(trade_date, buy_expiry- BDay(), freq = '5B') - spread_range = pd.Series(np.arange(ref - 10, ref +19, 5)) - - bought = build_swaption(index, series, buy_expiry, buy_strike, ref, trade_date, t_range, spread_range) - sold = build_swaption(index, series, sell_expiry, sell_strike, ref, trade_date, t_range, spread_range) - - delta_PNL = calc_delta_pnl(index, series, ref, trade_date, delta_notional, t_range, spread_range) - - #Calc PNL and Plot: - traded_price = 5000 - lowerbound = -.05 #parallel shift down 5% vol - upperbound = .1 #parallel shift up 10% vol - week = 1 #negative to count backwards - - PNL = calc_and_plot(bought, sold, traded_price, week, lowerbound, upperbound, delta_PNL) - - return (bought, sold, PNL, delta_PNL) - - - - - - - - - -def manual_index_update(index, date): #index as Index Object - index._yc = index._yc.expected_forward_curve(date) - index._trade_date = date - index._step_in_date = index.trade_date + datetime.timedelta(days=1) - index._accrued = index._fee_leg.accrued(index._step_in_date) - index._value_date = (pd.Timestamp(index._trade_date) + 3* BDay()).date() - index._update() - - -import numpy as np -import matplotlib -import matplotlib.pyplot as plt -from mpl_toolkits.axes_grid1 import AxesGrid - -def shiftedColorMap(cmap, start=0, midpoint=0.5, stop=1.0, name='shiftedcmap'): - ''' - Function to offset the "center" of a colormap. Useful for - data with a negative min and positive max and you want the - middle of the colormap's dynamic range to be at zero - - Input - ----- - cmap : The matplotlib colormap to be altered - start : Offset from lowest point in the colormap's range. - Defaults to 0.0 (no lower ofset). Should be between - 0.0 and `midpoint`. - midpoint : The new center of the colormap. Defaults to - 0.5 (no shift). Should be between 0.0 and 1.0. In - general, this should be 1 - vmax/(vmax + abs(vmin)) - For example if your data range from -15.0 to +5.0 and - you want the center of the colormap at 0.0, `midpoint` - should be set to 1 - 5/(5 + 15)) or 0.75 - stop : Offset from highets point in the colormap's range. - Defaults to 1.0 (no upper ofset). Should be between - `midpoint` and 1.0. - ''' - cdict = { - 'red': [], - 'green': [], - 'blue': [], - 'alpha': [] - } - - # regular index to compute the colors - reg_index = np.linspace(start, stop, 257) - - # shifted index to match the data - shift_index = np.hstack([ - np.linspace(0.0, midpoint, 128, endpoint=False), - np.linspace(midpoint, 1.0, 129, endpoint=True) - ]) - - for ri, si in zip(reg_index, shift_index): - r, g, b, a = cmap(ri) - - cdict['red'].append((si, r, r)) - cdict['green'].append((si, g, g)) - cdict['blue'].append((si, b, b)) - cdict['alpha'].append((si, a, a)) - - newcmap = matplotlib.colors.LinearSegmentedColormap(name, cdict) - plt.register_cmap(cmap=newcmap) - - return newcmap - - - |
