Ejemplo n.º 1
0
 def __init__(self, product_id='BTC-USD'):
     print("Initializing order Book websocket for " + product_id)
     self.product = product_id
     super(GDaxBook, self).__init__(products=[self.product])
     super(GDaxBook, self).start()
     self._asks = RBTree()
     self._bids = RBTree()
     self._client = PublicClient()
     self._sequence = -1
     self._current_ticker = None
Ejemplo n.º 2
0
 def __init__(self, product_id='BTC-USD', log_to=None):
     super(OrderBook, self).__init__(products=product_id)
     self._asks = RBTree()
     self._bids = RBTree()
     self._client = PublicClient()
     self._sequence = -1
     self._log_to = log_to
     if self._log_to:
         assert hasattr(self._log_to, 'write')
     self._current_ticker = None
Ejemplo n.º 3
0
 def __init__(self, product_id='BTC-USD', windowSize=30):
     super(AutoBot, self).__init__(products=product_id, channels=['ticker'])
     self._client = PublicClient()
     self._sequence = -1
     self._current_ticker = None
     self._queue = deque([], windowSize)
     self._window_size = windowSize
     self._last_average = 0
     self._ownedCoins = 0
Ejemplo n.º 4
0
    def __init__(self,
                 product_id='BTC-USD',
                 log_to=None,
                 autoreconnect=True,
                 max_retries=3):
        super(OrderBook, self).__init__(products=[product_id])

        self.channels = ['full']

        self._asks = RBTree()
        self._bids = RBTree()
        self._client = PublicClient()
        self._sequence = -1
        self._log_to = log_to
        self._retries = 0
        self._max_retries = max_retries
        self._autoreconnect = autoreconnect
        self._is_ready = False
        if self._log_to:
            assert hasattr(self._log_to, 'write')
        self._current_ticker = None
Ejemplo n.º 5
0
 def __init__(self, key, secret, passphrase, product):
     self.key = key
     self.secret = secret
     self.passphrase = passphrase
     self.product = product
     self.websocket_client = WebsocketClient()
     self.order_book = OrderBook(product_id=product)
     self.auth_client = AuthenticatedClient(key, secret, passphrase)
     self.public_client = PublicClient()
     self.sells = []
     self.buys = []
     self.sell_tracker = 0
     self.buy_tracker = 0
     self.sell_fees = 0
     self.buy_fees = 0
     self.num_buys = 0
     self.num_sells = 0
     self.av_sell = 0
     self.av_buy = 0
     self.last_buy = 0
     self.last_sell = 0
     self.current_balance = 0
     self.ticker_tracker = []
Ejemplo n.º 6
0
 def __init__(self,
              url="wss://ws-feed.gdax.com",
              product_id='BTC-USD',
              auth=False,
              api_key="",
              api_secret="",
              api_passphrase="",
              log_to=None):
     super(OrderBook, self).__init__(url=url,
                                     products=product_id,
                                     auth=auth,
                                     api_key=api_key,
                                     api_secret=api_secret,
                                     api_passphrase=api_passphrase)
     print("------------------------------orderbook url:", url)
     self._asks = RBTree()
     self._bids = RBTree()
     self._client = PublicClient()
     self._sequence = -1
     self._log_to = log_to
     if self._log_to:
         assert hasattr(self._log_to, 'write')
     self._current_ticker = None
Ejemplo n.º 7
0
    def __init__(self, saveMessage=0, product_id='BTC-USD'):

        self.url = "wss://ws-feed.gdax.com/"
        self.ws = create_connection(self.url)
        self.product_id = product_id
        self.sequence = -1
        self.stop = False
        self._sequence = -1
        self._client = PublicClient()
        self._asks = RBTree()
        self._bids = RBTree()
        self._current_ticker = None
        self.saveMessage = saveMessage
        self.t1 = None
        self.t2 = None
        self.t3 = None
Ejemplo n.º 8
0
    def __init__(self):
        self.binanceClient = BinanceClient(BinanceSettings.api_key,
                                           BinanceSettings.api_secret)
        self.gdax_public_client = GdaxPublicClient()
        self.gdax_authenticated_client = GdaxAuthenticatedClient(
            key=GdaxSettings.api_key,
            b64secret=GdaxSettings.api_secret,
            passphrase=GdaxSettings.api_passphrase)
        self.sandbox_gdax_authenticated_client = GdaxAuthenticatedClient(
            key=GdaxSettings.sandbox_key,
            b64secret=GdaxSettings.sandbox_secret,
            passphrase=GdaxSettings.sandbox_passphrase,
            api_url='https://api-public.sandbox.gdax.com')
        self.kraken_public_client = KrakenAPI()

        self.MARKET_BINANCE = 'binance'
        self.MARKET_GDAX = 'gdax'
        self.MARKET_KRAKEN = 'kraken'
Ejemplo n.º 9
0
 def __init__(self, product_id='BTC-USD'):
     super(OrderBook, self).__init__(products=product_id)
     self._asks = RBTree()
     self._bids = RBTree()
     self._client = PublicClient(product_id=product_id)
     self._sequence = -1
Ejemplo n.º 10
0
class OrderBook(WebsocketClient):
    def __init__(self, product_id='BTC-USD', log_to=None):
        super(OrderBook, self).__init__(products=product_id)
        self._asks = RBTree()
        self._bids = RBTree()
        self._client = PublicClient()
        self._sequence = -1
        self._log_to = log_to
        if self._log_to:
            assert hasattr(self._log_to, 'write')
        self._current_ticker = None

    @property
    def product_id(self):
        ''' Currently OrderBook only supports a single product even though it is stored as a list of products. '''
        return self.products[0]

    def on_message(self, message):
        if self._log_to:
            pickle.dump(message, self._log_to)

        sequence = message['sequence']
        if self._sequence == -1:
            self._asks = RBTree()
            self._bids = RBTree()
            res = self._client.get_product_order_book(product_id=self.product_id, level=3)
            for bid in res['bids']:
                self.add({
                    'id': bid[2],
                    'side': 'buy',
                    'price': Decimal(bid[0]),
                    'size': Decimal(bid[1])
                })
            for ask in res['asks']:
                self.add({
                    'id': ask[2],
                    'side': 'sell',
                    'price': Decimal(ask[0]),
                    'size': Decimal(ask[1])
                })
            self._sequence = res['sequence']

        if sequence <= self._sequence:
            # ignore older messages (e.g. before order book initialization from getProductOrderBook)
            return
        elif sequence > self._sequence + 1:
            print('Error: messages missing ({} - {}). Re-initializing websocket.'.format(sequence, self._sequence))
            self.close()
            self.start()
            return

        msg_type = message['type']
        if msg_type == 'open':
            self.add(message)
        elif msg_type == 'done' and 'price' in message:
            self.remove(message)
        elif msg_type == 'match':
            self.match(message)
            self._current_ticker = message
        elif msg_type == 'change':
            self.change(message)

        self._sequence = sequence

        # bid = self.get_bid()
        # bids = self.get_bids(bid)
        # bid_depth = sum([b['size'] for b in bids])
        # ask = self.get_ask()
        # asks = self.get_asks(ask)
        # ask_depth = sum([a['size'] for a in asks])
        # print('bid: %f @ %f - ask: %f @ %f' % (bid_depth, bid, ask_depth, ask))

    def on_error(self, e):
        self._sequence = -1
        self.close()
        self.start()

    def add(self, order):
        order = {
            'id': order.get('order_id') or order['id'],
            'side': order['side'],
            'price': Decimal(order['price']),
            'size': Decimal(order.get('size') or order['remaining_size'])
        }
        if order['side'] == 'buy':
            bids = self.get_bids(order['price'])
            if bids is None:
                bids = [order]
            else:
                bids.append(order)
            self.set_bids(order['price'], bids)
        else:
            asks = self.get_asks(order['price'])
            if asks is None:
                asks = [order]
            else:
                asks.append(order)
            self.set_asks(order['price'], asks)

    def remove(self, order):
        price = Decimal(order['price'])
        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if bids is not None:
                bids = [o for o in bids if o['id'] != order['order_id']]
                if len(bids) > 0:
                    self.set_bids(price, bids)
                else:
                    self.remove_bids(price)
        else:
            asks = self.get_asks(price)
            if asks is not None:
                asks = [o for o in asks if o['id'] != order['order_id']]
                if len(asks) > 0:
                    self.set_asks(price, asks)
                else:
                    self.remove_asks(price)

    def match(self, order):
        size = Decimal(order['size'])
        price = Decimal(order['price'])

        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if not bids:
                return
            assert bids[0]['id'] == order['maker_order_id']
            if bids[0]['size'] == size:
                self.set_bids(price, bids[1:])
            else:
                bids[0]['size'] -= size
                self.set_bids(price, bids)
        else:
            asks = self.get_asks(price)
            if not asks:
                return
            assert asks[0]['id'] == order['maker_order_id']
            if asks[0]['size'] == size:
                self.set_asks(price, asks[1:])
            else:
                asks[0]['size'] -= size
                self.set_asks(price, asks)

    def change(self, order):
        try:
            new_size = Decimal(order['new_size'])
        except KeyError:
            return
            
        price = Decimal(order['price'])

        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if bids is None or not any(o['id'] == order['order_id'] for o in bids):
                return
            index = [b['id'] for b in bids].index(order['order_id'])
            bids[index]['size'] = new_size
            self.set_bids(price, bids)
        else:
            asks = self.get_asks(price)
            if asks is None or not any(o['id'] == order['order_id'] for o in asks):
                return
            index = [a['id'] for a in asks].index(order['order_id'])
            asks[index]['size'] = new_size
            self.set_asks(price, asks)

        tree = self._asks if order['side'] == 'sell' else self._bids
        node = tree.get(price)

        if node is None or not any(o['id'] == order['order_id'] for o in node):
            return

    def get_current_ticker(self):
        return self._current_ticker

    def get_current_book(self):
        result = {
            'sequence': self._sequence,
            'asks': [],
            'bids': [],
        }
        for ask in self._asks:
            try:
                # There can be a race condition here, where a price point is removed
                # between these two ops
                this_ask = self._asks[ask]
            except KeyError:
                continue
            for order in this_ask:
                result['asks'].append([order['price'], order['size'], order['id']])
        for bid in self._bids:
            try:
                # There can be a race condition here, where a price point is removed
                # between these two ops
                this_bid = self._bids[bid]
            except KeyError:
                continue

            for order in this_bid:
                result['bids'].append([order['price'], order['size'], order['id']])
        return result

    def get_ask(self):
        return self._asks.min_key()

    def get_asks(self, price):
        return self._asks.get(price)

    def remove_asks(self, price):
        self._asks.remove(price)

    def set_asks(self, price, asks):
        self._asks.insert(price, asks)

    def get_bid(self):
        return self._bids.max_key()

    def get_bids(self, price):
        return self._bids.get(price)

    def remove_bids(self, price):
        self._bids.remove(price)

    def set_bids(self, price, bids):
        self._bids.insert(price, bids)
Ejemplo n.º 11
0
class Interface:
    def __init__(self):
        self.binanceClient = BinanceClient(BinanceSettings.api_key,
                                           BinanceSettings.api_secret)
        self.gdax_public_client = GdaxPublicClient()
        self.gdax_authenticated_client = GdaxAuthenticatedClient(
            key=GdaxSettings.api_key,
            b64secret=GdaxSettings.api_secret,
            passphrase=GdaxSettings.api_passphrase)
        self.sandbox_gdax_authenticated_client = GdaxAuthenticatedClient(
            key=GdaxSettings.sandbox_key,
            b64secret=GdaxSettings.sandbox_secret,
            passphrase=GdaxSettings.sandbox_passphrase,
            api_url='https://api-public.sandbox.gdax.com')
        self.kraken_public_client = KrakenAPI()

        self.MARKET_BINANCE = 'binance'
        self.MARKET_GDAX = 'gdax'
        self.MARKET_KRAKEN = 'kraken'

    def get_prices(self, exchange):
        if exchange == self.MARKET_BINANCE:
            market_books = self.binanceClient.get_products_and_prices()
        elif exchange == self.MARKET_GDAX:
            market_books = self.gdax_public_client.get_products_with_prices()
        elif exchange == self.MARKET_KRAKEN:
            market_books = self.kraken_public_client.get_market_tickers()
        else:
            print("No exchange found with name: " + exchange)
            # TODO throw exception
        return market_books

    def create_test_order(self,
                          exchange,
                          symbol,
                          side,
                          limit_market,
                          quantity,
                          price=0.0):
        if exchange == self.MARKET_BINANCE:
            response = self.binanceClient.create_test_order(symbol=symbol,
                                                            side=side,
                                                            type=limit_market,
                                                            quantity=quantity,
                                                            price=price,
                                                            timeInForce="GTC")
            print("order is filled")
            # The binance test order does not actually get passed to the matching engine, so we're unable to test this.

        if exchange == self.MARKET_GDAX:
            symbol_reformatted = symbol[:3] + "-" + symbol[
                3:]  # TODO is this correct?
            response = self.sandbox_gdax_authenticated_client.create_order(
                symbol=symbol_reformatted,
                side=side,
                limit_market=limit_market,
                quantity=quantity,
                price=price)
            order_id = response["id"]
            order_filled = False
            while not order_filled:
                order = self.sandbox_gdax_authenticated_client.get_order(
                    order_id)
                if order["status"] == "done":
                    print("order is filled!")
                    order_filled = True
                else:
                    print("order not yet filled")
                    time.sleep(5)

    def create_order(self,
                     exchange,
                     symbol,
                     side,
                     limit_market,
                     quantity,
                     price=0.0):
        if exchange == self.MARKET_BINANCE:
            order = self.binanceClient.create_order(symbol,
                                                    side,
                                                    quantity,
                                                    price,
                                                    type=limit_market)
        elif exchange == self.MARKET_GDAX:
            order = self.gdax_authenticated_client.create_order(
                symbol, side, limit_market, quantity, price)
        else:
            print("No exchange found with name: " + exchange)
            # TODO throw exception
        print(order)

    def order_filled(self, exchange, order_id):
        if exchange == self.MARKET_BINANCE:
            return self.binanceClient.get_order(order_id)['status'] == 'done'
        elif exchange == self.MARKET_GDAX:
            return self.gdax_authenticated_client.get_order(
                order_id)['status'] == 'done'
        else:
            return ''
Ejemplo n.º 12
0
class Bot(object):
    def __init__(self, key, secret, passphrase, product):
        self.key = key
        self.secret = secret
        self.passphrase = passphrase
        self.product = product
        self.websocket_client = WebsocketClient()
        self.order_book = OrderBook(product_id=product)
        self.auth_client = AuthenticatedClient(key, secret, passphrase)
        self.public_client = PublicClient()
        self.sells = []
        self.buys = []
        self.sell_tracker = 0
        self.buy_tracker = 0
        self.sell_fees = 0
        self.buy_fees = 0
        self.num_buys = 0
        self.num_sells = 0
        self.av_sell = 0
        self.av_buy = 0
        self.last_buy = 0
        self.last_sell = 0
        self.current_balance = 0
        self.ticker_tracker = []

    def get_order_info(self, ticker, number_measures, length_measures,
                       order_book_skim):

        bid_intervals = []
        bid_depths_intervals = []
        ask_intervals = []
        ask_depths_intervals = []
        count = 1
        while count <= number_measures:
            print('Volume check %s' % count)
            time.sleep(length_measures)
            current_order_book = self.order_book.get_current_book()
            bids, bid_depths, asks, ask_depths = sort_messages(
                ticker, current_order_book, order_book_skim)
            bid_intervals.append(bids)
            ask_intervals.append(asks)
            bid_depths_intervals.append(bid_depths)
            ask_depths_intervals.append(ask_depths)
            count += 1

        return bid_intervals, bid_depths_intervals, ask_intervals, ask_depths_intervals

    def check_volatility(self, volatility_interval, num_volatility_measures):
        if len(self.ticker_tracker) > num_volatility_measures + 1:
            delta_price = np.diff(self.ticker_tracker)
            vol_measure = np.average(delta_price[-num_volatility_measures:])

        else:
            vol_measure = 0

        return abs(vol_measure)

    def start_order_book(self):
        self.order_book.start()

    def order_book_repeat_sample(self, duration, order_book_skim):

        with open('crypto_data.csv', 'w') as csv_file:
            writer = csv.writer(
                csv_file,
                delimiter='\t',
                lineterminator='\n',
            )
            header = [
                'datetime', 'ticker price', 'average bid', 'average ask',
                'bid volume', 'ask volume'
            ]
            writer.writerow(header)
            while True:
                ticker = float(
                    self.public_client.get_product_ticker(
                        self.product)['price'])
                current_order_book = self.order_book.get_current_book()
                bids, bid_depths, asks, ask_depths = sort_messages(
                    ticker, current_order_book, order_book_skim)

                if len(bids) != 0 and len(asks) != 0 and len(
                        bid_depths) != 0 and len(ask_depths) != 0:
                    print(bids[1])
                    print(bids[2])
                    av_bid = np.average(bids)
                    av_ask = np.average(asks)
                    total_bids = np.sum(bid_depths)
                    total_asks = np.sum(ask_depths)
                else:
                    av_bid = 'N/A'
                    av_ask = 'N/A'
                    total_bids = 'N/A'
                    total_asks = 'N/A'
                print('Average bid', av_bid)
                print('Average ask', av_ask)
                print('total bid volume', total_bids)
                print('total ask volume', total_asks)
                data = [
                    datetime.datetime.now(), ticker, av_bid, av_ask,
                    total_bids, total_asks
                ]
                writer.writerow(data)
                time.sleep(duration)

    def track_performance(self, string_id, transaction):

        if 'side' in transaction.keys():
            if transaction['side'] == 'sell':
                self.sells.append(transaction['id'])
            if transaction['side'] == 'buy':
                self.buys.append(transaction['id'])

    def evaluate_performance(self):

        print('Current sell orders:')
        for sell in self.sells:
            order = self.auth_client.get_order(sell)

            if 'message' in order.keys():
                self.sells.remove(sell)

            else:
                print('price:', order['price'], 'size:', order['size'])

                if order['settled'] == True:
                    self.sell_tracker += float(order['size']) * float(
                        order['price'])
                    self.sell_fees += float(order['fill_fees'])
                    self.num_sells += float(order['size'])
                    self.sells.remove(sell)

        print('Current buy orders:')
        for buy in self.buys:
            order = self.auth_client.get_order(buy)

            if 'message' in order.keys():
                self.buys.remove(buy)

            else:

                print('price:', order['price'], 'size:', order['size'])
                if order['settled'] == True:
                    self.buy_tracker += float(order['size']) * float(
                        order['price'])
                    self.buy_fees += float(order['fill_fees'])
                    self.num_buys += float(order['size'])
                    self.buys.remove(buy)

        if self.num_buys > 0:
            self.av_buy = self.buy_tracker / self.num_buys

        if self.num_sells > 0:
            self.av_sell = self.sell_tracker / self.num_sells

        print('Number of buys:', self.num_buys)
        print('Buy USD volume:', self.buy_tracker)
        print('Number of sells:', self.num_sells)
        print('Sell USD volume:', self.sell_tracker)
        print('Net fees:', self.sell_fees + self.buy_fees)
        print(
            'Net USD profit:', self.sell_tracker - self.buy_tracker -
            self.sell_fees - self.buy_fees)
        print('Av sell:', self.av_sell)
        print('Av buy:', self.av_buy)

    def check_existing_sells(self, current_order_price, current_order_size,
                             vol_measure):

        new_average = (self.sell_tracker +
                       current_order_price * current_order_size) / (
                           self.num_sells + current_order_size)

        print('new av', new_average)

        if len(self.sells) > 0:

            if new_average > self.av_buy:

                if self.num_buys > 0:

                    for sell in self.sells:

                        order = self.auth_client.get_order(sell)
                        order_price = float(order['price'])

                        if 'message' in order.keys():
                            self.buys.remove(sell)
                            return 'keep'

                        else:
                            if self.av_buy < current_order_price:

                                if order_price < current_order_price - vol_measure:
                                    self.buys.remove(sell)
                                    self.auth_client.cancel_order(order['id'])
                                    return 'keep'

                                else:
                                    return 'abandon'

                            else:
                                return 'abandon'

                else:

                    if current_order_price > self.last_buy:

                        return 'keep'

                    else:
                        return 'abandon'

            else:
                return 'abandon'

        else:
            return 'keep'

    def check_existing_buys(self, current_order_price, current_order_size,
                            vol_measure):

        fees = 0.0025 * (current_order_price * current_order_size)

        current_plus_fees = current_order_price + fees

        new_average = (self.buy_tracker +
                       current_order_price * current_order_size +
                       fees) / (self.num_buys + current_order_size)

        if len(self.buys) > 0:

            if new_average < self.av_sell:

                if self.num_sells > 0:

                    for buy in self.buys:

                        order = self.auth_client.get_order(buy)

                        order_plus_fees = float(
                            order['price']) + 0.0025 * float(
                                order['price']) * float(order['size'])

                        if 'message' in order.keys():
                            self.buys.remove(buy)
                            return 'keep'

                        else:
                            if self.av_sell > order_plus_fees:

                                if order_plus_fees > current_plus_fees + vol_measure:
                                    self.buys.remove(buy)
                                    self.auth_client.cancel_order(order['id'])
                                    return 'keep'

                                else:
                                    return 'abandon'

                            else:
                                return 'abandon'

                else:

                    if current_order_price < self.last_sell:

                        return 'keep'

                    else:

                        return 'abandon'

            else:
                return 'abandon'

        else:
            return 'keep'

    def execute_volume_strategy(self, number_measures, length_measures,
                                order_book_skim, base_size,
                                volatility_interval, num_volatility_measures,
                                vol_confidence, run_minutes):

        t_end = time.time() + 60 * run_minutes
        while time.time() < t_end:
            print('time remaining', t_end - time.time())
            #
            #        while True:
            vol_measure = self.check_volatility(volatility_interval,
                                                num_volatility_measures)

            #        accounts = self.auth_client.get_accounts()

            #        balance = 0

            #     for account in accounts:
            #         if account['currency'] == self.product:
            #             balance = account['balance']

            #    print('balance', balance)

            ticker = float(
                self.public_client.get_product_ticker(self.product)['price'])

            bid_intervals, bid_depths_intervals, ask_intervals, ask_depths_intervals = self.get_order_info(
                ticker, number_measures, length_measures, order_book_skim)

            while check_order_info(bid_intervals, bid_depths_intervals,
                                   ask_intervals,
                                   ask_depths_intervals) == False:
                time.sleep(10)
                bid_intervals, bid_depths_intervals, ask_intervals, ask_depths_intervals = self.get_order_info(
                    ticker, number_measures, length_measures, order_book_skim)

            ticker = float(
                self.public_client.get_product_ticker(self.product)['price'])
            self.ticker_tracker.append(ticker)
            self.check_volatility(volatility_interval, num_volatility_measures)

            decision = make_trade_decision(ticker, bid_intervals,
                                           bid_depths_intervals, ask_intervals,
                                           ask_depths_intervals, vol_measure,
                                           vol_confidence, base_size,
                                           self.num_buys, self.num_sells,
                                           self.av_buy, self.av_sell)

            if decision[0] == 'buy':
                place_decision = self.check_existing_buys(
                    float(decision[1]), float(decision[2]), vol_measure)
                if place_decision == 'keep':

                    print('Placing buy order...')
                    print('price', decision[1], 'size', decision[2])
                    buy = self.auth_client.buy(price=decision[1],
                                               size=decision[2],
                                               product_id=self.product)
                    self.last_buy = float(decision[1])
                    self.track_performance('buy', buy)
                    time.sleep(10)

                if place_decision == 'abandon':
                    'Waiting on existing trades'

            elif decision[0] == 'sell':
                place_decision = self.check_existing_sells(
                    float(decision[1]), float(decision[2]), vol_measure)
                if place_decision == 'keep':

                    print('Placing sell order...')
                    print('price', decision[1], 'size', decision[2])
                    sell = self.auth_client.sell(price=decision[1],
                                                 size=decision[2],
                                                 product_id=self.product)
                    self.last_sell = float(decision[1])
                    self.track_performance('sell', sell)
                    time.sleep(10)

                if place_decision == 'abandon':
                    'Waiting on existing trades'

            elif decision[0] == 'hold':
                print('Holding...')

            else:
                print('Problem...')

            self.evaluate_performance()

        print('test complete')
        print()
Ejemplo n.º 13
0
class OrderBook(WebsocketClient):
    def __init__(self,
                 product_id='BTC-USD',
                 log_to=None,
                 autoreconnect=True,
                 max_retries=3):
        super(OrderBook, self).__init__(products=[product_id])

        self.channels = ['full']

        self._asks = RBTree()
        self._bids = RBTree()
        self._client = PublicClient()
        self._sequence = -1
        self._log_to = log_to
        self._retries = 0
        self._max_retries = max_retries
        self._autoreconnect = autoreconnect
        self._is_ready = False
        if self._log_to:
            assert hasattr(self._log_to, 'write')
        self._current_ticker = None

    @property
    def product_id(self):
        ''' Currently OrderBook only supports a single product even though it is stored as a list of products. '''
        return self.products[0]

    def is_ready(self):
        return self._is_ready

    def on_open(self):
        self._sequence = -1
        self._retries = 0
        print("-- Subscribed to OrderBook! --\n")

    def on_close(self):
        print("\n-- OrderBook Socket Closed! --")
        self._is_ready = False
        if not self.ws.sock or not self.ws.sock.connected and self._autoreconnect:
            self._sequence = -1

            if self._retries < self._max_retries:
                print('-- OrderBook Reconnecting... --')
                self._retries += 1
                self.start()
            else:
                print('-- Could not reconnect, stopping... --')

    def reset_book(self):
        self._is_ready = False
        self._asks = RBTree()
        self._bids = RBTree()
        res = self._client.get_product_order_book(product_id=self.product_id,
                                                  level=3)
        for bid in res['bids']:
            self.add({
                'id': bid[2],
                'side': 'buy',
                'price': Decimal(bid[0]),
                'size': Decimal(bid[1])
            })
        for ask in res['asks']:
            self.add({
                'id': ask[2],
                'side': 'sell',
                'price': Decimal(ask[0]),
                'size': Decimal(ask[1])
            })
        print("\n-- OrderBook Data Initialized --")
        self._is_ready = True
        self._sequence = res['sequence']

    def on_message(self, message):
        if self._log_to:
            pickle.dump(message, self._log_to)

        if 'sequence' not in message:
            return

        sequence = message['sequence']
        if self._sequence == -1:
            print("\n-- Initializing OrderBook --")
            self.reset_book()
            return
        if sequence <= self._sequence:
            # ignore older messages (e.g. before order book initialization from getProductOrderBook)
            return
        elif sequence > self._sequence + 1:
            self.on_sequence_gap(self._sequence, sequence)
            return

        msg_type = message['type']

        if msg_type == 'open':
            self.add(message)
        elif msg_type == 'done' and 'price' in message:
            self.remove(message)
        elif msg_type == 'match':
            self.match(message)
            self._current_ticker = message
        elif msg_type == 'change':
            self.change(message)

        self._sequence = sequence

    def on_error(self, ws, e):
        super(OrderBook, self).on_error(ws, e)

        if not ws.sock or not ws.sock.connected:
            self._sequence = -1
            self._is_ready = False

            if self._retries < self._max_retries:
                print('-- OrderBook Disconnected, reconnecting... --')
                self._retries += 1
                self.start()
            else:
                print('-- Could not reconnect, stopping... --')

    def on_sequence_gap(self, gap_start, gap_end):
        self._sequence = -1
        self.reset_book()

        print('-- Error: messages missing, re-initializing book. --'.format(
            gap_start, gap_end, self._sequence))

    def add(self, order):
        order = {
            'id': order.get('order_id') or order['id'],
            'side': order['side'],
            'price': Decimal(order['price']),
            'size': Decimal(order.get('size') or order['remaining_size'])
        }
        if order['side'] == 'buy':
            bids = self.get_bids(order['price'])
            if bids is None:
                bids = [order]
            else:
                bids.append(order)
            self.set_bids(order['price'], bids)
        else:
            asks = self.get_asks(order['price'])
            if asks is None:
                asks = [order]
            else:
                asks.append(order)
            self.set_asks(order['price'], asks)

    def remove(self, order):
        price = Decimal(order['price'])
        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if bids is not None:
                bids = [o for o in bids if o['id'] != order['order_id']]
                if len(bids) > 0:
                    self.set_bids(price, bids)
                else:
                    self.remove_bids(price)
        else:
            asks = self.get_asks(price)
            if asks is not None:
                asks = [o for o in asks if o['id'] != order['order_id']]
                if len(asks) > 0:
                    self.set_asks(price, asks)
                else:
                    self.remove_asks(price)

    def match(self, order):
        size = Decimal(order['size'])
        price = Decimal(order['price'])

        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if not bids:
                return
            assert bids[0]['id'] == order['maker_order_id']
            if bids[0]['size'] == size:
                self.set_bids(price, bids[1:])
            else:
                bids[0]['size'] -= size
                self.set_bids(price, bids)
        else:
            asks = self.get_asks(price)
            if not asks:
                return
            assert asks[0]['id'] == order['maker_order_id']
            if asks[0]['size'] == size:
                self.set_asks(price, asks[1:])
            else:
                asks[0]['size'] -= size
                self.set_asks(price, asks)

    def change(self, order):
        try:
            new_size = Decimal(order['new_size'])
        except KeyError:
            return

        try:
            price = Decimal(order['price'])
        except KeyError:
            return

        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if bids is None or not any(o['id'] == order['order_id']
                                       for o in bids):
                return
            index = [b['id'] for b in bids].index(order['order_id'])
            bids[index]['size'] = new_size
            self.set_bids(price, bids)
        else:
            asks = self.get_asks(price)
            if asks is None or not any(o['id'] == order['order_id']
                                       for o in asks):
                return
            index = [a['id'] for a in asks].index(order['order_id'])
            asks[index]['size'] = new_size
            self.set_asks(price, asks)

        tree = self._asks if order['side'] == 'sell' else self._bids
        node = tree.get(price)

        if node is None or not any(o['id'] == order['order_id'] for o in node):
            return

    def get_current_ticker(self):
        return self._current_ticker

    def get_current_book(self):
        result = {
            'sequence': self._sequence,
            'asks': [],
            'bids': [],
        }
        for ask in self._asks:
            try:
                # There can be a race condition here, where a price point is removed
                # between these two ops
                this_ask = self._asks[ask]
            except KeyError:
                continue
            for order in this_ask:
                result['asks'].append(
                    [order['price'], order['size'], order['id']])
        for bid in self._bids:
            try:
                # There can be a race condition here, where a price point is removed
                # between these two ops
                this_bid = self._bids[bid]
            except KeyError:
                continue

            for order in this_bid:
                result['bids'].append(
                    [order['price'], order['size'], order['id']])
        return result

    def get_ask(self):
        return self._asks.min_key()

    def get_asks(self, price):
        return self._asks.get(price)

    def remove_asks(self, price):
        self._asks.remove(price)

    def set_asks(self, price, asks):
        self._asks.insert(price, asks)

    def get_bid(self):
        return self._bids.max_key()

    def get_bids(self, price):
        return self._bids.get(price)

    def remove_bids(self, price):
        self._bids.remove(price)

    def set_bids(self, price, bids):
        self._bids.insert(price, bids)
Ejemplo n.º 14
0
class OrderBook(WebsocketClient):
    def __init__(self, product_id='BTC-USD', log_to=None):
        super(OrderBook, self).__init__(products=product_id)
        self._asks = RBTree()
        self._bids = RBTree()
        self._client = PublicClient()
        self._sequence = -1
        self._log_to = log_to
        if self._log_to:
            assert hasattr(self._log_to, 'write')
        self._current_ticker = None

    @property
    def product_id(self):
        ''' Currently OrderBook only supports a single product even though it is stored as a list of products. '''
        return self.products[0]

    def on_open(self):
        self._sequence = -1
        print("-- Subscribed to OrderBook! --\n")

    def on_close(self):
        print("\n-- OrderBook Socket Closed! --")

    def reset_book(self):
        self._asks = RBTree()
        self._bids = RBTree()
        res = self._client.get_product_order_book(
            product_id=self.product_id, level=3)
        for bid in res['bids']:
            self.add({
                'id': bid[2],
                'side': 'buy',
                'price': Decimal(bid[0]),
                'size': Decimal(bid[1])
            })
        for ask in res['asks']:
            self.add({
                'id': ask[2],
                'side': 'sell',
                'price': Decimal(ask[0]),
                'size': Decimal(ask[1])
            })
        self._sequence = res['sequence']

    def on_message(self, message):
        if self._log_to:
            pickle.dump(message, self._log_to)

        sequence = message['sequence']
        if self._sequence == -1:
            self.reset_book()
            return
        if sequence <= self._sequence:
            # ignore older messages (e.g. before order book initialization from getProductOrderBook)
            return
        elif sequence > self._sequence + 1:
            self.on_sequence_gap(self._sequence, sequence)
            return

        msg_type = message['type']
        if msg_type == 'open':
            self.add(message)
        elif msg_type == 'done' and 'price' in message:
            self.remove(message)
        elif msg_type == 'match':
            self.match(message)
            self._current_ticker = message
        elif msg_type == 'change':
            self.change(message)

        self._sequence = sequence

    def on_sequence_gap(self, gap_start, gap_end):
        self.reset_book()
        print('Error: messages missing ({} - {}). Re-initializing  book at sequence.'.format(
            gap_start, gap_end, self._sequence))

    def add(self, order):
        order = {
            'id': order.get('order_id') or order['id'],
            'side': order['side'],
            'price': Decimal(order['price']),
            'size': Decimal(order.get('size') or order['remaining_size'])
        }
        if order['side'] == 'buy':
            bids = self.get_bids(order['price'])
            if bids is None:
                bids = collections.OrderedDict()
            bids[order['id']] = order
            self.set_bids(order['price'], bids)
        else:
            asks = self.get_asks(order['price'])
            if asks is None:
                asks = collections.OrderedDict()
            asks[order['id']] = order
            self.set_asks(order['price'], asks)

    def remove(self, order):
        price = Decimal(order['price'])
        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if bids is not None:
                if order['order_id'] in bids:
                    del bids[order['order_id']]
                if len(bids) > 0:
                    self.set_bids(price, bids)
                else:
                    self.remove_bids(price)
        else:
            asks = self.get_asks(price)
            if asks is not None:
                if order['order_id'] in asks:
                    del asks[order['order_id']]
                if len(asks) > 0:
                    self.set_asks(price, asks)
                else:
                    self.remove_asks(price)

    def match(self, order):
        size = Decimal(order['size'])
        price = Decimal(order['price'])

        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if not bids:
                return
            top_order = bids.items()[0]
            assert top_order[1]['id'] == order['maker_order_id']
            if top_order[1]['size'] == size:
                del bids[order['maker_order_id']]
                self.set_bids(price, bids)
            else:
                top_order[1]['size'] -= size
                self.set_bids(price, bids)
        else:
            asks = self.get_asks(price)
            if not asks:
                return
            top_order = asks.items()[0]
            assert top_order[1]['id'] == order['maker_order_id']
            if top_order[1]['size'] == size:
                del asks[order['maker_order_id']]
                self.set_asks(price, asks)
            else:
                top_order[1]['size'] -= size
                self.set_asks(price, asks)

    def change(self, order):
        try:
            new_size = Decimal(order['new_size'])
        except KeyError:
            return

        try:
            price = Decimal(order['price'])
        except KeyError:
            return

        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if bids is None or order['order_id'] not in bids:
                return
            bids[order['order_id']]['size'] = new_size
            self.set_bids(price, bids)
        else:
            asks = self.get_asks(price)
            if asks is None or order['order_id'] not in asks:
                return
            asks[order['order_id']]['size'] = new_size
            self.set_asks(price, asks)

    def get_current_ticker(self):
        return self._current_ticker

    def get_current_book(self):
        result = {
            'sequence': self._sequence,
            'asks': [],
            'bids': [],
        }
        for ask in self._asks:
            try:
                # There can be a race condition here, where a price point is removed
                # between these two ops
                this_ask = self._asks[ask]
            except KeyError:
                continue
            for order in this_ask:
                result['asks'].append(
                    [order['price'], order['size'], order['id']])
        for bid in self._bids:
            try:
                # There can be a race condition here, where a price point is removed
                # between these two ops
                this_bid = self._bids[bid]
            except KeyError:
                continue

            for order in this_bid:
                result['bids'].append(
                    [order['price'], order['size'], order['id']])
        return result

    def get_ask(self):
        return self._asks.min_key()

    def get_asks(self, price):
        return self._asks.get(price)

    def remove_asks(self, price):
        self._asks.remove(price)

    def set_asks(self, price, asks):
        self._asks.insert(price, asks)

    def get_bid(self):
        return self._bids.max_key()

    def get_bids(self, price):
        return self._bids.get(price)

    def remove_bids(self, price):
        self._bids.remove(price)

    def set_bids(self, price, bids):
        self._bids.insert(price, bids)
Ejemplo n.º 15
0
 def __init__(self, product_id='BTC-USD'):
     super(OrderBook, self).__init__(products=product_id)
     self._asks = RBTree()
     self._bids = RBTree()
     self._client = PublicClient(product_id=product_id)
     self._sequence = -1
Ejemplo n.º 16
0
from gdax.public_client import PublicClient

client = PublicClient()


def get_quotes(ticker):
    result = (client.get_product_ticker(ticker))
    return result


if __name__ == "__main__":
    get_quotes('BTC-USD')
Ejemplo n.º 17
0
class OrderBook(WebsocketClient):
    def __init__(self, product_id='BTC-USD'):
        super(OrderBook, self).__init__(products=product_id)
        self._asks = RBTree()
        self._bids = RBTree()
        self._client = PublicClient(product_id=product_id)
        self._sequence = -1

    def on_message(self, message):
        sequence = message['sequence']
        if self._sequence == -1:
            self._asks = RBTree()
            self._bids = RBTree()
            res = self._client.get_product_order_book(level=3)
            for bid in res['bids']:
                self.add({
                    'id': bid[2],
                    'side': 'buy',
                    'price': Decimal(bid[0]),
                    'size': Decimal(bid[1])
                })
            for ask in res['asks']:
                self.add({
                    'id': ask[2],
                    'side': 'sell',
                    'price': Decimal(ask[0]),
                    'size': Decimal(ask[1])
                })
            self._sequence = res['sequence']

        if sequence <= self._sequence:
            # ignore older messages (e.g. before order book initialization from getProductOrderBook)
            return
        elif sequence > self._sequence + 1:
            print('Error: messages missing ({} - {}). Re-initializing websocket.'.format(sequence, self._sequence))
            self.close()
            self.start()
            return

        # print(message)
        msg_type = message['type']
        if msg_type == 'open':
            self.add(message)
        elif msg_type == 'done' and 'price' in message:
            self.remove(message)
        elif msg_type == 'match':
            self.match(message)
        elif msg_type == 'change':
            self.change(message)

        self._sequence = sequence

        # bid = self.get_bid()
        # bids = self.get_bids(bid)
        # bid_depth = sum([b['size'] for b in bids])
        # ask = self.get_ask()
        # asks = self.get_asks(ask)
        # ask_depth = sum([a['size'] for a in asks])
        # print('bid: %f @ %f - ask: %f @ %f' % (bid_depth, bid, ask_depth, ask))

    def add(self, order):
        order = {
            'id': order.get('order_id') or order['id'],
            'side': order['side'],
            'price': Decimal(order['price']),
            'size': Decimal(order.get('size') or order['remaining_size'])
        }
        if order['side'] == 'buy':
            bids = self.get_bids(order['price'])
            if bids is None:
                bids = [order]
            else:
                bids.append(order)
            self.set_bids(order['price'], bids)
        else:
            asks = self.get_asks(order['price'])
            if asks is None:
                asks = [order]
            else:
                asks.append(order)
            self.set_asks(order['price'], asks)

    def remove(self, order):
        price = Decimal(order['price'])
        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if bids is not None:
                bids = [o for o in bids if o['id'] != order['order_id']]
                if len(bids) > 0:
                    self.set_bids(price, bids)
                else:
                    self.remove_bids(price)
        else:
            asks = self.get_asks(price)
            if asks is not None:
                asks = [o for o in asks if o['id'] != order['order_id']]
                if len(asks) > 0:
                    self.set_asks(price, asks)
                else:
                    self.remove_asks(price)

    def match(self, order):
        size = Decimal(order['size'])
        price = Decimal(order['price'])

        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if not bids:
                return
            assert bids[0]['id'] == order['maker_order_id']
            if bids[0]['size'] == size:
                self.set_bids(price, bids[1:])
            else:
                bids[0]['size'] -= size
                self.set_bids(price, bids)
        else:
            asks = self.get_asks(price)
            if not asks:
                return
            assert asks[0]['id'] == order['maker_order_id']
            if asks[0]['size'] == size:
                self.set_asks(price, asks[1:])
            else:
                asks[0]['size'] -= size
                self.set_asks(price, asks)

    def change(self, order):
        new_size = Decimal(order['new_size'])
        price = Decimal(order['price'])

        if order['side'] == 'buy':
            bids = self.get_bids(price)
            if bids is None or not any(o['id'] == order['order_id'] for o in bids):
                return
            index = map(itemgetter('id'), bids).index(order['order_id'])
            bids[index]['size'] = new_size
            self.set_bids(price, bids)
        else:
            asks = self.get_asks(price)
            if asks is None or not any(o['id'] == order['order_id'] for o in asks):
                return
            index = map(itemgetter('id'), asks).index(order['order_id'])
            asks[index]['size'] = new_size
            self.set_asks(price, asks)

        tree = self._asks if order['side'] == 'sell' else self._bids
        node = tree.get(price)

        if node is None or not any(o['id'] == order['order_id'] for o in node):
            return

    def get_current_book(self):
        result = {
            'sequence': self._sequence,
            'asks': [],
            'bids': [],
        }
        for ask in self._asks:
            try:
                # There can be a race condition here, where a price point is removed
                # between these two ops
                this_ask = self._asks[ask]
            except KeyError:
                continue
            for order in this_ask:
                result['asks'].append([order['price'], order['size'], order['id']])
        for bid in self._bids:
            try:
                # There can be a race condition here, where a price point is removed
                # between these two ops
                this_bid = self._bids[bid]
            except KeyError:
                continue

            for order in this_bid:
                result['bids'].append([order['price'], order['size'], order['id']])
        return result

    def get_ask(self):
        return self._asks.min_key()

    def get_asks(self, price):
        return self._asks.get(price)

    def remove_asks(self, price):
        self._asks.remove(price)

    def set_asks(self, price, asks):
        self._asks.insert(price, asks)

    def get_bid(self):
        return self._bids.max_key()

    def get_bids(self, price):
        return self._bids.get(price)

    def remove_bids(self, price):
        self._bids.remove(price)

    def set_bids(self, price, bids):
        self._bids.insert(price, bids)