Esempio n. 1
0
 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
Esempio n. 2
0
    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"])
Esempio n. 3
0
 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'])
Esempio n. 4
0
    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)))
Esempio n. 6
0
    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)))