def unpack_trd(self,st): rights = {1:"Call",0:"Put",-1:"Spot"} out = [x.tolist() for x in unstruct(st).T] out[0] = ["Open" if x==0 else "Close" for x in out[0]] #Leg out[2] = ["Ask" if x==1 else "Bid" for x in out[2]] #Side out[3] = [rights[x] for x in out[3]] #Right return out
def join_search(self,cols): #Join trades with cols requested ts = self.ts ts = unstruct(ts[np.where(ts["SIZ"]!=0)[0]]) stk = ts[np.where(ts[:,0]==-1)[0],:] opt = ts[np.where(ts[:,0]!=-1)[0],:] opt = utils.sort_array(opt,(3,2,1,0)) lst = [] cols = ["IDX","STR","TNR"] + cols for l in range(2): I = opt[np.where(opt[:,1]==l)[0],2] K = opt[np.where(opt[:,1]==l)[0],3] st = self.search_raw(I,K,cols,l) leg = np.zeros((st.shape[0],1)) leg[:] = l st = np.hstack([leg,st]) #join leg lst.append(st) st = np.vstack(lst) st = np.vstack([ #join right np.hstack([np.ones((st.shape[0],1)),st]), #Calls np.hstack([np.zeros((st.shape[0],1)),st]) #Puts ]) st = st[utils.intersect2d(st[:,(0,1,2,3)],opt[:,(0,1,2,3)]),:] st = utils.sort_array(st,(3,2,1,0)) size = np.expand_dims(opt[:,-1],axis=0).T opt = np.hstack([size,st]) #join size return opt,stk #STK: RGT,LEG,IDX,STR,SIZ & OPT: SIZ,RGT,LEG,IDX,STR,TNR + cols requested
def search_raw(self,I,K,cols,leg=0): #Arrays have to be sorted for this! st = self.rs[cols][np.where( np.logical_and( np.in1d(self.rs["IDX"][:,leg],I), np.in1d(self.rs["STR"][:,leg],K) ))[0],leg] return unstruct(st)
def surface(symbol, qdate, qtime=None, errors=False, n=False, loc=0, scale=0): df = query.vols(["*"], ["Date", "Time", "Tenor", "Strike"], symbol, qdate, qtime) st = utils.pack(df) del df #---------------------------------------------------------------------------------- f = lambda LST: pricer.norm_weights(LST, loc, scale) wgt = utils.apply(f, 1, st, ["Time", "Tenor"], ["LogStrike"]) #retrive weights vector sv = pricer.SSVI(errors) f = lambda LST, VAR, TNR, VOL: sv.calibrate(LST, VAR, TNR, VOL, wgt) if errors == True: prm = utils.apply(f, 6, st, ["Time"], ["LogStrike", "TotAtmfVar", "Tenor", "SmtVol"], diff=True, fill=False) eps = prm[-1] prm = np.asarray(prm[:-1]).T else: prm = utils.apply(f, 5, st, ["Time"], ["LogStrike", "TotAtmfVar", "Tenor", "SmtVol"], fill=False) #---------------------------------------------------------------------------------- reduced = [ "Time", "Group", "Tenor", "SpotMid", "Forward", "CumDivDays", "Div", "ImpBor", "Rate", "CallH0", "CallH1", "CallKh", "PutH0", "PutH1", "PutKh", "TotAtmfVar" ] st = utils.unique_nosort(st[reduced]) prm = utils.restack(prm, st["TotAtmfVar"], tile=False) rho = sv.correlation(st["TotAtmfVar"], prm[:, 0], prm[:, 1], prm[:, 2]) phi = sv.power_law(st["TotAtmfVar"], prm[:, 3], prm[:, 4]) atm, skw, krt = sv.raw2jw(st["Tenor"] / base, st["TotAtmfVar"], phi, rho) arr = unstruct(st) arr = np.column_stack([arr, atm, skw, krt, phi, rho]) df = utils.unpack(arr, qdate, raw=False, symbol=symbol) if errors == True and n == False: return df, eps elif errors == False and n == True: return df, n elif errors == True and n == True: return df, eps, n else: return df
def pop(self,leg=0): rs,fs = self.rs,self.fs if leg==0: rs[fct_cols][:,0] = self.params.loc[rs["IDX"][:,0],fct_cols].to_records(index=False) rs[fct_cols][:,1] = self.params.loc[rs["IDX"][:,0],fct_cols].to_records(index=False) self.rs = rs self.build_raw(0) else: rs[fct_cols[2:]][:,1] = struct( #Have to convert to unstructured array for broadcasting across cols of the structure (unstruct(rs[fct_cols[2:]][:,0]) * (1 + unstruct(fs[fct_cols[2:]][rs["IDX"][:,0]]))), dtype = (rs[fct_cols[2:]][:,1].dtype) ) rs[fct_cols[:2]][:,1] = struct( (unstruct(rs[fct_cols[:2]][:,0]) - unstruct(fs[fct_cols[:2]][rs["IDX"][:,0]])), dtype = (rs[fct_cols[:2]][:,1].dtype) ) self.rs = rs self.build_raw(1)
def select(st, cols=()): arr = np.hsplit(unstruct(st[cols]), len(cols)) arr = [np.squeeze(x) for x in arr] return arr
def apply(f, returns, st, cat_cols=(), args=(), asarray=False, fill=False, diff=False): assert ( returns != 1 or diff != True ), "can't handle 1 return and different dimensions -> set diff to False" if returns > 1: deq = [deque() for i in range(returns)] else: deq = deque() if asarray == False: args = unstruct(st[args]) else: args = np.vstack(args).T items = [np.unique(st[i]) for i in cat_cols] for x in product(*items): cout.info(f"Categories: {x}") cond = [st[j] == x[i] for j, i in zip(cat_cols, range(len(cat_cols)))] idx = np.select([np.logical_and.reduce(cond)], [True], False) fargs = args[idx, :].T ret = list(f(*fargs)) assert isinstance( ret, Iterable) != False, "arg func is not returning iterable" assert diff == False or len( ret ) == returns, f"arg func returns {len(ret)} vals, but expected {returns}" if fill == True: if returns > 1: for i in range(returns): ret[i] = np.resize(ret[i], fargs.shape[1]) else: ret = np.resize(ret, fargs.shape[1]) if returns > 1: for i in range(returns): deq[i].append(ret[i]) else: deq.append(ret) if returns == 1: ret = np.hstack(list(deq)).T elif returns > 1 and diff == False and fill == False: ret = np.vstack(list(deq)).T elif returns > 1 and diff == False and fill == True: ret = [list(flatten(d)) for d in deq] ret = np.asarray(ret).T elif returns > 1 and diff == True: ret = np.asarray(deq).T ret = [np.hstack(ret[:, i]) for i in range(returns)] return ret
def main(qdate, symbols, qtime=None): for symbol in symbols: start_time = time.time() weekday = 5 if symbol != "NDX" else 4 quotes = query.front_series(3, weekday, symbol, "USD", qdate, qtime) if checks(qdate, symbol, quotes, weekday) == 0: continue cout.info(f"{qdate} {symbol} - initing vol fetch") st = utils.pack(quotes) f = pricer.impdivsborrows yld = utils.apply(f, 2, st, ["Time", "Tenor"], [ "Moneyness", "SpotMid", "Strike", "Tenor", "CallBid", "PutAsk", "Rate", "Div", "CumDivDays" ], fill=True) f = lambda STR, SPT, SPR: pricer.fit_spread(STR, SPT, SPR, "C") chs = utils.apply(f, 3, st, ["Time", "Tenor"], ["Strike", "SpotMid", "CallSpread"], fill=True) f = lambda STR, SPT, SPR: pricer.fit_spread(STR, SPT, SPR, "P") phs = utils.apply(f, 3, st, ["Time", "Tenor"], ["Strike", "SpotMid", "PutSpread"], fill=True) f = lambda TNR, SPT, FRT, CDD, DIV: pricer.forward( TNR, SPT, FRT, yld[:, 0], CDD, DIV) args = utils.select(st, ["Tenor", "SpotMid", "Rate", "CumDivDays", "Div"]) fwd = f(*args) lst = np.log(st["Strike"] / fwd) f = lambda CPX, SPT, STR, TNR, FRT: pricer.Vol( "C", CPX, SPT, STR, TNR, FRT, yld[:, 1], chs[:, 0], chs[:, 1], chs[:, 2]).root(0.01, 4) args = utils.select(st, ["CallMid", "SpotMid", "Strike", "Tenor", "Rate"]) cvol, ceep = f(*args) f = lambda PPX, SPT, STR, TNR, FRT: pricer.Vol( "P", PPX, SPT, STR, TNR, FRT, yld[:, 1], phs[:, 0], phs[:, 1], phs[:, 2]).root(0.01, 4) args = utils.select(st, ["PutMid", "SpotMid", "Strike", "Tenor", "Rate"]) pvol, peep = f(*args) ceep = utils.apply(pricer.interp, 1, st, ["Time", "Tenor"], [lst, ceep], asarray=True, fill=True) peep = utils.apply(pricer.interp, 1, st, ["Time", "Tenor"], [lst, peep], asarray=True, fill=True) rvol = [ (i + j) / 2 if np.isnan(i) == False and np.isnan(j) == False else j if np.isnan(j) == False else i if np.isnan(i) == False else np.nan for i, j in zip(cvol, pvol) ] svol = utils.apply(pricer.interp, 1, st, ["Time", "Tenor"], [lst, rvol], asarray=True, fill=True) var = utils.apply(pricer.totatmfvar, 1, st, ["Time", "Tenor"], [st["Tenor"], lst, rvol], asarray=True, fill=True) if len(var[np.isnan(var)]) > 0: var = utils.apply(pricer.totatmfvar, 1, st, ["Time", "Tenor"], [st["Tenor"], lst, svol], asarray=True, fill=True) ar = np.column_stack([ unstruct(st), yld, chs, phs, fwd, lst, cvol, ceep, pvol, peep, rvol, svol, var ]) df = utils.unpack(ar) query.post(df, "Vols", symbol, "append") elapsed = round((time.time() - start_time) / 60, 3) cout.info(f"{qdate} {symbol} - elapsed {elapsed} mins")
def surface(symbol, qdate, qtime=None, errors=False, post=True, loc=0, scale=None): q = f"select * from dbo.{symbol} where Date = convert(datetime,'{qdate}',103) order by Time,Tenor,Strike" df = query.get("Vols", q) if qtime is not None: df = df[df["Time"] == qtime] st = utils.pack(df) del df #---------------------------------------------------------------------------------- f = lambda LST: pricer.norm_weights(LST, loc, scale) wgt = utils.apply(f, 1, st, ["Time", "Tenor"], ["LogStrike"]) sv = pricer.SSVI(errors) f = lambda LST, VAR, TNR, VOL: sv.calibrate(LST, VAR, TNR, VOL, wgt) if errors == True: prm = utils.apply(f, 6, st, ["Time"], ["LogStrike", "TotAtmfVar", "Tenor", "SmtVol"], diff=True, fill=False) errors = prm[-1] prm = np.asarray(prm[:-1]).T else: prm = utils.apply(f, 5, st, ["Time"], ["LogStrike", "TotAtmfVar", "Tenor", "SmtVol"], fill=False) #---------------------------------------------------------------------------------- reduced = [ "Time", "Tenor", "SpotMid", "Forward", "CumDivDays", "Div", "ImpBor", "Rate", "CallH0", "CallH1", "CallKh", "PutH0", "PutH1", "PutKh", "TotAtmfVar" ] st = utils.unique_nosort(st[reduced]) prm = utils.restack(prm, st["TotAtmfVar"], tile=False) rho = sv.correlation(st["TotAtmfVar"], prm[:, 0], prm[:, 1], prm[:, 2]) phi = sv.power_law(st["TotAtmfVar"], prm[:, 3], prm[:, 4]) atm, skw, krt = sv.raw2jw(st["Tenor"] / base, st["TotAtmfVar"], phi, rho) arr = unstruct(st) arr = np.column_stack([arr, atm, skw, krt, phi, rho]) df = utils.unpack(arr, qdate, False, symbol) if post == True: query.post(df, "Params", "main", "replace") return df # symbol = "JPM" # qdate = "16/10/2020" # qtime = 2040 # errors = True # df = surface(symbol,qdate,qtime=None,errors=False,post=False)
f = lambda STR,SPT,SPR: pricer.fit_spread(STR,SPT,SPR,"P") phs = utils.apply(f,3,st,["Time","Tenor"],["Strike","SpotMid","PutSpread"],fill=True) f = lambda TNR,SPT,FRT,CDD,DIV: pricer.forward(TNR,SPT,FRT,yld[:,0],CDD,DIV) args = utils.select(st,["Tenor","SpotMid","Rate","CumDivDays","Div"]) fwd = f(*args) lst = np.log(st["Strike"]/fwd) f = lambda CPX,SPT,STR,TNR,FRT: pricer.Vol("C",CPX,SPT,STR,TNR,FRT,yld[:,1],chs[:,0],chs[:,1],chs[:,2]).root(0.01,4) args = utils.select(st,["CallMid","SpotMid","Strike","Tenor","Rate"]) cvol,ceep = f(*args) f = lambda PPX,SPT,STR,TNR,FRT: pricer.Vol("P",PPX,SPT,STR,TNR,FRT,yld[:,1],phs[:,0],phs[:,1],phs[:,2]).root(0.01,4) args = utils.select(st,["PutMid","SpotMid","Strike","Tenor","Rate"]) pvol,peep = f(*args) rvol = (cvol + pvol)/2 svol = utils.apply(pricer.interp,1,st,["Time","Tenor"],[lst,rvol],asarray=True,fill=True) var = utils.apply(pricer.totatmfvar,1,st,["Time","Tenor"],[st["Tenor"],lst,svol],asarray=True,fill=True) ar = np.column_stack([unstruct(st),yld,chs,phs,fwd,lst,cvol,ceep,pvol,peep,rvol,svol,var]) df = utils.unpack(ar,qdate) query.post(df,"Vols",symbol,"append") elapsed = round((time.time()-start_time)/60,3) cout.info(f"{symbol} - elapsed {elapsed} mins") break cout.terminate() except: cout.error("Error")