def get_spread(self, a, q=5, bias=0, spread_size=0.5, better=0): better = better or self.sp["better"] p = a.status["pos"]; q=abs(q) if not bias: bias = -p or q*u.sign(random.random()-0.49) # slight buy bias (: get = lambda cls,i: cls.lst[i]["price"] if len(cls.lst)-i>0 else 0 if not get(a.mbids, 0) or not get(a.masks, 0): return # get_out if no bid or no ask ! wbid, wask = [a.mbids.lst[-1]["price"] - better, a.masks.lst[-1]["price"] + better] for cls in [a.mbids, a.masks]: price = get(cls, 0) + better * min(1, bias / q) # increase with position price = u.between(wbid, price, wask) live = 0 if abs(p) > 3*q and cls.sens == u.sign(p) else 1 for k in self.watch: self.prep[k] += cls.sens*q * self.assets[cls.name].status[k] # greeks if/after filled self.prep["trades"].append( {"name":cls.name, "price":price, "quantity": cls.sens*q, "live": live} )
async def best_order1(self, a, q, lm=0, better=0, force_mod=False): better = better or self.sp["better"] sens = u.sign(q); cls = a.mbids if sens > 0 else a.masks p = cls.best_price() if not p: return {"price": 0} # there is no market price if best_price is 0 h = {"name":a.name, "price": p + sens*better, "quantity": q, "order_type": lm, "live": 1} self.debug("trading:", h) return await self.execute_trade(h, force_mod)
def json_representation(data, code, headers=None): resp = utils.json_dumps(data) signature = utils.sign(resp) response = make_response(resp, code) response.headers.extend(headers or {}) response.headers.add('signature', signature) response.headers.set("Content-Type", "application/json") return response
async def random(self, q=0): # this is stupid random trades. t = self m = t.master q = q or m.sp["quantity"] if random.random() < 0.5: # only trade 25% (0.5*0.5) of the time for k, a in t.assets.items(): # place new orders if random.random() < 0.5: continue # cancel half the time await m.best_order( a, u.sign(random.random() - 0.49) * (abs(q) or 1), "L")
async def christian(self): # this is stupid random trades. t = self m = t.master # mxcycles=2000 # if t.num == mxcycles: # t.info("final=", m.pairs) # throw(ValueError("done")) # parameters siz = size_of_spread = m.sp[ "quantity"] # todo: put in config both siz and step step = m.sp[ "step"] # we probably pay 0.04 to open and cancel spread, no point for less. To be tested m.store = {} for pair, pr in m.pairs.items(): pri = self.pairdiff(pair) if not pri: continue if not pr.get("pos"): pr.update({"pos": 0, "cur": 0}) pr["cur"] = pri # current price pos = pr["pos"] # current pos dma = pr["dma"] = pri - pr[ "avg"] # difference with the "real" price tgt = pr["tgt"] = -int(round(dma / step, 0)) # if dma > 0, we should sell sens = u.sign(tgt - pos) or 1 # ex: dma>0 -> tgt = -10, pos = -7, sign = sign(-3) = -1 def trade(): for i in range(pos, tgt, sens): if t.tradespread(siz * sens, pair): pr["pos"] += sens return pr["pos"] if tgt == 0 or u.sign(tgt) != u.sign(pr["pos"]): pos = trade() # came back to mean: liquidate position # if abs(pr["pos"]) - abs(tgt) > 6: pos = trade() # not yet to mean, but lock in some profit in case it goes back if abs(tgt) > abs(pos): trade() # increase position
def best_order(self, a, q, name="standing", lm="L", add=None, better=None, force_mod=False): if not q: return sens = u.sign(q); mcls = a.mbids if sens > 0 else a.masks; ocls = mcls.orders if lm == "M": return [ocls.place_order, {"name":a.name, "quantity": q, "order_type": lm}] p = mcls.best_price() if not p: return # there is no market price if best_price is 0 better = better if better != None else (self.sp["better"] or 0.01) pa = p+add if add != None else p + sens*better o = {"name":a.name, "price": pa, "quantity": q, "order_type": lm} allorders = ocls.get_live() x = exist = allorders[0] if len(allorders) else 0 # will modify the first order if it exists exc = lambda: [x.mock_modify_order, o] if exist else [ocls.place_order, o] return 0 if (x and abs(x.h["price"] - o["price"])<0.02) else exc()
async def add_fill(self, f): o = f.order oid = o.order_id fp = round(f.fill_price, 2) fq = round(f.filled_quantity * u.sign(o.quantity)) self.status["pos"] += fq self.status["cash"] -= fq * fp h = { "price": fp, "quantity": fq, "typ": "bids" if fq > 0 else "asks" } #, "size":abs(fq) self.info(f"filled-{oid[-6:]} ({fq} at {fp})", h) ok = self.exist_order(oid, "fill_order", p=o.price, q=o.quantity) h["ok"] = 1 if ok else 0 ok.fill(f) if ok else 0 return [h, f]
def fill(self, f): o = f.order oid = o.order_id op = round(f.fill_price, 2) oq = round(f.filled_quantity * u.sign(o.quantity)) if self.cancelled: self.warning("Sorry, cancelled order was filled:", self.show({"fill": oq})) def err(fv, typ, m): # check (well you never know....) msg = f'{self.all.name}: {m} {typ} when filling {self.sid}: {fv} vs {self.h[typ]} {self.h}' self.fatal(msg) diff_price = d = self.h["price"] - op if self.h["price"] else 0 if d != 0 and d * self.all.sens < 0: err(op, "price", "worse") if f.filled_quantity > abs(self.h["qleft"]): err(f.filled_quantity, 'quantity', 'too much') self.filled += oq self.h["qleft"] -= oq self.h["size"] -= f.filled_quantity if self.h["size"] <= 0: self.mark_cancelled() self.debug(f"filled-{self.sid}", self.show()) return self