Пример #1
0
    def __init__(self, ccy, exchange):
        """
        OrderBook constructor

        :param ccy: currency symbol
        :param exchange: 'coinbase' or 'bitfinex'
        """
        self.sym = ccy
        self.db = Database(ccy, exchange)
        self.bids = CoinbaseBook(ccy, 'bids') if exchange == 'coinbase' else \
            BitfinexBook(ccy, 'bids')
        self.asks = CoinbaseBook(ccy, 'asks') if exchange == 'coinbase' else \
            BitfinexBook(ccy, 'asks')
        self.midpoint = float()
        self.buy_tracker = TradeTracker()
        self.sell_tracker = TradeTracker()
Пример #2
0
    def __init__(self, ccy: str, exchange: str):
        """
        OrderBook constructor.

        :param ccy: currency symbol
        :param exchange: 'coinbase' or 'bitfinex'
        """
        self.sym = ccy
        self.db = Database(sym=ccy, exchange=exchange)
        self.db.init_db_connection()
        self.bids = get_orderbook(name=exchange)(sym=ccy, side='bids')
        self.asks = get_orderbook(name=exchange)(sym=ccy, side='asks')
        self.exchange = exchange
        self.midpoint = float()
        self.spread = float()
        self.buy_tracker = TradeTracker()
        self.sell_tracker = TradeTracker()
        self.last_tick_time = None
Пример #3
0
    def __init__(self, sym: str, exchange: str):
        """
        OrderBook constructor.

        :param sym: instrument name
        :param exchange: 'coinbase' or 'bitfinex' or 'bitmex'
        """
        self.sym = sym
        self.db = Database(sym=sym, exchange=exchange)
        self.db.init_db_connection()
        self.bids = BOOK_BY_EXCHANGE[exchange](sym=sym, side='bids')
        self.asks = BOOK_BY_EXCHANGE[exchange](sym=sym, side='asks')
        self.exchange = exchange
        self.midpoint = float()
        self.spread = float()
        self.buy_tracker = TradeTracker()
        self.sell_tracker = TradeTracker()
        self.last_tick_time = None
Пример #4
0
class OrderBook(ABC):
    def __init__(self, ccy, exchange):
        """
        OrderBook constructor

        :param ccy: currency symbol
        :param exchange: 'coinbase' or 'bitfinex'
        """
        self.sym = ccy
        self.db = Database(ccy, exchange)
        self.bids = CoinbaseBook(ccy, 'bids') if exchange == 'coinbase' else \
            BitfinexBook(ccy, 'bids')
        self.asks = CoinbaseBook(ccy, 'asks') if exchange == 'coinbase' else \
            BitfinexBook(ccy, 'asks')
        self.midpoint = float()
        self.buy_tracker = TradeTracker()
        self.sell_tracker = TradeTracker()

    def __str__(self):
        return '%s  ||  %s' % (self.bids, self.asks)

    @abstractmethod
    def new_tick(self, msg):
        """
        Event handler for incoming tick messages

        :param msg: incoming order or trade message
        :return:
        """
        pass

    def clear_trade_trackers(self):
        """
        Reset buy and sell trade trackers; used between LOB snapshots

        :return: (void)
        """
        self.buy_tracker.clear()
        self.sell_tracker.clear()

    def clear_book(self):
        """
        Method to reset the limit order book

        :return: (void)
        """
        self.bids.clear()
        self.asks.clear()
        print('--Cleared %s order book--' % self.sym)

    # def render_book(self):
    #     """
    #     Convert the limit order book into a DataFrame
    #     :return: pandas dataframe
    #     """
    #
    #     pd_bids = self.bids.get_bids_to_list()
    #     pd_asks = self.asks.get_asks_to_list()
    #
    #     return pd.concat([pd_bids, pd_asks], sort=False)

    def render_book(self):
        """
        Create stationary feature set for limit order book

        Source: https://arxiv.org/abs/1810.09965v1

        :return: numpy array
        """
        bid_price, bid_level = self.bids.get_bid()
        ask_price, ask_level = self.asks.get_ask()

        self.midpoint = (bid_price + ask_price) / 2.0

        bid_data = self.bids.get_bids_to_list(midpoint=self.midpoint)
        ask_data = self.asks.get_asks_to_list(midpoint=self.midpoint)

        buy_trades = np.array(self.buy_tracker.notional)
        sell_trades = np.array(self.sell_tracker.notional)
        self.clear_trade_trackers()

        if INCLUDE_ORDERFLOW:
            bid_distances, bid_notionals, bid_cancel_notionals, bid_limit_notionals, \
            bid_market_notionals = bid_data

            ask_distances, ask_notionals, ask_cancel_notionals, ask_limit_notionals, \
            ask_market_notionals = ask_data

            return np.hstack((bid_notionals, ask_notionals, bid_distances,
                              ask_distances, buy_trades, sell_trades,
                              bid_cancel_notionals, ask_cancel_notionals,
                              bid_limit_notionals, ask_limit_notionals,
                              bid_market_notionals, ask_market_notionals))
        else:
            bid_distances, bid_notionals = bid_data

            ask_distances, ask_notionals = ask_data

            return np.hstack((bid_notionals, ask_notionals, bid_distances,
                              ask_distances, buy_trades, sell_trades))

    # def render_book(self):
    #     """
    #     Create stationary feature set for limit order book
    #
    #     Source: https://arxiv.org/abs/1810.09965v1
    #
    #     :return: numpy array
    #     """
    #     bid_price, bid_level = self.bids.get_bid()
    #     ask_price, ask_level = self.asks.get_ask()
    #
    #     self.midpoint = (bid_price + ask_price) / 2.0
    #
    #     bids = self.bids.get_bids_to_list(self.midpoint)
    #     asks = self.asks.get_asks_to_list(self.midpoint)
    #
    #     buy_trades = np.array(self.buy_tracker.notional)
    #     sell_trades = np.array(self.sell_tracker.notional)
    #
    #     self.clear_trade_trackers()
    #
    #     return np.hstack((bids, asks, buy_trades, sell_trades))

    @property
    def best_bid(self):
        """
        Get the best bid
        :return: float best bid
        """
        return self.bids.get_bid()

    @property
    def best_ask(self):
        """
        Get the best ask
        :return: float best ask
        """
        return self.asks.get_ask()

    def done_warming_up(self):
        """
        Flag to indicate if the entire Limit Order Book has been loaded
        :return: True if loaded / False if still waiting to download
        """
        return ~self.bids.warming_up & ~self.asks.warming_up
Пример #5
0
class OrderBook(ABC):

    def __init__(self, ccy: str, exchange: str):
        """
        OrderBook constructor.

        :param ccy: currency symbol
        :param exchange: 'coinbase' or 'bitfinex'
        """
        self.sym = ccy
        self.db = Database(sym=ccy, exchange=exchange)
        self.db.init_db_connection()
        self.bids = get_orderbook(name=exchange)(sym=ccy, side='bids')
        self.asks = get_orderbook(name=exchange)(sym=ccy, side='asks')
        self.exchange = exchange
        self.midpoint = float()
        self.spread = float()
        self.buy_tracker = TradeTracker()
        self.sell_tracker = TradeTracker()
        self.last_tick_time = None

    def __str__(self):
        return '%s  ||  %s' % (self.bids, self.asks)

    @abstractmethod
    def new_tick(self, msg: dict) -> bool:
        """
        Event handler for incoming tick messages.

        :param msg: incoming order or trade message
        :return: FALSE if reconnection to WebSocket is needed, else TRUE if good
        """
        return True

    def clear_trade_trackers(self) -> None:
        """
        Reset buy and sell trade trackers; used between LOB snapshots.

        :return: (void)
        """
        self.buy_tracker.clear()
        self.sell_tracker.clear()

    def clear_book(self) -> None:
        """
        Method to reset the limit order book.

        :return: (void)
        """
        self.bids.clear()  # warming_up flag reset in `Position` class
        self.asks.clear()  # warming_up flag reset in `Position` class
        self.last_tick_time = None
        LOGGER.info("{}'s order book cleared.".format(self.sym))

    def render_book(self) -> np.ndarray:
        """
        Create stationary feature set for limit order book.

        :return: LOB feature set
        """
        # get price levels of LOB
        bid_price, bid_level = self.bids.get_bid()
        ask_price, ask_level = self.asks.get_ask()

        # derive midpoint price and spread from bid and ask data
        self.midpoint = (ask_price + bid_price) / 2.0
        self.spread = round(ask_price - bid_price, 4)  # round to clean float rounding

        # transform raw LOB data into stationary feature set
        bid_data = self.bids.get_bids_to_list(midpoint=self.midpoint)
        ask_data = self.asks.get_asks_to_list(midpoint=self.midpoint)

        # convert buy and sell trade notional values to an array
        buy_trades = np.array(self.buy_tracker.notional)
        sell_trades = np.array(self.sell_tracker.notional)

        # reset trackers after each LOB render
        self.clear_trade_trackers()

        return np.hstack((self.midpoint, self.spread,
                          buy_trades, sell_trades,
                          *bid_data, *ask_data))

    @staticmethod
    def render_lob_feature_names(include_orderflow: bool = INCLUDE_ORDERFLOW) -> list:
        """
        Get the column names for the LOB render features.

        :param include_orderflow: if TRUE, order flow imbalance stats are included in set
        :return: list containing features names
        """
        feature_names = list()

        feature_names.append('midpoint')
        feature_names.append('spread')
        feature_names.append('buys')
        feature_names.append('sells')

        feature_types = ['distance', 'notional']
        if include_orderflow:
            feature_types += ['cancel_notional', 'limit_notional', 'market_notional']

        for side in ['bid', 'ask']:
            for feature in feature_types:
                for row in range(MAX_BOOK_ROWS):
                    feature_names.append("{}_{}_{}".format(side, feature, row))

        LOGGER.info("render_feature_names() has {} features".format(len(feature_names)))

        return feature_names

    @property
    def best_bid(self) -> float:
        """
        Get the best bid.

        :return: float best bid
        """
        return self.bids.get_bid()

    @property
    def best_ask(self) -> float:
        """
        Get the best ask.

        :return: float best ask
        """
        return self.asks.get_ask()

    @property
    def done_warming_up(self) -> bool:
        """
        Flag to indicate if the entire Limit Order Book has been loaded.

        :return: True if loaded / False if still waiting to download
        """
        return self.bids.warming_up is False & self.asks.warming_up is False