Esempio n. 1
0
    def test_no_matching_orders(self):
        # Orderbook for ABC
        book = Orderbook('ABC')

        bob = Client('Bob')
        alice = Client('Alice')
        eve = Client('Eve')

        # Bob offers @ 9, alice asks @ 10, bob cancels then eve asks @ 8.5
        bob_order = Order("ABC", 9.00, 2, Side.BUY, bob.client_id)
        book.submit_order(bob_order)
        book.submit_order(Order("ABC", 10.00, 1, Side.SELL, alice.client_id))
        book.cancel_order(bob_order.order_id)
        book.submit_order(Order("ABC", 8.50, 1, Side.SELL, eve.client_id))

        # Check that the orders weren't matched
        bob_fills = book.get_filled_by_client_id(bob.client_id)
        alice_fills = book.get_filled_by_client_id(alice.client_id)
        eve_fills = book.get_filled_by_client_id(eve.client_id)

        self.assertEqual(len(bob_fills), 0)
        self.assertEqual(len(alice_fills), 0)
        self.assertEqual(len(eve_fills), 0)

        self.assertFalse(book.is_matched())
Esempio n. 2
0
    def test_matching_order(self):
        # Orderbook for ABC
        book = Orderbook('ABC')

        bob = Client('Bob')
        alice = Client('Alice')

        # Bob buys at 10, Alice sells at 10
        book.submit_order(Order("ABC", 10.00, 1, Side.BUY, bob.client_id))
        book.submit_order(Order("ABC", 10.00, 1, Side.SELL, alice.client_id))

        # Check that the orders were matched
        bob_fills = book.get_filled_by_client_id(bob.client_id)
        alice_fills = book.get_filled_by_client_id(alice.client_id)

        self.assertEqual(len(bob_fills), 1)
        self.assertEqual(len(alice_fills), 1)

        # Check that the fills are correctly recorded
        bob_fill = bob_fills[0]
        alice_fill = bob_fills[0]
        self.assertEqual(bob_fill.maker, bob.client_id)
        self.assertEqual(bob_fill.taker, alice.client_id)
        self.assertEqual(bob_fill.size, 1)
        self.assertEqual(bob_fill.side, Side.SELL)
        self.assertEqual(bob_fill.instrument, 'ABC')
        self.assertEqual(bob_fill, alice_fill)
Esempio n. 3
0
    def test_price_time_priority(self):
        # Orderbook for ABC
        book = Orderbook('ABC')

        bob = Client('Bob')
        alice = Client('Alice')
        eve = Client('Eve')

        # Bob buys at 10, Alice sells at 10, Eve tries to sell at 10 as well
        book.submit_order(Order("ABC", 10.00, 1, Side.BUY, bob.client_id))
        book.submit_order(Order("ABC", 10.00, 1, Side.SELL, alice.client_id))
        book.submit_order(Order("ABC", 10.00, 1, Side.SELL, eve.client_id))

        # Check that the orders were matched
        bob_fills = book.get_filled_by_client_id(bob.client_id)
        alice_fills = book.get_filled_by_client_id(alice.client_id)
        eve_fills = book.get_filled_by_client_id(eve.client_id)

        self.assertEqual(len(bob_fills), 1)
        self.assertEqual(len(alice_fills), 1)
        self.assertEqual(len(eve_fills), 0)

        # Check that the fills are correctly recorded
        bob_fill = bob_fills[0]
        alice_fill = bob_fills[0]
        self.assertEqual(bob_fill.maker, bob.client_id)
        self.assertEqual(bob_fill.taker, alice.client_id)
        self.assertEqual(bob_fill.size, 1)
        self.assertEqual(bob_fill.side, Side.SELL)
        self.assertEqual(bob_fill.instrument, 'ABC')
        self.assertEqual(bob_fill, alice_fill)

        # Check that Eve's order is still on the book
        self.assertEqual(len(book.get_orders_by_client_id(eve.client_id)), 1)
Esempio n. 4
0
    def test_invalid_side(self):
        # Try making an order with side of 0
        with self.assertRaises(ValueError):
            o = Order("ABC", 10.00, 5, 0, 123)

        # Try making an order with side of 'BUY'
        with self.assertRaises(ValueError):
            o = Order("ABC", 10.00, 5, 'BUY', 123)
Esempio n. 5
0
    def test_non_integer_size(self):
        # Try making an order with size 'a'
        with self.assertRaises(ValueError):
            o = Order("ABC", 10.00, 'a', Side.BUY, 123)

        # Try making an order with size 1.5
        with self.assertRaises(ValueError):
            o = Order("ABC", 10.00, 1.5, Side.BUY, 123)
Esempio n. 6
0
    def test_serialize_order(self):
        o = Order("ABC", 10.00, 10, Side.BUY, 123)
        o_serialized = Order.serialize(o)

        self.assertEqual(o_serialized, "o|ABC|10.0000|10|BUY|123")

        o = Order("CBA", 12.333, 432, Side.SELL, 4242)
        o_serialized = Order.serialize(o)

        self.assertEqual(o_serialized, "o|CBA|12.3330|432|SELL|4242")
Esempio n. 7
0
def generate_order(instrument, client_id):
    size = int(np.random.normal(SIZE_MEAN, SIZE_SD))
    size = max(1, size)

    if random.random() > 0.5:
        price = np.random.normal(99.00, PRICE_SD)
        return Order(instrument, price, size, Side.BUY, client_id)
    else:
        price = np.random.normal(101.00, PRICE_SD)
        return Order(instrument, price, size, Side.SELL, client_id)
Esempio n. 8
0
    def test_price_time_order(self):
        """
        Test the price-time ordering of orders.

        Orders should be sorted by price first (highest to lowest
            for buy orders and reverse for sell orders) and then
            by time.
        """
        early_order = Order("ABC", 10.00, 1, Side.BUY, 123)
        late_order = Order("ABC", 10.00, 1, Side.BUY, 123)

        self.assertTrue(early_order < late_order,
                        'Early orders should come first')

        low_order = Order("ABC", 10.00, 1, Side.BUY, 123)
        high_order = Order("ABC", 11.00, 1, Side.BUY, 123)

        self.assertTrue(high_order < low_order,
                        'Buy orders with highest price come first')

        low_order = Order("ABC", 10.00, 1, Side.SELL, 123)
        high_order = Order("ABC", 11.00, 1, Side.SELL, 123)

        self.assertTrue(low_order < high_order,
                        'Sell orders with lowest price come first')

        high_order = Order("ABC", 11.00, 1, Side.SELL, 123)
        low_order = Order("ABC", 10.00, 1, Side.SELL, 123)

        self.assertTrue(
            low_order < high_order,
            'Sell orders with lowest price come first, time second')
Esempio n. 9
0
    def test_best_offer(self):
        # Orderbook for ABC
        book = Orderbook('ABC')
        bob = Client('Bob')

        o1 = Order("ABC", 10.00, 1, Side.BUY, bob.client_id)
        book.submit_order(o1)
        self.assertEqual(book.best_offer(), 10.00)

        o2 = Order("ABC", 11.00, 1, Side.BUY, bob.client_id)
        book.submit_order(o2)
        self.assertEqual(book.best_offer(), 11.00)

        # Cancelling the second order should bring the best offer back to 10.00
        book.cancel_order(o2.order_id)
        self.assertEqual(book.best_offer(), 10.00)
Esempio n. 10
0
async def process_message(websocket, path):
    global messages, i, since_update

    msg = await websocket.recv()
    since_update += 1

    message_type = msg.split('|', maxsplit=1)[0]

    if message_type == 'o':
        await websocket.send("ACK")
        o = Order.deserialize(msg)
        if o.size != 0:
            trades = book.submit_order(o)
            """
            if len(trades) > 0:
                print('\n'.join(map(str, trades)))
            """

    elif message_type == 'bb':
        await websocket.send(f"bb|{book.best_bid():.4f}")

    elif message_type == 'bo':
        await websocket.send(f"bo|{book.best_offer():.4f}")

    elif message_type == 'bbbo':
        await websocket.send(
            f"bbbo|{book.best_bid():.4f}|{book.best_offer():.4f}|{time.time_ns()}"
        )
Esempio n. 11
0
    def test_reject_order(self):
        book = Orderbook('ABC')

        bob = Client('Bob')

        # Should not be able to submit an order for another instrument
        with self.assertRaises(RejectedOrder):
            book.submit_order(Order("CBA", 9.00, 2, Side.BUY, bob.client_id))
Esempio n. 12
0
    def test_deserialize_order(self):
        o_serialized = "o|ABC|10.0000|10|BUY|123"
        o = Order.deserialize(o_serialized)

        self.assertEqual(o.instrument, "ABC")
        self.assertEqual(o.price, 10.00)
        self.assertEqual(o.size, 10)
        self.assertEqual(o.side, Side.BUY)
        self.assertEqual(o.client_id, 123)

        o_serialized = "o|CBA|12.3330|432|SELL|4242"

        o = Order.deserialize(o_serialized)

        self.assertEqual(o.instrument, "CBA")
        self.assertEqual(o.price, 12.333)
        self.assertEqual(o.size, 432)
        self.assertEqual(o.side, Side.SELL)
        self.assertEqual(o.client_id, 4242)
Esempio n. 13
0
    def test_split_orders(self):
        # Orderbook for ABC
        book = Orderbook('ABC')

        bob = Client('Bob')
        alice = Client('Alice')
        eve = Client('Eve')

        # Bob buys 2 at 10, Alice sells at 10, Eve tries to sell at 10 as well
        t1 = book.submit_order(Order("ABC", 10.00, 2, Side.BUY, bob.client_id))
        t2 = book.submit_order(
            Order("ABC", 10.00, 1, Side.SELL, alice.client_id))
        t3 = book.submit_order(Order("ABC", 10.00, 1, Side.SELL,
                                     eve.client_id))

        # Check that the orders were matched
        bob_fills = book.get_filled_by_client_id(bob.client_id)
        alice_fills = book.get_filled_by_client_id(alice.client_id)
        eve_fills = book.get_filled_by_client_id(eve.client_id)

        self.assertEqual(len(bob_fills), 2)
        self.assertEqual(len(alice_fills), 1)
        self.assertEqual(len(eve_fills), 1)

        # Check that the fills are correctly recorded
        bob_fill = bob_fills[0]
        alice_fill = alice_fills[0]
        self.assertEqual(bob_fill.maker, bob.client_id)
        self.assertEqual(bob_fill.taker, alice.client_id)
        self.assertEqual(bob_fill.size, 1)
        self.assertEqual(bob_fill.side, Side.SELL)
        self.assertEqual(bob_fill.instrument, 'ABC')
        self.assertEqual(bob_fill, alice_fill)

        bob_fill = bob_fills[1]
        eve_fill = eve_fills[0]
        self.assertEqual(bob_fill.maker, bob.client_id)
        self.assertEqual(bob_fill.taker, eve.client_id)
        self.assertEqual(bob_fill.size, 1)
        self.assertEqual(bob_fill.side, Side.SELL)
        self.assertEqual(bob_fill.instrument, 'ABC')
        self.assertEqual(bob_fill, eve_fill)
Esempio n. 14
0
def generate_order(instrument, client_id):
    global PRICE_MEAN
    price = round(np.random.normal(PRICE_MEAN, PRICE_SD), 2)
    PRICE_MEAN += (random.random() - 0.5) * RANDOM_WALK_COEFF

    size = int(25 * random.random())
    size = max(1, size)

    side = Side.BUY if random.random() > 0.5 else Side.SELL

    return Order(instrument, price, size, side, client_id)
Esempio n. 15
0
    def test_cancel_order(self):
        # Orderbook for ABC
        book = Orderbook('ABC')
        bob = Client('Bob')

        o1 = Order("ABC", 10.00, 1, Side.BUY, bob.client_id)
        book.submit_order(o1)
        self.assertEqual(book.get_order_status(o1.order_id),
                         OrderStatus.ACTIVE)
        book.cancel_order(o1.order_id)
        self.assertEqual(book.get_order_status(o1.order_id),
                         OrderStatus.CANCELLED)
Esempio n. 16
0
async def spam_orders(instrument, client_id):
    while True:
        o = generate_order(instrument, client_id)
        o_serialized = Order.serialize(o)
        msg = o_serialized
        async with websockets.connect(SERVER_ADDRESS) as websocket:
            await websocket.send(msg)
            print(f"> {msg}")

            resp = await websocket.recv()
            print(f"< {resp}")

        delay = np.random.normal(WAIT_MEAN, WAIT_SD)
        await usleep(delay)
Esempio n. 17
0
    def test_order_status(self):
        """
        Order status should be OrderStatus.ACTIVE when the order is first
            created, then change to OrderStatus.FILLED if the order is
            successfully matched, or OrderStatus.CANCELLED if cancelled.
        """
        o = Order("ABC", 50.00, 2, Side.BUY, 123)

        self.assertEqual(o.get_status(), OrderStatus.ACTIVE)

        o.cancel()

        self.assertEqual(o.get_status(), OrderStatus.CANCELLED)
Esempio n. 18
0
 def test_invalid_client_id(self):
     # Try making an order with client_id 'abc'
     with self.assertRaises(ValueError):
         o = Order("ABC", 10.00, 5, Side.BUY, 'abc')
Esempio n. 19
0
 def test_negative_price(self):
     # Try making an order at price of -10.00
     with self.assertRaises(ValueError):
         o = Order("ABC", -10.00, 5, Side.BUY, 123)
Esempio n. 20
0
 def test_negative_size(self):
     # Try making an order with size -5
     with self.assertRaises(ValueError):
         o = Order("ABC", 10.00, -5, Side.BUY, 123)