Beispiel #1
0
    async def _snapshot(self, symbol: str):
        str_to_sign = "GET" + self.rest_endpoints[0].routes.l2book.format(
            symbol)
        headers = self.generate_token(str_to_sign)
        data = await self.http_conn.read(self.rest_endpoints[0].route(
            'l2book', self.sandbox).format(symbol),
                                         header=headers)
        timestamp = time.time()
        data = json.loads(data, parse_float=Decimal)
        data = data['data']
        self.seq_no[symbol] = int(data['sequence'])
        bids = {
            Decimal(price): Decimal(amount)
            for price, amount in data['bids']
        }
        asks = {
            Decimal(price): Decimal(amount)
            for price, amount in data['asks']
        }
        self._l2_book[symbol] = OrderBook(self.id,
                                          symbol,
                                          max_depth=self.max_depth,
                                          bids=bids,
                                          asks=asks)

        await self.book_callback(L2_BOOK,
                                 self._l2_book[symbol],
                                 timestamp,
                                 raw=data,
                                 sequence_number=int(data['sequence']))
Beispiel #2
0
    async def _snapshot(self, symbol: str):
        """
        {
            "id": 2679059670,
            "asks": [[price, amount], [...], ...],
            "bids": [[price, amount], [...], ...]
        }
        """
        url = f'https://api.gateio.ws/api/v4/spot/order_book?currency_pair={symbol}&limit=100&with_id=true'
        ret = await self.http_conn.read(url)
        data = json.loads(ret, parse_float=Decimal)

        symbol = self.exchange_symbol_to_std_symbol(symbol)
        self._l2_book[symbol] = OrderBook(self.id,
                                          symbol,
                                          max_depth=self.max_depth)
        self.last_update_id[symbol] = data['id']
        self._l2_book[symbol].book.bids = {
            Decimal(price): Decimal(amount)
            for price, amount in data['bids']
        }
        self._l2_book[symbol].book.asks = {
            Decimal(price): Decimal(amount)
            for price, amount in data['asks']
        }
        await self.book_callback(L2_BOOK,
                                 self._l2_book[symbol],
                                 time.time(),
                                 raw=data,
                                 sequence_number=data['id'])
Beispiel #3
0
    async def _pair_l2_update(self, msg: str, timestamp: float):
        delta = {BID: [], ASK: []}
        pair = self.exchange_symbol_to_std_symbol(msg['symbol'])
        if msg['event'] == 'snapshot':
            # Reset the book
            self._l2_book[pair] = OrderBook(self.id,
                                            pair,
                                            max_depth=self.max_depth)

        for side in (BID, ASK):
            for update in msg[side + 's']:
                price = update['px']
                qty = update['qty']
                self._l2_book[pair].book[side][price] = qty
                if qty <= 0:
                    del self._l2_book[pair].book[side][price]
                delta[side].append((price, qty))

        await self.book_callback(
            L2_BOOK,
            self._l2_book[pair],
            timestamp,
            raw=msg,
            delta=delta if msg['event'] != 'snapshot' else None,
            sequence_number=msg['seqnum'])
Beispiel #4
0
    async def _book_snapshot(self, msg: dict, pair: str, timestamp: float):
        """
        {
            "feed": "book_snapshot",
            "product_id": "PI_XBTUSD",
            "timestamp": 1565342712774,
            "seq": 30007298,
            "bids": [
                {
                    "price": 11735.0,
                    "qty": 50000.0
                },
                ...
            ],
            "asks": [
                {
                    "price": 11739.0,
                    "qty": 47410.0
                },
                ...
            ],
            "tickSize": null
        }
        """
        bids = {Decimal(update['price']): Decimal(update['qty']) for update in msg['bids']}
        asks = {Decimal(update['price']): Decimal(update['qty']) for update in msg['asks']}
        if pair in self._l2_book:
            self._l2_book[pair].book.bids = bids
            self._l2_book[pair].book.asks = asks
        else:
            self._l2_book[pair] = OrderBook(self.id, pair, max_depth=self.max_depth, bids=bids, asks=asks)

        self._l2_book[pair].timestamp = self.timestamp_normalize(msg["timestamp"]) if "timestamp" in msg else None

        await self.book_callback(L2_BOOK, self._l2_book[pair], timestamp, raw=msg, sequence_number=msg['seq'])
Beispiel #5
0
    async def _book_snapshot(self, pairs: list):
        # Coinbase needs some time to send messages to us
        # before we request the snapshot. If we don't sleep
        # the snapshot seq no could be much earlier than
        # the subsequent messages, causing a seq no mismatch.
        await asyncio.sleep(2)

        urls = [self.rest_endpoints[0].route('l3book', self.sandbox).format(pair) for pair in pairs]

        results = []
        for url in urls:
            ret = await self.http_conn.read(url)
            results.append(ret)
            # rate limit - 3 per second
            await asyncio.sleep(0.3)

        timestamp = time.time()
        for res, pair in zip(results, pairs):
            orders = json.loads(res, parse_float=Decimal)
            npair = self.exchange_symbol_to_std_symbol(pair)
            self._l3_book[npair] = OrderBook(self.id, pair, max_depth=self.max_depth)
            self.seq_no[npair] = orders['sequence']
            for side in (BID, ASK):
                for price, size, order_id in orders[side + 's']:
                    price = Decimal(price)
                    size = Decimal(size)
                    if price in self._l3_book[npair].book[side]:
                        self._l3_book[npair].book[side][price][order_id] = size
                    else:
                        self._l3_book[npair].book[side][price] = {order_id: size}
                    self.order_map[order_id] = (price, size)
            await self.book_callback(L3_BOOK, self._l3_book[npair], timestamp, raw=orders)
Beispiel #6
0
    async def _snapshot(self, pair: str) -> None:
        max_depth = self.max_depth if self.max_depth else 1000
        if max_depth not in self.valid_depths:
            for d in self.valid_depths:
                if d > max_depth:
                    max_depth = d
                    break

        url = f'{self.rest_endpoint}/depth?symbol={pair}&limit={max_depth}'
        resp = await self.http_conn.read(url)
        resp = json.loads(resp, parse_float=Decimal)

        std_pair = self.exchange_symbol_to_std_symbol(pair)
        self.last_update_id[std_pair] = resp['lastUpdateId']
        self._l2_book[std_pair] = OrderBook(
            self.id,
            std_pair,
            max_depth=self.max_depth,
            bids={Decimal(u[0]): Decimal(u[1])
                  for u in resp['bids']},
            asks={Decimal(u[0]): Decimal(u[1])
                  for u in resp['asks']})
        await self.book_callback(L2_BOOK,
                                 self._l2_book[std_pair],
                                 time.time(),
                                 timestamp=None,
                                 raw=resp,
                                 sequence_number=self.last_update_id[std_pair])
Beispiel #7
0
    async def _book_snapshot(self, msg: dict, timestamp: float):
        """
        {
            'jsonrpc': '2.0',
            'method': 'subscription',
            'params': {
                'channel': 'book.BTC-PERPETUAL.raw',
                'data': {
                    'timestamp': 1598232105378,
                    'instrument_name': 'BTC-PERPETUAL',
                    'change_id': 21486665526, '
                    'bids': [['new', Decimal('11618.5'), Decimal('279310.0')], ..... ]
                    'asks': [[ ....... ]]
                }
            }
        }
        """
        ts = msg["params"]["data"]["timestamp"]
        pair = self.exchange_symbol_to_std_symbol(msg["params"]["data"]["instrument_name"])
        self._l2_book[pair] = OrderBook(self.id, pair, max_depth=self.max_depth)
        self._l2_book[pair].book.bids = {Decimal(price): Decimal(amount) for _, price, amount in msg["params"]["data"]["bids"]}
        self._l2_book[pair].book.asks = {Decimal(price): Decimal(amount) for _, price, amount in msg["params"]["data"]["asks"]}
        self.seq_no[pair] = msg["params"]["data"]["change_id"]

        await self.book_callback(L2_BOOK, self._l2_book[pair], timestamp, timestamp=self.timestamp_normalize(ts), sequence_number=msg["params"]["data"]["change_id"], raw=msg)
Beispiel #8
0
 def _reset(self):
     self.partial_received = defaultdict(bool)
     self.order_id = {}
     self.open_orders = {}
     for pair in self.normalized_symbols:
         self._l2_book[pair] = OrderBook(self.id, pair, max_depth=self.max_depth)
         self.order_id[pair] = defaultdict(dict)
Beispiel #9
0
    async def _snapshot(self, pair: str) -> None:
        max_depth = self.max_depth if self.max_depth else 1000
        if max_depth not in self.valid_depths:
            for d in self.valid_depths:
                if d > max_depth:
                    max_depth = d
                    break

        resp = await self.http_conn.read(self.rest_endpoints[0].route(
            'l2book', self.sandbox).format(pair, max_depth))
        resp = json.loads(resp, parse_float=Decimal)
        timestamp = self.timestamp_normalize(
            resp['E']) if 'E' in resp else None

        std_pair = self.exchange_symbol_to_std_symbol(pair)
        self.last_update_id[std_pair] = resp['lastUpdateId']
        self._l2_book[std_pair] = OrderBook(
            self.id,
            std_pair,
            max_depth=self.max_depth,
            bids={Decimal(u[0]): Decimal(u[1])
                  for u in resp['bids']},
            asks={Decimal(u[0]): Decimal(u[1])
                  for u in resp['asks']})
        await self.book_callback(L2_BOOK,
                                 self._l2_book[std_pair],
                                 time.time(),
                                 timestamp=timestamp,
                                 raw=resp,
                                 sequence_number=self.last_update_id[std_pair])
Beispiel #10
0
    async def _book(self, msg: dict, timestamp: float):
        sequence_number = msg['data']['seqnum']
        pair = self.exchange_symbol_to_std_symbol(msg['symbol'])
        delta = {BID: [], ASK: []}

        if msg['m'] == 'depth-snapshot':
            self.seq_no[pair] = sequence_number
            self._l2_book[pair] = OrderBook(self.id, pair, max_depth=self.max_depth)
        else:
            # ignore messages while we wait for the snapshot
            if self.seq_no[pair] is None:
                return
            if self.seq_no[pair] + 1 != sequence_number:
                raise MissingSequenceNumber
            self.seq_no[pair] = sequence_number

        for side in ('bids', 'asks'):
            for price, amount in msg['data'][side]:
                s = BID if side == 'bids' else ASK
                price = Decimal(price)
                size = Decimal(amount)
                if size == 0:
                    delta[s].append((price, 0))
                    if price in self._l2_book[pair].book[s]:
                        del self._l2_book[pair].book[s][price]
                else:
                    delta[s].append((price, size))
                    self._l2_book[pair].book[s][price] = size

        await self.book_callback(L2_BOOK, self._l2_book[pair], timestamp, timestamp=self.timestamp_normalize(msg['data']['ts']), raw=msg, delta=delta if msg['m'] != 'depth-snapshot' else None, sequence_number=sequence_number)
Beispiel #11
0
    async def _book(self, msg: dict, timestamp: float):
        if msg['action'] == 'partial':
            # snapshot
            for update in msg['data']:
                pair = self.exchange_symbol_to_std_symbol(update['instrument_id'])
                bids = {Decimal(price): Decimal(amount) for price, amount, *_ in update['bids']}
                asks = {Decimal(price): Decimal(amount) for price, amount, *_ in update['asks']}
                self._l2_book[pair] = OrderBook(self.id, pair, max_depth=self.max_depth, checksum_format='OKCOIN', bids=bids, asks=asks)

                if self.checksum_validation and self._l2_book[pair].book.checksum() != (update['checksum'] & 0xFFFFFFFF):
                    raise BadChecksum
                await self.book_callback(L2_BOOK, self._l2_book[pair], timestamp, timestamp=self.timestamp_normalize(update['timestamp']), raw=msg, checksum=update['checksum'] & 0xFFFFFFFF)
        else:
            # update
            for update in msg['data']:
                delta = {BID: [], ASK: []}
                pair = self.exchange_symbol_to_std_symbol(update['instrument_id'])
                for side in ('bids', 'asks'):
                    s = BID if side == 'bids' else ASK
                    for price, amount, *_ in update[side]:
                        price = Decimal(price)
                        amount = Decimal(amount)
                        if amount == 0:
                            if price in self._l2_book[pair].book[s]:
                                delta[s].append((price, 0))
                                del self._l2_book[pair].book[s][price]
                        else:
                            delta[s].append((price, amount))
                            self._l2_book[pair].book[s][price] = amount

                if self.checksum_validation and self._l2_book[pair].book.checksum() != (update['checksum'] & 0xFFFFFFFF):
                    raise BadChecksum
                await self.book_callback(L2_BOOK, self._l2_book[pair], timestamp, timestamp=self.timestamp_normalize(update['timestamp']), raw=msg, delta=delta, checksum=update['checksum'] & 0xFFFFFFFF)
Beispiel #12
0
    async def _book(self, msg: dict, pair: str, timestamp: float):
        delta = {BID: [], ASK: []}
        msg = msg[1:-2]

        if 'as' in msg[0]:
            # Snapshot
            bids = {
                Decimal(update[0]): Decimal(update[1])
                for update in msg[0]['bs']
            }
            asks = {
                Decimal(update[0]): Decimal(update[1])
                for update in msg[0]['as']
            }
            self._l2_book[pair] = OrderBook(
                self.id,
                pair,
                max_depth=self.max_depth,
                bids=bids,
                asks=asks,
                checksum_format='KRAKEN',
                truncate=self.max_depth != self.valid_depths[-1])
            await self.book_callback(L2_BOOK,
                                     self._l2_book[pair],
                                     timestamp,
                                     raw=msg)
        else:
            for m in msg:
                for s, updates in m.items():
                    side = False
                    if s == 'b':
                        side = BID
                    elif s == 'a':
                        side = ASK
                    if side:
                        for update in updates:
                            price, size, *_ = update
                            price = Decimal(price)
                            size = Decimal(size)
                            if size == 0:
                                # Per Kraken's technical support
                                # they deliver erroneous deletion messages
                                # periodically which should be ignored
                                if price in self._l2_book[pair].book[side]:
                                    del self._l2_book[pair].book[side][price]
                                    delta[side].append((price, 0))
                            else:
                                delta[side].append((price, size))
                                self._l2_book[pair].book[side][price] = size

            if self.checksum_validation and 'c' in msg[0] and self._l2_book[
                    pair].book.checksum() != int(msg[0]['c']):
                raise BadChecksum("Checksum validation on orderbook failed")
            await self.book_callback(
                L2_BOOK,
                self._l2_book[pair],
                timestamp,
                delta=delta,
                raw=msg,
                checksum=int(msg[0]['c']) if 'c' in msg[0] else None)
Beispiel #13
0
    async def _book(self, msg: dict, timestamp: float):
        """
        {
            'ch':'market.BTC_CW.depth.step0',
            'ts':1565857755564,
            'tick':{
                'mrid':14848858327,
                'id':1565857755,
                'bids':[
                    [  Decimal('9829.99'), 1], ...
                ]
                'asks':[
                    [ 9830, 625], ...
                ]
            },
            'ts':1565857755552,
            'version':1565857755,
            'ch':'market.BTC_CW.depth.step0'
        }
        """
        pair = self.exchange_symbol_to_std_symbol(msg['ch'].split('.')[1])
        data = msg['tick']

        # When Huobi Delists pairs, empty updates still sent:
        # {'ch': 'market.AKRO-USD.depth.step0', 'ts': 1606951241196, 'tick': {'mrid': 50651100044, 'id': 1606951241, 'ts': 1606951241195, 'version': 1606951241, 'ch': 'market.AKRO-USD.depth.step0'}}
        # {'ch': 'market.AKRO-USD.depth.step0', 'ts': 1606951242297, 'tick': {'mrid': 50651100044, 'id': 1606951242, 'ts': 1606951242295, 'version': 1606951242, 'ch': 'market.AKRO-USD.depth.step0'}}
        if 'bids' in data and 'asks' in data:
            if pair not in self._l2_book:
                self._l2_book[pair] = OrderBook(self.id, pair, max_depth=self.max_depth)
            self._l2_book[pair].book.bids = {Decimal(price): Decimal(amount) for price, amount in data['bids']}
            self._l2_book[pair].book.asks = {Decimal(price): Decimal(amount) for price, amount in data['asks']}

            await self.book_callback(L2_BOOK, self._l2_book[pair], timestamp, timestamp=self.timestamp_normalize(msg['ts']), raw=msg)
Beispiel #14
0
    async def _book(self, msg: dict, timestamp: float):
        '''
        {
            'instrument_name': 'BTC_USDT',
            'subscription': 'book.BTC_USDT.150',
            'channel': 'book',
            'depth': 150,
            'data': [
                {
                    'bids': [
                        [Decimal('57553.03'), Decimal('0.481606'), 2],
                        [Decimal('57552.47'), Decimal('0.000418'), 1],
                        ...
                    ]
                    'asks': [
                        [Decimal('57555.44'), Decimal('0.343236'), 1],
                        [Decimal('57555.95'), Decimal('0.026062'), 1],
                        ...
                    ]
                }
            ]
        }
        '''
        pair = self.exchange_symbol_to_std_symbol(msg['instrument_name'])
        for entry in msg['data']:
            if pair not in self._l2_book:
                self._l2_book[pair] = OrderBook(self.id, pair, max_depth=self.max_depth)

            self._l2_book[pair].book.bids = {price: amount for price, amount, _ in entry['bids']}
            self._l2_book[pair].book.asks = {price: amount for price, amount, _ in entry['asks']}

            await self.book_callback(L2_BOOK, self._l2_book[pair], timestamp, timestamp=self.timestamp_normalize(entry['t']), raw=entry)
Beispiel #15
0
    async def _snapshot(self, symbol: str, sequence_number: int):
        while True:
            ret, headers = await self.http_conn.read(
                f'https://api.bittrex.com/v3/markets/{symbol}/orderbook?depth={self.__depth()}',
                return_headers=True)
            seq = int(headers['Sequence'])
            if seq >= sequence_number:
                break
            await asyncio.sleep(1.0)

        self.seq_no[symbol] = seq
        data = json.loads(ret, parse_float=Decimal)
        self._l2_book[symbol] = OrderBook(self.id,
                                          symbol,
                                          max_depth=self.max_depth)
        for side, entries in data.items():
            self._l2_book[symbol].book[side] = {
                Decimal(e['rate']): Decimal(e['quantity'])
                for e in entries
            }
        await self.book_callback(L2_BOOK,
                                 self._l2_book[symbol],
                                 time.time(),
                                 raw=data,
                                 sequence_number=seq)
Beispiel #16
0
    async def _snapshot(self, symbol: str, sequence_number: int):
        while True:
            ret, headers = await self.http_conn.read(
                self.rest_endpoints[0].route('l2book', self.sandbox).format(
                    symbol, self.__depth()),
                return_headers=True)
            seq = int(headers['Sequence'])
            if seq >= sequence_number:
                break
            await asyncio.sleep(1.0)

        self.seq_no[symbol] = seq
        data = json.loads(ret, parse_float=Decimal)
        self._l2_book[symbol] = OrderBook(self.id,
                                          symbol,
                                          max_depth=self.max_depth)
        for side, entries in data.items():
            self._l2_book[symbol].book[side] = {
                Decimal(e['rate']): Decimal(e['quantity'])
                for e in entries
            }
        await self.book_callback(L2_BOOK,
                                 self._l2_book[symbol],
                                 time.time(),
                                 raw=data,
                                 sequence_number=seq)
Beispiel #17
0
    async def _book(self, msg: dict, timestamp: float):
        """
        {
            "jsonrpc":"2.0",
            "method":"channelMessage",
            "params":{
                "channel":"lightning_board_BTC_JPY",
                "message":{
                    "mid_price":2534243.0,
                    "bids":[

                    ],
                    "asks":[
                        {
                        "price":2534500.0,
                        "size":0.0
                        },
                        {
                        "price":2536101.0,
                        "size":0.0
                        }
                    ]
                }
            }
        }
        """
        snapshot = msg['params']['channel'].startswith('lightning_board_snapshot')
        if snapshot:
            pair = msg['params']['channel'].split("lightning_board_snapshot")[1][1:]
        else:
            pair = msg['params']['channel'].split("lightning_board")[1][1:]
        pair = self.exchange_symbol_to_std_symbol(pair)

        # Ignore deltas until a snapshot is received
        if pair not in self._l2_book and not snapshot:
            return

        delta = None
        if snapshot:
            self._l2_book[pair] = OrderBook(self.id, pair, max_depth=self.max_depth)
        else:
            delta = {BID: [], ASK: []}

        data = msg['params']['message']
        for side in ('bids', 'asks'):
            s = BID if side == 'bids' else ASK
            if snapshot:
                self._l2_book[pair].book[side] = {d['price']: d['size'] for d in data[side]}
            else:
                for entry in data[side]:
                    if entry['size'] == 0:
                        if entry['price'] in self._l2_book[pair].book[side]:
                            del self._l2_book[pair].book[side][entry['price']]
                            delta[s].append((entry['price'], Decimal(0.0)))
                    else:
                        self._l2_book[pair].book[side][entry['price']] = entry['size']
                        delta[s].append((entry['price'], entry['size']))

        await self.book_callback(L2_BOOK, self._l2_book[pair], timestamp, raw=msg, delta=delta)
Beispiel #18
0
    async def l2_book(self, symbol: str, retry_count=1, retry_delay=60):
        ret = OrderBook(self.id, symbol)

        data = await self._get('orderBook/L2', self.std_symbol_to_exchange_symbol(symbol), retry_count, retry_delay)
        for update in data:
            side = ASK if update['side'] == 'Sell' else BID
            ret.book[side][decimal.Decimal(update['price'])] = decimal.Decimal(update['size'])
        return ret
Beispiel #19
0
 async def l2_book(self, symbol: str, retry_count=1, retry_delay=60):
     ret = OrderBook(self.id, symbol)
     sym = self.std_symbol_to_exchange_symbol(symbol)
     data = await self.http_conn.read(f"{self.api}/markets/{sym}/orderbook?depth=100", retry_count=retry_count, retry_delay=retry_delay)
     data = json.loads(data, parse_float=Decimal)['result']
     ret.book.bids = {u[0]: u[1] for u in data['bids']}
     ret.book.asks = {u[0]: u[1] for u in data['asks']}
     return ret
Beispiel #20
0
 async def l2_book(self, symbol: str, retry_count=1, retry_delay=60):
     ret = OrderBook(self.id, symbol)
     sym = self.std_symbol_to_exchange_symbol(symbol).replace("/", "")
     data = await self._post_public("/public/Depth", {'pair': sym, 'count': 200}, retry_count=retry_count, retry_delay=retry_delay)
     for _, val in data['result'].items():
         ret.book.bids = {Decimal(u[0]): Decimal(u[1]) for u in val['bids']}
         ret.book.asks = {Decimal(u[0]): Decimal(u[1]) for u in val['asks']}
         return ret
Beispiel #21
0
    async def _book(self, msg: dict, chan_id: int, timestamp: float):
        delta = {BID: [], ASK: []}
        msg_type = msg[0][0]
        pair = None
        # initial update (i.e. snapshot)
        if msg_type == 'i':
            delta = None
            pair = msg[0][1]['currencyPair']
            pair = self.exchange_symbol_to_std_symbol(pair)
            self._l2_book[pair] = OrderBook(self.id,
                                            pair,
                                            max_depth=self.max_depth)
            # 0 is asks, 1 is bids
            order_book = msg[0][1]['orderBook']
            for index, side in enumerate([ASK, BID]):
                for key in order_book[index]:
                    amount = Decimal(order_book[index][key])
                    price = Decimal(key)
                    self._l2_book[pair].book[side][price] = amount
        else:
            pair = self._channel_map[chan_id]
            pair = self.exchange_symbol_to_std_symbol(pair)
            for update in msg:
                msg_type = update[0]
                # order book update
                if msg_type == 'o':
                    side = ASK if update[1] == 0 else BID
                    price = Decimal(update[2])
                    amount = Decimal(update[3])
                    if amount == 0:
                        delta[side].append((price, 0))
                        del self._l2_book[pair].book[side][price]
                    else:
                        delta[side].append((price, amount))
                        self._l2_book[pair].book[side][price] = amount
                elif msg_type == 't':
                    # index 1 is trade id, 2 is side, 3 is price, 4 is amount, 5 is timestamp, 6 is timestamp ms
                    _, order_id, _, price, amount, server_ts, _ = update
                    price = Decimal(price)
                    amount = Decimal(amount)
                    t = Trade(self.id,
                              pair,
                              BUY if update[2] == 1 else SELL,
                              amount,
                              price,
                              float(server_ts),
                              id=order_id,
                              raw=msg)
                    await self.callback(TRADES, t, timestamp)
                else:
                    LOG.warning("%s: Unexpected message received: %s", self.id,
                                msg)

        await self.book_callback(L2_BOOK,
                                 self._l2_book[pair],
                                 timestamp,
                                 delta=delta,
                                 raw=msg)
Beispiel #22
0
 async def l2_book(self, symbol: str, retry_count=1, retry_delay=60):
     data = await self._request('GET',
                                f'/products/{symbol}/book?level=2',
                                retry_count=retry_count,
                                retry_delay=retry_delay)
     ret = OrderBook(self.id, symbol)
     ret.book.bids = {Decimal(u[0]): Decimal(u[1]) for u in data['bids']}
     ret.book.asks = {Decimal(u[0]): Decimal(u[1]) for u in data['asks']}
     return ret
Beispiel #23
0
 async def l2_book(self, symbol: str, retry_count=1, retry_delay=60):
     ret = OrderBook(self.id, symbol)
     sym = self.std_symbol_to_exchange_symbol(symbol)
     data = await self._get("returnOrderBook",
                            params=f"&currencyPair={sym}",
                            retry_count=retry_count,
                            retry_delay=retry_delay)
     ret.book.bids = {Decimal(u[0]): Decimal(u[1]) for u in data['bids']}
     ret.book.asks = {Decimal(u[0]): Decimal(u[1]) for u in data['asks']}
     return ret
Beispiel #24
0
    async def _snapshot(self, pairs: list, conn: AsyncConnection):
        await asyncio.sleep(5)
        urls = [f'https://www.bitstamp.net/api/v2/order_book/{sym}' for sym in pairs]
        results = [await self.http_conn.read(url) for url in urls]
        results = [json.loads(resp, parse_float=Decimal) for resp in results]

        for r, pair in zip(results, pairs):
            std_pair = self.exchange_symbol_to_std_symbol(pair) if pair else 'BTC-USD'
            self.last_update_id[std_pair] = r['timestamp']
            self._l2_book[std_pair] = OrderBook(self.id, std_pair, max_depth=self.max_depth, asks={Decimal(u[0]): Decimal(u[1]) for u in r['asks']}, bids={Decimal(u[0]): Decimal(u[1]) for u in r['bids']})
            await self.book_callback(L2_BOOK, self._l2_book[std_pair], time.time(), timestamp=float(r['timestamp']), raw=r)
Beispiel #25
0
    async def _pair_level2_snapshot(self, msg: dict, timestamp: float):
        pair = self.exchange_symbol_to_std_symbol(msg['product_id'])
        bids = {Decimal(price): Decimal(amount) for price, amount in msg['bids']}
        asks = {Decimal(price): Decimal(amount) for price, amount in msg['asks']}
        if pair not in self._l2_book:
            self._l2_book[pair] = OrderBook(self.id, pair, max_depth=self.max_depth, bids=bids, asks=asks)
        else:
            self._l2_book[pair].book.bids = bids
            self._l2_book[pair].book.asks = asks

        await self.book_callback(L2_BOOK, self._l2_book[pair], timestamp, raw=msg)
Beispiel #26
0
    async def _book(self, msg: dict, timestamp: float):
        """
        {
            'book': {
                'asks': [],
                'bids': [
                    [345475000, 14340]
                ]
            },
            'depth': 30,
            'sequence': 9047872983,
            'symbol': 'BTCUSD',
            'timestamp': 1625329629283990943,
            'type': 'incremental'
        }
        """
        symbol = self.exchange_symbol_to_std_symbol(msg['symbol'])
        ts = self.timestamp_normalize(msg['timestamp'])
        delta = {BID: [], ASK: []}

        if msg['type'] == 'snapshot':
            delta = None
            self._l2_book[symbol] = OrderBook(
                self.id,
                symbol,
                max_depth=self.max_depth,
                bids={
                    Decimal(entry[0]) / Decimal(self.price_scale[symbol]):
                    Decimal(entry[1])
                    for entry in msg['book']['bids']
                },
                asks={
                    Decimal(entry[0]) / Decimal(self.price_scale[symbol]):
                    Decimal(entry[1])
                    for entry in msg['book']['asks']
                })
        else:
            for key, side in (('asks', ASK), ('bids', BID)):
                for price, amount in msg['book'][key]:
                    price = Decimal(price) / Decimal(self.price_scale[symbol])
                    amount = Decimal(amount)
                    delta[side].append((price, amount))
                    if amount == 0:
                        # for some unknown reason deletes can be repeated in book updates
                        if price in self._l2_book[symbol].book[side]:
                            del self._l2_book[symbol].book[side][price]
                    else:
                        self._l2_book[symbol].book[side][price] = amount

        await self.book_callback(L2_BOOK,
                                 self._l2_book[symbol],
                                 timestamp,
                                 timestamp=ts,
                                 delta=delta)
Beispiel #27
0
    async def _book(self, pair: str, msg: list, timestamp: float):
        """For L2 book updates."""
        if not isinstance(msg[1], list):
            if msg[1] != 'hb':
                LOG.warning('%s: Unexpected book L2 msg %s', self.id, msg)
            return

        delta = None
        if isinstance(msg[1][0], list):
            # snapshot so clear book
            self._l2_book[pair] = OrderBook(self.id,
                                            pair,
                                            max_depth=self.max_depth)
            for update in msg[1]:
                price, _, amount = update
                price = Decimal(price)
                amount = Decimal(amount)

                if amount > 0:
                    side = BID
                else:
                    side = ASK
                    amount = abs(amount)
                self._l2_book[pair].book[side][price] = amount
        else:
            # book update
            delta = {BID: [], ASK: []}
            price, count, amount = msg[1]
            price = Decimal(price)
            amount = Decimal(amount)

            if amount > 0:
                side = BID
            else:
                side = ASK
                amount = abs(amount)

            if count > 0:
                # change at price level
                delta[side].append((price, amount))
                self._l2_book[pair].book[side][price] = amount
            else:
                # remove price level
                if price in self._l2_book[pair].book[side]:
                    del self._l2_book[pair].book[side][price]
                    delta[side].append((price, 0))

        await self.book_callback(L2_BOOK,
                                 self._l2_book[pair],
                                 timestamp,
                                 raw=msg,
                                 delta=delta,
                                 sequence_number=msg[-1])
Beispiel #28
0
    async def _book(self, msg: dict, timestamp: float):
        pair = self.exchange_symbol_to_std_symbol(msg['id'])
        delta = {BID: [], ASK: []}

        if msg['type'] == 'channel_data':
            updated = False
            offset = int(msg['contents']['offset'])
            for side, key in ((BID, 'bids'), (ASK, 'asks')):
                for data in msg['contents'][key]:
                    price = Decimal(data[0])
                    amount = Decimal(data[1])

                    if price in self._offsets[
                            pair] and offset < self._offsets[pair][price]:
                        continue

                    updated = True
                    self._offsets[pair][price] = offset
                    delta[side].append((price, amount))

                    if amount == 0:
                        if price in self._l2_book[pair].book[side]:
                            del self._l2_book[pair].book[side][price]
                    else:
                        self._l2_book[pair].book[side][price] = amount
            if updated:
                await self.book_callback(L2_BOOK,
                                         self._l2_book[pair],
                                         timestamp,
                                         delta=delta,
                                         raw=msg)
        else:
            # snapshot
            self._l2_book[pair] = OrderBook(self.id,
                                            pair,
                                            max_depth=self.max_depth)
            self._offsets[pair] = {}

            for side, data in msg['contents'].items():
                side = BID if side == 'bids' else ASK
                for entry in data:
                    self._offsets[pair][Decimal(entry['price'])] = int(
                        entry['offset'])
                    size = Decimal(entry['size'])
                    if size > 0:
                        self._l2_book[pair].book[side][Decimal(
                            entry['price'])] = size
            await self.book_callback(L2_BOOK,
                                     self._l2_book[pair],
                                     timestamp,
                                     delta=None,
                                     raw=msg)
Beispiel #29
0
    async def _book(self, msg: dict, ts: float):
        if 'snapshot' in msg:
            for pair, update in msg['snapshot'].items():
                symbol = self.exchange_symbol_to_std_symbol(pair)
                bids = {
                    Decimal(price): Decimal(size)
                    for price, size in update['b']
                }
                asks = {
                    Decimal(price): Decimal(size)
                    for price, size in update['a']
                }
                self._l2_book[symbol] = OrderBook(self.id,
                                                  pair,
                                                  max_depth=self.max_depth,
                                                  bids=bids,
                                                  asks=asks)
                await self.book_callback(L2_BOOK,
                                         self._l2_book[symbol],
                                         ts,
                                         sequence_number=update['s'],
                                         delta=None,
                                         raw=msg,
                                         timestamp=self.timestamp_normalize(
                                             update['t']))
                self.seq_no[symbol] = update['s']
        else:
            delta = {BID: [], ASK: []}
            for pair, update in msg['update'].items():
                symbol = self.exchange_symbol_to_std_symbol(pair)

                if self.seq_no[symbol] + 1 != update['s']:
                    raise MissingSequenceNumber
                self.seq_no[symbol] = update['s']

                for side, key in ((BID, 'b'), (ASK, 'a')):
                    for price, size in update[key]:
                        price = Decimal(price)
                        size = Decimal(size)
                        delta[side].append((price, size))
                        if size == 0:
                            del self._l2_book[symbol].book[side][price]
                        else:
                            self._l2_book[symbol].book[side][price] = size
                    await self.book_callback(
                        L2_BOOK,
                        self._l2_book[symbol],
                        ts,
                        sequence_number=update['s'],
                        delta=delta,
                        raw=msg,
                        timestamp=self.timestamp_normalize(update['t']))
Beispiel #30
0
 async def l2_book(self, symbol: str, retry_count=1, retry_delay=60):
     ret = OrderBook(self.id, symbol)
     sym = self.std_symbol_to_exchange_symbol(symbol)
     data = await self._get(f"/v1/book/{sym}", retry_count, retry_delay)
     ret.book.bids = {
         Decimal(u['price']): Decimal(u['amount'])
         for u in data['bids']
     }
     ret.book.asks = {
         Decimal(u['price']): Decimal(u['amount'])
         for u in data['asks']
     }
     return ret