Exemple #1
0
class MatchingEngineTestSuite(AbstractServer):
    """Matching engine test cases."""
    @blocking_call_on_reactor_thread
    @inlineCallbacks
    def setUp(self, annotate=True):
        yield super(MatchingEngineTestSuite, self).setUp(annotate=annotate)
        # Object creation
        self.ask = Ask(
            OrderId(TraderId('2'), OrderNumber(1)),
            AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(30), Timestamp.now())
        self.bid = Bid(
            OrderId(TraderId('4'), OrderNumber(2)),
            AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(30), Timestamp.now())
        self.ask_order = Order(
            OrderId(TraderId('5'), OrderNumber(3)),
            AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(30), Timestamp.now(), True)
        self.bid_order = Order(
            OrderId(TraderId('6'), OrderNumber(4)),
            AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(30), Timestamp.now(), False)
        self.order_book = OrderBook()
        self.matching_engine = MatchingEngine(
            PriceTimeStrategy(self.order_book))

        self.ask_count = 2
        self.bid_count = 2

    def create_ask(self, amount1, amount2):
        """
        Create an ask with a specific price and quantity
        """
        new_ask = Ask(
            OrderId(TraderId('2'), OrderNumber(self.ask_count)),
            AssetPair(AssetAmount(amount1, 'BTC'), AssetAmount(amount2, 'MB')),
            Timeout(30), Timestamp.now())
        self.ask_count += 1
        return new_ask

    def create_bid(self, amount1, amount2):
        """
        Create a bid with a specific price and quantity
        """
        new_bid = Bid(
            OrderId(TraderId('2'), OrderNumber(self.bid_count)),
            AssetPair(AssetAmount(amount1, 'BTC'), AssetAmount(amount2, 'MB')),
            Timeout(30), Timestamp.now())
        self.bid_count += 1
        return new_bid

    @blocking_call_on_reactor_thread
    @inlineCallbacks
    def tearDown(self, annotate=True):
        self.order_book.shutdown_task_manager()
        yield super(MatchingEngineTestSuite, self).tearDown(annotate=annotate)

    def test_empty_match_order_empty(self):
        # Test for match order with an empty order book
        self.order_book.insert_ask(self.ask)
        self.assertEquals([],
                          self.matching_engine.match(
                              self.order_book.get_ask(self.ask.order_id)))
        self.order_book.remove_ask(self.ask.order_id)

        self.order_book.insert_bid(self.bid)
        self.assertEquals([],
                          self.matching_engine.match(
                              self.order_book.get_bid(self.bid.order_id)))
        self.order_book.remove_bid(self.bid.order_id)

    def test_match_order_bid(self):
        # Test for match bid order
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_bid(self.bid)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_bid(self.bid.order_id))
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(3000, matching_ticks[0][2])

    def test_match_order_ask(self):
        # Test for match ask order
        self.order_book.insert_bid(self.bid)
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_ask(self.ask.order_id))
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(3000, matching_ticks[0][2])

    def test_no_match_reserved(self):
        """
        Test whether there is no match when we already reserved some quantity
        """
        self.order_book.insert_bid(self.bid)
        self.order_book.get_tick(self.bid.order_id).reserve_for_matching(3000)
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_ask(self.ask.order_id))
        self.assertEquals([], matching_ticks)

    def test_multiple_price_levels_asks(self):
        """
        Test matching when there are asks in multiple price levels
        """
        self.order_book.insert_ask(self.create_ask(50, 350))
        self.order_book.insert_ask(self.create_ask(18, 72))
        self.order_book.insert_ask(self.create_ask(100, 700))
        my_bid = self.create_bid(200, 2000)
        self.order_book.insert_bid(my_bid)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_bid(my_bid.order_id))

        self.assertEqual(len(matching_ticks), 3)
        total_matched = sum([quantity for _, _, quantity in matching_ticks])
        self.assertEqual(total_matched, 168)

    def test_multiple_price_levels_bids(self):
        """
        Test matching when there are bids in multiple price levels
        """
        self.order_book.insert_bid(self.create_bid(50, 200))
        self.order_book.insert_bid(self.create_bid(18, 72))
        self.order_book.insert_bid(self.create_bid(100, 400))
        my_ask = self.create_ask(200, 200)
        self.order_book.insert_ask(my_ask)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_ask(my_ask.order_id))

        self.assertEqual(len(matching_ticks), 3)
        total_matched = sum([quantity for _, _, quantity in matching_ticks])
        self.assertEqual(total_matched, 168)

    def test_price_time_priority_asks(self):
        """
        Test whether the price-time priority works correctly
        """
        self.order_book.insert_ask(self.create_ask(20, 100))
        self.order_book.insert_ask(self.create_ask(25, 125))
        self.order_book.insert_ask(self.create_ask(10, 50))

        my_bid = self.create_bid(50, 250)
        self.order_book.insert_bid(my_bid)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_bid(my_bid.order_id))

        self.assertEqual(len(matching_ticks), 3)
        self.assertEqual(matching_ticks[-1][1].assets.first.amount, 10)
        self.assertEqual(matching_ticks[-1][2], 5)

    def test_price_time_priority_bids(self):
        """
        Test whether the price-time priority works correctly
        """
        self.order_book.insert_bid(self.create_bid(20, 100))
        self.order_book.insert_bid(self.create_bid(25, 125))
        self.order_book.insert_bid(self.create_bid(10, 50))

        my_ask = self.create_ask(50, 250)
        self.order_book.insert_ask(my_ask)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_ask(my_ask.order_id))

        self.assertEqual(len(matching_ticks), 3)
        self.assertEqual(matching_ticks[-1][1].assets.first.amount, 10)
        self.assertEqual(matching_ticks[-1][2], 5)

    def test_matching_multiple_levels(self):
        """
        Test a matching with multiple price levels
        """
        self.order_book.insert_bid(self.create_bid(10, 60))
        self.order_book.insert_bid(self.create_bid(10, 50))
        my_ask = self.create_ask(30, 180)
        self.order_book.insert_ask(my_ask)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_ask(my_ask.order_id))
        self.assertEqual(len(matching_ticks), 1)
class MatchingEngineTestSuite(AbstractServer):
    """Matching engine test cases."""

    @inlineCallbacks
    def setUp(self):
        yield super(MatchingEngineTestSuite, self).setUp()
        # Object creation
        self.ask = Ask(OrderId(TraderId('2'), OrderNumber(1)),
                       AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')), Timeout(30), Timestamp.now())
        self.bid = Bid(OrderId(TraderId('4'), OrderNumber(2)),
                       AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')), Timeout(30), Timestamp.now())
        self.ask_order = Order(OrderId(TraderId('5'), OrderNumber(3)),
                               AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
                               Timeout(30), Timestamp.now(), True)
        self.bid_order = Order(OrderId(TraderId('6'), OrderNumber(4)),
                               AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
                               Timeout(30), Timestamp.now(), False)
        self.order_book = OrderBook()
        self.matching_engine = MatchingEngine(PriceTimeStrategy(self.order_book))

        self.ask_count = 2
        self.bid_count = 2

    def create_ask(self, amount1, amount2):
        """
        Create an ask with a specific price and quantity
        """
        new_ask = Ask(OrderId(TraderId('2'), OrderNumber(self.ask_count)),
                      AssetPair(AssetAmount(amount1, 'BTC'), AssetAmount(amount2, 'MB')), Timeout(30), Timestamp.now())
        self.ask_count += 1
        return new_ask

    def create_bid(self, amount1, amount2):
        """
        Create a bid with a specific price and quantity
        """
        new_bid = Bid(OrderId(TraderId('3'), OrderNumber(self.bid_count)),
                      AssetPair(AssetAmount(amount1, 'BTC'), AssetAmount(amount2, 'MB')), Timeout(30), Timestamp.now())
        self.bid_count += 1
        return new_bid

    @inlineCallbacks
    def tearDown(self):
        self.order_book.shutdown_task_manager()
        yield super(MatchingEngineTestSuite, self).tearDown()

    def test_empty_match_order_empty(self):
        # Test for match order with an empty order book
        self.order_book.insert_ask(self.ask)
        self.assertEquals([], self.matching_engine.match(self.order_book.get_ask(self.ask.order_id)))
        self.order_book.remove_ask(self.ask.order_id)

        self.order_book.insert_bid(self.bid)
        self.assertEquals([], self.matching_engine.match(self.order_book.get_bid(self.bid.order_id)))
        self.order_book.remove_bid(self.bid.order_id)

    def test_match_order_bid(self):
        # Test for match bid order
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_bid(self.bid)
        matching_ticks = self.matching_engine.match(self.order_book.get_bid(self.bid.order_id))
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(3000, matching_ticks[0][2])

    def test_match_order_ask(self):
        # Test for match ask order
        self.order_book.insert_bid(self.bid)
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.matching_engine.match(self.order_book.get_ask(self.ask.order_id))
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(3000, matching_ticks[0][2])

    def test_no_match_reserved(self):
        """
        Test whether there is no match when we already reserved some quantity
        """
        self.order_book.insert_bid(self.bid)
        self.order_book.get_tick(self.bid.order_id).reserve_for_matching(3000)
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.matching_engine.match(self.order_book.get_ask(self.ask.order_id))
        self.assertEquals([], matching_ticks)

    def test_multiple_price_levels_asks(self):
        """
        Test matching when there are asks in multiple price levels
        """
        self.order_book.insert_ask(self.create_ask(50, 350))
        self.order_book.insert_ask(self.create_ask(18, 72))
        self.order_book.insert_ask(self.create_ask(100, 700))
        my_bid = self.create_bid(200, 2000)
        self.order_book.insert_bid(my_bid)
        matching_ticks = self.matching_engine.match(self.order_book.get_bid(my_bid.order_id))

        self.assertEqual(len(matching_ticks), 3)
        total_matched = sum([quantity for _, _, quantity in matching_ticks])
        self.assertEqual(total_matched, 168)

    def test_multiple_price_levels_bids(self):
        """
        Test matching when there are bids in multiple price levels
        """
        self.order_book.insert_bid(self.create_bid(50, 200))
        self.order_book.insert_bid(self.create_bid(18, 72))
        self.order_book.insert_bid(self.create_bid(100, 400))
        my_ask = self.create_ask(200, 200)
        self.order_book.insert_ask(my_ask)
        matching_ticks = self.matching_engine.match(self.order_book.get_ask(my_ask.order_id))

        self.assertEqual(len(matching_ticks), 3)
        total_matched = sum([quantity for _, _, quantity in matching_ticks])
        self.assertEqual(total_matched, 168)

    def test_price_time_priority_asks(self):
        """
        Test whether the price-time priority works correctly
        """
        self.order_book.insert_ask(self.create_ask(20, 100))
        self.order_book.insert_ask(self.create_ask(25, 125))
        self.order_book.insert_ask(self.create_ask(10, 50))

        my_bid = self.create_bid(50, 250)
        self.order_book.insert_bid(my_bid)
        matching_ticks = self.matching_engine.match(self.order_book.get_bid(my_bid.order_id))

        self.assertEqual(len(matching_ticks), 3)
        self.assertEqual(matching_ticks[-1][1].assets.first.amount, 10)
        self.assertEqual(matching_ticks[-1][2], 5)

    def test_price_time_priority_bids(self):
        """
        Test whether the price-time priority works correctly
        """
        self.order_book.insert_bid(self.create_bid(20, 100))
        self.order_book.insert_bid(self.create_bid(25, 125))
        self.order_book.insert_bid(self.create_bid(10, 50))

        my_ask = self.create_ask(50, 250)
        self.order_book.insert_ask(my_ask)
        matching_ticks = self.matching_engine.match(self.order_book.get_ask(my_ask.order_id))

        self.assertEqual(len(matching_ticks), 3)
        self.assertEqual(matching_ticks[-1][1].assets.first.amount, 10)
        self.assertEqual(matching_ticks[-1][2], 5)

    def test_matching_multiple_levels(self):
        """
        Test a matching with multiple price levels
        """
        self.order_book.insert_bid(self.create_bid(10, 60))
        self.order_book.insert_bid(self.create_bid(10, 50))
        my_ask = self.create_ask(30, 180)
        self.order_book.insert_ask(my_ask)
        matching_ticks = self.matching_engine.match(self.order_book.get_ask(my_ask.order_id))
        self.assertEqual(len(matching_ticks), 1)
class MatchingEngineTestSuite(AbstractServer):
    """Matching engine test cases."""
    @blocking_call_on_reactor_thread
    @inlineCallbacks
    def setUp(self, annotate=True):
        yield super(MatchingEngineTestSuite, self).setUp(annotate=annotate)
        # Object creation
        self.ask = Ask(OrderId(TraderId('2'), OrderNumber(1)),
                       Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(30),
                       Timestamp.now())
        self.bid = Bid(OrderId(TraderId('4'), OrderNumber(2)),
                       Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(30),
                       Timestamp.now())
        self.ask_order = Order(OrderId(TraderId('5'), OrderNumber(3)),
                               Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(30), Timestamp.now(), True)
        self.bid_order = Order(OrderId(TraderId('6'), OrderNumber(4)),
                               Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(30), Timestamp.now(), False)
        self.order_book = OrderBook()
        self.matching_engine = MatchingEngine(
            PriceTimeStrategy(self.order_book))

        self.ask_count = 2
        self.bid_count = 2

    def create_ask(self, price, quantity):
        """
        Create an ask with a specific price and quantity
        """
        new_ask = Ask(OrderId(TraderId('2'), OrderNumber(self.ask_count)),
                      Price(price, 'BTC'), Quantity(quantity, 'MC'),
                      Timeout(30), Timestamp.now())
        self.ask_count += 1
        return new_ask

    def create_bid(self, price, quantity):
        """
        Create a bid with a specific price and quantity
        """
        new_bid = Bid(OrderId(TraderId('2'), OrderNumber(self.bid_count)),
                      Price(price, 'BTC'), Quantity(quantity, 'MC'),
                      Timeout(30), Timestamp.now())
        self.bid_count += 1
        return new_bid

    @blocking_call_on_reactor_thread
    @inlineCallbacks
    def tearDown(self, annotate=True):
        self.order_book.shutdown_task_manager()
        yield super(MatchingEngineTestSuite, self).tearDown(annotate=annotate)

    def test_empty_match_order_empty(self):
        # Test for match order with an empty order book
        self.order_book.insert_ask(self.ask)
        self.assertEquals([],
                          self.matching_engine.match(
                              self.order_book.get_ask(self.ask.order_id)))
        self.order_book.remove_ask(self.ask.order_id)

        self.order_book.insert_bid(self.bid)
        self.assertEquals([],
                          self.matching_engine.match(
                              self.order_book.get_bid(self.bid.order_id)))
        self.order_book.remove_bid(self.bid.order_id)

    def test_match_order_bid(self):
        # Test for match bid order
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_bid(self.bid)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_bid(self.bid.order_id))
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(Quantity(30, 'MC'), matching_ticks[0][2])

    def test_match_order_ask(self):
        # Test for match ask order
        self.order_book.insert_bid(self.bid)
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_ask(self.ask.order_id))
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(Quantity(30, 'MC'), matching_ticks[0][2])

    def test_no_match_reserved(self):
        """
        Test whether there is no match when we already reserved some quantity
        """
        self.order_book.insert_bid(self.bid)
        self.order_book.get_tick(self.bid.order_id).reserve_for_matching(
            Quantity(30, 'MC'))
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_ask(self.ask.order_id))
        self.assertEquals([], matching_ticks)

    def test_multiple_price_levels_asks(self):
        """
        Test matching when there are asks in multiple price levels
        """
        self.order_book.insert_ask(self.create_ask(7, 50))
        self.order_book.insert_ask(self.create_ask(4, 18))
        self.order_book.insert_ask(self.create_ask(7, 100))
        my_bid = self.create_bid(10, 100)
        self.order_book.insert_bid(my_bid)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_bid(my_bid.order_id))

        self.assertEqual(len(matching_ticks), 3)
        total_matched = sum(
            [float(quantity) for _, _, quantity in matching_ticks])
        self.assertEqual(Quantity(total_matched, 'MC'), Quantity(100, 'MC'))

    def test_multiple_price_levels_bids(self):
        """
        Test matching when there are bids in multiple price levels
        """
        self.order_book.insert_bid(self.create_bid(4, 50))
        self.order_book.insert_bid(self.create_bid(7, 18))
        self.order_book.insert_bid(self.create_bid(4, 100))
        my_ask = self.create_ask(1, 100)
        self.order_book.insert_ask(my_ask)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_ask(my_ask.order_id))

        self.assertEqual(len(matching_ticks), 3)
        total_matched = sum(
            [float(quantity) for _, _, quantity in matching_ticks])
        self.assertEqual(Quantity(total_matched, 'MC'), Quantity(100, 'MC'))
class MatchingEngineTestSuite(AbstractServer):
    """Matching engine test cases."""
    @blocking_call_on_reactor_thread
    @inlineCallbacks
    def setUp(self, annotate=True):
        yield super(MatchingEngineTestSuite, self).setUp(annotate=annotate)
        # Object creation
        self.ask = Ask(OrderId(TraderId('2'), OrderNumber(1)),
                       Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(30),
                       Timestamp.now())
        self.bid = Bid(OrderId(TraderId('4'), OrderNumber(2)),
                       Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(30),
                       Timestamp.now())
        self.ask_order = Order(OrderId(TraderId('5'), OrderNumber(3)),
                               Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(30), Timestamp.now(), True)
        self.bid_order = Order(OrderId(TraderId('6'), OrderNumber(4)),
                               Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(30), Timestamp.now(), False)
        self.order_book = OrderBook()
        self.matching_engine = MatchingEngine(
            PriceTimeStrategy(self.order_book))

    @blocking_call_on_reactor_thread
    @inlineCallbacks
    def tearDown(self, annotate=True):
        self.order_book.cancel_all_pending_tasks()
        yield super(MatchingEngineTestSuite, self).tearDown(annotate=annotate)

    def test_empty_match_order_empty(self):
        # Test for match order with an empty order book
        self.order_book.insert_ask(self.ask)
        self.assertEquals([],
                          self.matching_engine.match(
                              self.order_book.get_ask(self.ask.order_id)))
        self.order_book.remove_ask(self.ask.order_id)

        self.order_book.insert_bid(self.bid)
        self.assertEquals([],
                          self.matching_engine.match(
                              self.order_book.get_bid(self.bid.order_id)))
        self.order_book.remove_bid(self.bid.order_id)

    def test_match_order_bid(self):
        # Test for match bid order
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_bid(self.bid)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_bid(self.bid.order_id))
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(Quantity(30, 'MC'), matching_ticks[0][2])

    def test_match_order_ask(self):
        # Test for match ask order
        self.order_book.insert_bid(self.bid)
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_ask(self.ask.order_id))
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(Quantity(30, 'MC'), matching_ticks[0][2])

    def test_no_match_reserved(self):
        """
        Test whether there is no match when we already reserved some quantity
        """
        self.order_book.insert_bid(self.bid)
        self.order_book.get_tick(self.bid.order_id).reserve_for_matching(
            Quantity(30, 'MC'))
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.matching_engine.match(
            self.order_book.get_ask(self.ask.order_id))
        self.assertEquals([], matching_ticks)