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)
Example #6
0
def select(st, cols=()):
    arr = np.hsplit(unstruct(st[cols]), len(cols))
    arr = [np.squeeze(x) for x in arr]
    return arr
Example #7
0
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
Example #8
0
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")