def orderDictToOrder(o): sideMulti = 1 if o["side"] == "Buy" else -1 ext = o['ext_fields'] if 'ext_fields' in o.keys() else None stop = o['trigger_price'] if 'trigger_price' in o.keys() else None if stop is None: stop = o['stop_px'] if 'stop_px' in o.keys() else None if stop is None and ext is not None and 'trigger_price' in ext.keys(): stop = ext['trigger_price'] order = Order( orderId=o["order_link_id"], stop=float(stop) if stop is not None else None, limit=float(o["price"]) if o['order_type'] == 'Limit' else None, amount=float(o["qty"] * sideMulti)) if "order_status" in o.keys(): order.stop_triggered = o[ "order_status"] == "New" and stop is not None order.active = o['order_status'] == 'New' or o[ 'order_status'] == 'Untriggered' elif "stop_order_status" in o.keys(): order.stop_triggered = o["stop_order_status"] == 'Triggered' or o[ 'stop_order_status'] == 'Active' order.active = o['stop_order_status'] == 'Triggered' or o[ 'stop_order_status'] == 'Untriggered' exec = o['cum_exec_qty'] if 'cum_exec_qty' in o.keys() else 0 order.executed_amount = float(exec) * sideMulti order.tstamp = parse_utc_timestamp(o['timestamp'] if 'timestamp' in o.keys() else o['created_at']) order.exchange_id = o["order_id"] if 'order_id' in o.keys( ) else o['stop_order_id'] order.executed_price = None if 'cum_exec_value' in o.keys() and 'cum_exec_qty' in o.keys( ) and float(o['cum_exec_value']) != 0: order.executed_price = o['cum_exec_qty'] / float( o["cum_exec_value"]) # cause of inverse return order
def _websocket_callback(self, table): if self.bitmex is None: #not started yet return if table == 'trade': trades = self.bitmex.recent_trades_and_clear() if len(self.h1Bars) == 0: return for trade in trades: tstamp = parse_utc_timestamp(trade['timestamp']) bar = self.h1Bars[0] if bar is not None and bar.last_tick_tstamp > tstamp: continue #trade already counted barstamp = int(tstamp / (60 * 60)) * 60 * 60 price = float(trade['price']) size = float(trade['size']) if bar is not None and barstamp == bar.tstamp: bar.high = max(bar.high, price) bar.low = min(bar.low, price) bar.close = price bar.volume = bar.volume + size bar.last_tick_tstamp = tstamp elif len(self.h1Bars) == 0 or barstamp > bar.tstamp: self.h1Bars.insert( 0, Bar(tstamp=barstamp, open=price, high=price, low=price, close=price, volume=size)) elif table == 'tradeBin1h': dicts = self.bitmex.recent_H1_bars() bars = [] for d in dicts: bars.append(self.barDictToBar(d, 60)) bars.sort(key=lambda b: b.tstamp, reverse=False) # order with latest bar first # merge into self.h1Bars for b in bars: if b.tstamp > self.h1Bars[0].tstamp: #newer than newest in history self.h1Bars.insert(0, b) else: for i in range(len(self.h1Bars)): if b.tstamp == self.h1Bars[i].tstamp: self.h1Bars[i] = b break if self.on_tick_callback is not None and table in [ "tradeBin1h", "order", "execution" ]: self.on_tick_callback( fromAccountAction=table in ["order", "execution"])
def barDictToBar(b, barLengthMinutes): if 'tstamp' not in b.keys(): b['tstamp'] = parse_utc_timestamp( b['timestamp'] ) - barLengthMinutes * 60 # bitmex uses endtime for bar timestamp return Bar(tstamp=b['tstamp'], open=b['open'], high=b['high'], low=b['low'], close=b['close'], volume=b['volume'])
def get_orders(self) -> List[Order]: mexOrders = self.bitmex.open_orders() result: List[Order] = [] for o in mexOrders: sideMulti = 1 if o["side"] == "Buy" else -1 order = Order(orderId=o["clOrdID"], stop=o["stopPx"], limit=o["price"], amount=o["orderQty"] * sideMulti) order.stop_triggered = o["triggered"] == "StopOrderTriggered" order.executed_amount = (o["cumQty"]) * sideMulti order.tstamp = parse_utc_timestamp(o['timestamp']) order.execution_tstamp = order.tstamp order.active = o['ordStatus'] == 'New' order.exchange_id = o["orderID"] order.executed_price = o["avgPx"] result.append(order) return result
def socket_callback(self, topic): try: data = self.ws.get_data(topic) gotTick = False while len(data) > 0: if topic == 'trade': tstamp = parse_utc_timestamp(data['time']) bar_time = math.floor(tstamp / 60) * 60 price = float(data['price']) volume = float(data['last_size']) isBuy = data['side'] == "buy" if len(self.m1_bars ) > 0 and self.m1_bars[-1].tstamp == bar_time: last_bar = self.m1_bars[-1] else: last_bar = Bar(tstamp=bar_time, open=price, high=price, low=price, close=price, volume=0) self.m1_bars.append(last_bar) gotTick = True last_bar.close = price last_bar.low = min(last_bar.low, price) last_bar.high = max(last_bar.high, price) last_bar.volume += volume last_bar.last_tick_tstamp = tstamp if isBuy: last_bar.buyVolume += volume else: last_bar.sellVolume += volume data = self.ws.get_data(topic) # new bars is handling directly in the messagecause we get a new one on each tick if gotTick and self.on_tick_callback is not None: self.on_tick_callback(fromAccountAction=False) except Exception as e: self.logger.error("error in socket data(%s): %s " % (topic, str(e)))
if exchange == 'bybit': url = URL + "&from=" + str(start) print(url+" __ "+str(len(result))) r = requests.get(url=url) # extracting data in json format data= r.json() if exchange == 'bybit': data = r.json()["result"] if len(data) < 200: print(str(data)[:100]) sleep(10) else: wroteData= False if exchange == 'bitmex': for b in data: b['tstamp'] = parse_utc_timestamp(b['timestamp']) result += data lastSync += len(data) start = int(data[-1]['open_time'])+1 if exchange == 'bybit' else start + len(data) if lastSync > 15000 or (len(data) < 200 and not wroteData): wroteData= True lastSync= 0 max= math.ceil((len(result)+offset)/batchsize) idx= max - 2 while idx < max: if idx*batchsize-offset >= 0: with open('history/'+exchange+'/M1_'+str(idx)+'.json','w') as file: json.dump(result[idx*batchsize-offset:(idx+1)*batchsize-offset],file) print("wrote file "+str(idx)) idx += 1
def socket_callback(self, topic): try: gotTick = False msgs = self.ws.get_data(topic) while len(msgs) > 0: if topic == 'order' or topic == 'stop_order': # {'order_id': '96319991-c6ac-4ad5-bdf8-a5a79b624951', 'order_link_id': '', 'symbol': 'BTCUSD', # 'side': 'Buy', 'order_type': 'Limit', 'price': '7325.5', 'qty': 1, 'time_in_force': # 'GoodTillCancel', 'order_status': 'Filled', 'leaves_qty': 0, 'cum_exec_qty': 1, # 'cum_exec_value': '0.00013684', 'cum_exec_fee': '0.00000011', 'timestamp': # '2019-12-26T20:02:19.576Z', 'take_profit': '0', 'stop_loss': '0', 'trailing_stop': '0', # 'last_exec_price': '7307.5'} for o in msgs: if o['symbol'] != self.symbol: continue # ignore orders not of my symbol order = self.orderDictToOrder(o) prev: Order = self.orders[ order.exchange_id] if order.exchange_id in self.orders.keys() else None if prev is not None: if prev.tstamp > order.tstamp or abs(prev.executed_amount) > abs(order.executed_amount): # already got newer information, probably the info of the stop order getting # triggered, when i already got the info about execution self.logger.info("ignoring delayed update for %s " % prev.id) continue # ws removes stop price when executed if order.stop_price is None: order.stop_price = prev.stop_price order.stop_triggered = True # there was a stop and its no longer there -> it was triggered and order turned to linear if order.limit_price is None: order.limit_price = prev.limit_price prev = order if not prev.active and prev.execution_tstamp == 0: prev.execution_tstamp = datetime.utcnow().timestamp() self.orders[order.exchange_id] = prev self.logger.info("order update: %s" % (str(order))) elif topic == 'execution': # {'symbol': 'BTCUSD', 'side': 'Buy', 'order_id': '96319991-c6ac-4ad5-bdf8-a5a79b624951', # 'exec_id': '22add7a8-bb15-585f-b068-3a8648f6baff', 'order_link_id': '', 'price': '7307.5', # 'order_qty': 1, 'exec_type': 'Trade', 'exec_qty': 1, 'exec_fee': '0.00000011', 'leaves_qty': 0, # 'is_maker': False, 'trade_time': '2019-12-26T20:02:19.576Z'} for execution in msgs: if execution['order_id'] in self.orders.keys(): sideMulti = 1 if execution['side'] == "Buy" else -1 order = self.orders[execution['order_id']] order.executed_amount = (execution['order_qty'] - execution['leaves_qty']) * sideMulti if (order.executed_amount - order.amount) * sideMulti >= 0: order.active = False self.on_execution_callback(order_id=order.id, executed_price=float(execution['price']), amount=execution['exec_qty'] * sideMulti, tstamp=parse_utc_timestamp(execution['trade_time'])) self.logger.info("got order execution: %s %.3f @ %.2f " % ( execution['order_link_id'], execution['exec_qty'] * sideMulti, float(execution['price']))) elif topic == 'wallet': for wallet in msgs: self.longPos.walletBalance = float(wallet["wallet_balance"]) self.shortPos.walletBalance = float(wallet["wallet_balance"]) self.updatePosition_internally() elif topic == 'position': # {'user_id': 712961, 'symbol': 'BTCUSD', 'size': 1, 'side': 'Buy', 'position_value': # '0.00013684', 'entry_price': '7307.80473546', 'liq_price': '6674', 'bust_price': '6643.5', # 'leverage': '10', 'order_margin': '0', 'position_margin': '0.00001369', 'available_balance': # '0.17655005', 'take_profit': '0', 'stop_loss': '0', 'realised_pnl': '-0.00000011', # 'trailing_stop': '0', 'wallet_balance': '0.17656386', 'risk_id': 1, 'occ_closing_fee': # '0.00000012', 'occ_funding_fee': '0', 'auto_add_margin': 0, 'cum_realised_pnl': '0.00175533', # 'position_status': 'Normal', 'position_seq': 505770784} for pos in msgs: if pos['symbol'] == self.symbol: if pos["side"] == "Sell": self.shortPos.quantity = -float(pos['size']) self.shortPos.avgEntryPrice = float(pos['entry_price']) else: self.longPos.quantity = float(pos['size']) self.longPos.avgEntryPrice = float(pos['entry_price']) self.updatePosition_internally() elif topic.startswith('candle.') and topic.endswith('.' + self.symbol): msgs.sort(key=lambda temp: temp['start'], reverse=True) if len(self.bars) > 0: for b in reversed(msgs): if self.bars[0]['start'] >= b['start'] >= self.bars[-1]['start']: # find bar to fix for idx in range(0, len(self.bars)): if b['start'] == self.bars[idx]['start']: self.bars[idx] = b break elif b['start'] > self.bars[0]['start']: self.bars.insert(0, b) gotTick = True # ignore old bars else: self.bars = msgs gotTick = True elif topic == 'instrument_info.100ms.' + self.symbol: obj = msgs if 'update' in obj.keys(): obj = obj['update'][0] if obj['symbol'] == self.symbol and 'last_price_e4' in obj.keys(): self.last = float(obj['last_price_e4']) / 10000 else: self.logger.error('got unkown topic in callback: ' + topic) msgs = self.ws.get_data(topic) # new bars is handling directly in the messagecause we get a new one on each tick if topic in ["order", "stop_order", "execution", "wallet"]: gotTick = True self.reset_order_sync_timer() # only when something with orders changed if gotTick and self.on_tick_callback is not None: self.on_tick_callback( fromAccountAction=topic in ["order", "stop_order", "execution", "wallet"]) # got something new except Exception as e: self.logger.error("error in socket data(%s): %s " % (topic, str(e)))