Beispiel #1
0
 def __match_order(self, order: Order) -> None:
     price = order.get_price()
     order_id = order.get_order_id()
     side = order.get_order_side()
     order_key = self.__get_ob_order_hash_redis_key(side, price)
     size_key = self.__get_ob_sum_size_redis_key(side, price)
     self.redis_server.hincrbyfloat(order_key, order_id, '-' + order.get_size())
     self.redis_server.incrbyfloat(size_key, '-' + order.get_size())
Beispiel #2
0
 def test_that_orders_work_as_expect(self):
     o = Order('BTC-USD', 0, OrderSide.bid, '0.1', '100')
     assert o.get_product_id() == 'BTC-USD'
     assert o.get_sequence_id() == 0
     assert o.get_order_side() == OrderSide.bid
     assert o.get_size() == '0.1'
     assert o.get_price() == '100'
     o.add_filled_size('0.05')
     assert o.get_remaining_size() == '0.05'
Beispiel #3
0
 def __change_order(self, order: Order) -> None:
     price = order.get_price()
     order_id = order.get_order_id()
     side = order.get_order_side()
     new_order_size = order.get_filled_size()
     order_key = self.__get_ob_order_hash_redis_key(side, price)
     size_key = self.__get_ob_sum_size_redis_key(side, price)
     if self.redis_server.hexists(order_key, order_id):
         self.redis_server.hset(order_key, order_id, new_order_size)
         self.redis_server.incrbyfloat(size_key, '-' + order.get_remaining_size())
Beispiel #4
0
 def __remove_order(self, order: Order) -> None:
     price = order.get_price()
     side = order.get_order_side()
     order_key = self.__get_ob_order_hash_redis_key(side, price)
     size_key = self.__get_ob_sum_size_redis_key(side, price)
     self.redis_server.hdel(order_key, order.get_order_id())
     if self.redis_server.hlen(order_key) == 0:
         # why bother deleting here?
         self.redis_server.delete(order_key)
         self.redis_server.delete(size_key)
         self.redis_server.zrem(self.__get_ob_order_set_redis_key(side),
                                self.__get_ob_sum_size_redis_key(side, price))
     else:
         self.redis_server.incrbyfloat(size_key, '-' + order.get_size())
Beispiel #5
0
    def __sub__(self, order: Order) -> None:
        self.validate_order(order)
        self.__update_sequence_id(order.get_sequence_id())
        if not order.get_historical():
            if order.get_status() in [OrderStatus.filled, OrderStatus.canceled]:
                self.__remove_order(order)
            elif order.get_order_type() == OrderType.change:
                self.__change_order(order)
            else:
                self.__match_order(order)

        self.__register_product_change(order.get_order_side())
        self.orders_subtracted = self.orders_subtracted + 1
        # if self.orders_subtracted % 1000 == 1:
        #     print('Heartbeat {} orders removed from {}'.format(self.orders_subtracted, self.get_product_id()))
        self.__add_trade_to_trade_history(order)
 def test_order_cancellation(self):
     order_book, portfolio_group = generate_objects(self.product_manager)
     order = Order('BTC-USD', 0, OrderSide.bid, '1', '10.0', order_id='1')
     order_book + order
     portfolio_group.handle_done_order('1', OrderStatus.canceled)
     assert portfolio_group.get_available_qty(Currency.USD) == 100
     assert portfolio_group.get_available_qty(Currency.BTC) == 100
 def test_order_match(self):
     order_book, portfolio_group = generate_objects(self.product_manager)
     order = Order('BTC-USD', 0, OrderSide.bid, '1', '10.0', order_id='1')
     order_book + order
     portfolio_group.handle_match_order('1', '0.5')
     assert portfolio_group.get_available_qty(Currency.USD) == 90
     assert portfolio_group.get_available_qty(Currency.BTC) == 100.5
Beispiel #8
0
 def validate_order(self, order: Order) -> bool:
     if isinstance(order, Order):
         if order.get_product_id() != self.get_product_id():
             raise OrderBookException(
                 'You can only add orders with the same product id {} {}'.format(self.get_product_id(),
                                                                                 order.get_product_id())
             )
         elif order.get_sequence_id() < self.get_sequence_id():
             raise SequenceException(
                 'You cannot add orders with a lower sequence id {} {}'.format(self.get_sequence_id(),
                                                                               order.get_sequence_id())
             )
         else:
             return True
     else:
         raise OrderBookException(
             'You can only add orders of type Order to an order book {}'.format(str(type(order)))
         )
Beispiel #9
0
    def __add__(self, order: Order) -> None:
        self.validate_order(order)
        self.__update_sequence_id(order.get_sequence_id())
        price = order.get_price()
        side = order.get_order_side()
        if not order.get_historical():
            # This marks that we have live orders at this price
            self.redis_server.zadd(self.__get_ob_order_set_redis_key(side), price,
                                   self.__get_ob_sum_size_redis_key(side, price))
            # This adds the order to a list of orders keyed off price
            self.redis_server.hset(self.__get_ob_order_hash_redis_key(side, price), order.get_order_id(),
                                   order.get_size())
            self.redis_server.incrbyfloat(self.__get_ob_sum_size_redis_key(side, price), order.get_size())

        self.__register_product_change(order.get_order_side())
        self.orders_added = self.orders_added + 1
        # if self.orders_added % 1000 == 1:
        # print('Heartbeat {} orders added to {}'.format(self.orders_added, self.get_product_id()))
        self.__add_trade_to_trade_history(order)
Beispiel #10
0
 def parse_gdax_json_to_order(self, raw_order: Dict) -> Order:
     product_id, side, size, price, order_id, filled_size = raw_order[
         'product_id'], raw_order['side'], raw_order['size'], raw_order[
             'price'], raw_order['id'], raw_order['filled_size']
     created_at = parser.parse(raw_order['created_at'])
     side = 'bid' if side == 'buy' else 'ask'
     order = Order(product_id,
                   0,
                   OrderSide[side],
                   size,
                   price,
                   OrderStatus.open,
                   order_id,
                   created_at=created_at)
     order.add_filled_size(filled_size)
     self.log(
         LogType.info, 'Order id {} created {} seconds ago'.format(
             order.get_order_id(), order.get_created_at_seconds_ago()))
     return order
Beispiel #11
0
 def __sub__(self, order: Order) -> OrderBook:
     order_book = self.get_order_book(order.get_product_id())
     val = order_book - order
     return val
Beispiel #12
0
 def __add_trade_to_trade_history(self, order: Order) -> None:
     th_set_key = self.__get_th_order_set_redis_key(order.get_order_type(), order.get_order_side())
     th_order_size_key = self.__get_th_redis_key(order.get_order_type(), order.get_order_side(),
                                                 order.get_unix_timestamp())
     self.redis_server.zadd(th_set_key, order.get_unix_timestamp(), th_order_size_key)
     self.redis_server.incrbyfloat(th_order_size_key, order.get_size())
 def test_that_creating_an_order_reduces_available_qty(self):
     order_book, portfolio_group = generate_objects(self.product_manager)
     order = Order('BTC-USD', 0, OrderSide.bid, '1', '10.0', order_id='1')
     order_book + order
     assert portfolio_group.get_available_qty(Currency.USD) == 90
     assert portfolio_group.get_available_qty(Currency.BTC) == 100
    def test_that_order_book_works_as_expected(self):
        product_id = 'BTC-USD'
        product = Product(product_id=product_id,
                          quote_currency=Currency.USD,
                          base_currency=Currency.BTC,
                          quote_increment='0.01',
                          base_min_size='0.01')
        ob = OrderBook(product)
        # test empty order book
        assert (ob.get_product_id() == product_id)
        assert (ob.orders_added == 0)
        assert (ob.orders_subtracted == 0)

        def get_price(side):
            price = 20 if side == OrderSide.ask else 10
            return str(price)

        def get_better_price(s, i=0):
            price = int(get_price(s)) - 1 - i if s == OrderSide.ask else int(
                get_price(s)) + 1 + i
            return str(price)

        def get_worse_price(s, i=0):
            price = int(get_price(s)) + 1 + i if s == OrderSide.ask else int(
                get_price(s)) - 1 - i
            return str(price)

        def get_other_side(s):
            return OrderSide.bid if s == OrderSide.ask else OrderSide.ask

        for side in OrderSide:
            ob = OrderBook(product)
            ob.redis_server.flushdb()

            # test adding base set of orders
            order = Order(product_id,
                          0,
                          get_other_side(side),
                          '1.0',
                          get_price(get_other_side(side)),
                          order_id='0')
            ob + order
            order = Order(product_id,
                          0,
                          side,
                          '1.0',
                          get_price(side),
                          order_id='1')
            ob + order
            order = Order(product_id,
                          0,
                          side,
                          '1.0',
                          get_worse_price(side),
                          order_id='2')
            ob + order

            # test matching and filling an order at best price
            order = Order(product_id,
                          0,
                          side,
                          '1.0',
                          get_price(side),
                          order_type=OrderType.match,
                          order_id='1')
            ob - order
            order = Order(product_id,
                          0,
                          side,
                          '0',
                          get_price(side),
                          order_type=OrderType.match,
                          status=OrderStatus.filled,
                          order_id='1')
            ob - order
            assert ob.get_best(side) == float(get_worse_price(side))
            assert ob.get_median_trade_size(side, OrderType.match, 10, 1) == 1.

            # test adding an order at a worse price
            order = Order(product_id,
                          0,
                          side,
                          '1.0',
                          get_worse_price(side, 1),
                          order_id='3')
            ob + order
            assert (ob.get_best(side) == float(get_worse_price(side)))
            assert ob.get_price(side,
                                2) == (float(get_worse_price(side)),
                                       float(get_worse_price(side, 1)),
                                       float(get_worse_price(side)) +
                                       float(get_worse_price(side, 1)), 0., 1.)

            # test cancelling order at best price
            order = Order(product_id,
                          0,
                          side,
                          '1.0',
                          get_worse_price(side),
                          order_id='2',
                          order_type=OrderType.cancel,
                          status=OrderStatus.canceled)
            ob - order
            assert (ob.get_best(side) == float(get_worse_price(side, 1)))

            # test changing order at best price
            order = Order(product_id,
                          0,
                          side,
                          '1',
                          get_worse_price(side, 1),
                          order_id='3',
                          order_type=OrderType.change)
            order.add_filled_size('0.5')
            ob - order
            assert (ob.get_best(side) == float(get_worse_price(side, 1)))

            # test cancelling order with unrecognized order id
            order = Order(product_id,
                          0,
                          side,
                          '4',
                          get_worse_price(side),
                          order_id='1e2',
                          order_type=OrderType.cancel,
                          status=OrderStatus.canceled)
            ob - order
            assert (ob.get_best(side) == float(get_worse_price(side, 1)))

            assert (ob.get_best(get_other_side(side)) == float(
                get_price(get_other_side(side))))