def setUp(self, annotate=True):
        yield super(PriceTimeStrategyTestSuite, self).setUp(annotate=annotate)
        # Object creation
        self.ask = Ask(MessageId(TraderId('0'), MessageNumber('1')),
                       OrderId(TraderId('0'), OrderNumber(1)),
                       Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                       Timestamp.now())
        self.ask2 = Ask(MessageId(TraderId('1'), MessageNumber('1')),
                        OrderId(TraderId('1'), OrderNumber(2)),
                        Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask3 = Ask(MessageId(TraderId('3'), MessageNumber('1')),
                        OrderId(TraderId('0'), OrderNumber(3)),
                        Price(200, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask4 = Ask(MessageId(TraderId('4'), MessageNumber('1')),
                        OrderId(TraderId('1'), OrderNumber(4)),
                        Price(50, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask5 = Ask(MessageId(TraderId('4'), MessageNumber('1')),
                        OrderId(TraderId('1'), OrderNumber(4)),
                        Price(100, 'A'), Quantity(30, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask6 = Ask(MessageId(TraderId('4'), MessageNumber('1')),
                        OrderId(TraderId('1'), OrderNumber(4)),
                        Price(100, 'BTC'), Quantity(30, 'A'), Timeout(100),
                        Timestamp.now())

        self.bid = Bid(MessageId(TraderId('5'), MessageNumber('2')),
                       OrderId(TraderId('0'), OrderNumber(5)),
                       Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                       Timestamp.now())
        self.bid2 = Bid(MessageId(TraderId('6'), MessageNumber('2')),
                        OrderId(TraderId('0'), OrderNumber(6)),
                        Price(200, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                        Timestamp.now())
        self.bid3 = Bid(MessageId(TraderId('7'), MessageNumber('2')),
                        OrderId(TraderId('0'), OrderNumber(7)),
                        Price(50, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())
        self.bid4 = Bid(MessageId(TraderId('8'), MessageNumber('2')),
                        OrderId(TraderId('0'), OrderNumber(8)),
                        Price(100, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())

        self.ask_order = Order(OrderId(TraderId('9'), OrderNumber(11)),
                               Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(100), Timestamp.now(), True)
        self.ask_order2 = Order(OrderId(TraderId('9'), OrderNumber(12)),
                                Price(10, 'BTC'), Quantity(60, 'MC'),
                                Timeout(100), Timestamp.now(), True)

        self.bid_order = Order(OrderId(TraderId('9'), OrderNumber(13)),
                               Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(100), Timestamp.now(), False)
        self.bid_order2 = Order(OrderId(TraderId('9'), OrderNumber(14)),
                                Price(100, 'BTC'), Quantity(60, 'MC'),
                                Timeout(100), Timestamp.now(), False)
        self.order_book = OrderBook(MemoryMessageRepository('0'))
        self.price_time_strategy = PriceTimeStrategy(self.order_book)
Exemple #2
0
 def setUp(self, annotate=True):
     yield super(AbstractTestOrderBook, self).setUp(annotate=annotate)
     # Object creation
     self.ask = Ask(
         OrderId(TraderId('0'), OrderNumber(1)),
         AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')),
         Timeout(100), Timestamp.now())
     self.invalid_ask = Ask(
         OrderId(TraderId('0'), OrderNumber(1)),
         AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')),
         Timeout(0), Timestamp(0.0))
     self.ask2 = Ask(
         OrderId(TraderId('1'), OrderNumber(1)),
         AssetPair(AssetAmount(400, 'BTC'), AssetAmount(30, 'MB')),
         Timeout(100), Timestamp.now())
     self.bid = Bid(
         OrderId(TraderId('2'), OrderNumber(1)),
         AssetPair(AssetAmount(200, 'BTC'), AssetAmount(30, 'MB')),
         Timeout(100), Timestamp.now())
     self.invalid_bid = Bid(
         OrderId(TraderId('0'), OrderNumber(1)),
         AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')),
         Timeout(0), Timestamp(0.0))
     self.bid2 = Bid(
         OrderId(TraderId('3'), OrderNumber(1)),
         AssetPair(AssetAmount(300, 'BTC'), AssetAmount(30, 'MB')),
         Timeout(100), Timestamp.now())
     self.trade = Trade.propose(
         TraderId('0'), OrderId(TraderId('0'), OrderNumber(1)),
         OrderId(TraderId('0'), OrderNumber(1)),
         AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')),
         Timestamp(1462224447.117))
     self.order_book = OrderBook()
Exemple #3
0
class AbstractTestOrderBook(AbstractServer):
    """
    Base class for the order book tests.
    """

    @blocking_call_on_reactor_thread
    @inlineCallbacks
    def setUp(self, annotate=True):
        yield super(AbstractTestOrderBook, self).setUp(annotate=annotate)
        # Object creation
        self.ask = Ask(OrderId(TraderId('0'), OrderNumber(1)), Price(100, 'BTC'), Quantity(30, 'MC'),
                       Timeout(1462224447.117), Timestamp(1462224447.117))
        self.invalid_ask = Ask(OrderId(TraderId('0'), OrderNumber(1)), Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(0), Timestamp(0.0))
        self.ask2 = Ask(OrderId(TraderId('1'), OrderNumber(1)), Price(400, 'BTC'), Quantity(30, 'MC'),
                        Timeout(1462224447.117), Timestamp(1462224447.117))
        self.bid = Bid(OrderId(TraderId('2'), OrderNumber(1)), Price(200, 'BTC'), Quantity(30, 'MC'),
                       Timeout(1462224447.117), Timestamp(1462224447.117))
        self.invalid_bid = Bid(OrderId(TraderId('0'), OrderNumber(1)), Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(0), Timestamp(0.0))
        self.bid2 = Bid(OrderId(TraderId('3'), OrderNumber(1)), Price(300, 'BTC'), Quantity(30, 'MC'),
                        Timeout(1462224447.117), Timestamp(1462224447.117))
        self.trade = Trade.propose(MessageId(TraderId('0'), MessageNumber(1)),
                                   OrderId(TraderId('0'), OrderNumber(1)),
                                   OrderId(TraderId('0'), OrderNumber(1)), Price(100, 'BTC'),
                                   Quantity(30, 'MC'), Timestamp(1462224447.117))
        self.order_book = OrderBook()

    def tearDown(self, annotate=True):
        self.order_book.shutdown_task_manager()
        super(AbstractTestOrderBook, self).tearDown(annotate=annotate)
Exemple #4
0
 def setUp(self, annotate=True):
     yield super(AbstractTestOrderBook, self).setUp(annotate=annotate)
     # Object creation
     self.ask = Ask(OrderId(TraderId('0'), OrderNumber(1)),
                    Price(100, 'BTC'), Quantity(30, 'MC'),
                    Timeout(1462224447.117), Timestamp(1462224447.117))
     self.invalid_ask = Ask(OrderId(TraderId('0'), OrderNumber(1)),
                            Price(100, 'BTC'), Quantity(30, 'MC'),
                            Timeout(0), Timestamp(0.0))
     self.ask2 = Ask(OrderId(TraderId('1'), OrderNumber(1)),
                     Price(400, 'BTC'), Quantity(30, 'MC'),
                     Timeout(1462224447.117), Timestamp(1462224447.117))
     self.bid = Bid(OrderId(TraderId('2'), OrderNumber(1)),
                    Price(200, 'BTC'), Quantity(30, 'MC'),
                    Timeout(1462224447.117), Timestamp(1462224447.117))
     self.invalid_bid = Bid(OrderId(TraderId('0'), OrderNumber(1)),
                            Price(100, 'BTC'), Quantity(30, 'MC'),
                            Timeout(0), Timestamp(0.0))
     self.bid2 = Bid(OrderId(TraderId('3'), OrderNumber(1)),
                     Price(300, 'BTC'), Quantity(30, 'MC'),
                     Timeout(1462224447.117), Timestamp(1462224447.117))
     self.trade = Trade.propose(MessageId(TraderId('0'), MessageNumber(1)),
                                OrderId(TraderId('0'), OrderNumber(1)),
                                OrderId(TraderId('0'), OrderNumber(1)),
                                Price(100, 'BTC'), Quantity(30, 'MC'),
                                Timestamp(1462224447.117))
     self.order_book = OrderBook()
Exemple #5
0
    def setUp(self):
        yield super(PriceTimeStrategyTestSuite, self).setUp()
        # Object creation
        self.ask = Ask(OrderId(TraderId(b'0'), OrderNumber(1)),
                       AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.ask2 = Ask(OrderId(TraderId(b'1'), OrderNumber(2)),
                        AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.ask3 = Ask(OrderId(TraderId(b'0'), OrderNumber(3)),
                        AssetPair(AssetAmount(40000, 'BTC'), AssetAmount(200, 'MB')), Timeout(100), Timestamp.now())
        self.ask4 = Ask(OrderId(TraderId(b'1'), OrderNumber(4)),
                        AssetPair(AssetAmount(3000, 'A'), AssetAmount(3000, 'MB')), Timeout(100), Timestamp.now())
        self.ask5 = Ask(OrderId(TraderId(b'1'), OrderNumber(4)),
                        AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'C')), Timeout(100), Timestamp.now())

        self.bid = Bid(OrderId(TraderId(b'0'), OrderNumber(5)),
                       AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.bid2 = Bid(OrderId(TraderId(b'0'), OrderNumber(6)),
                        AssetPair(AssetAmount(6000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())

        self.ask_order = Order(OrderId(TraderId(b'9'), OrderNumber(11)),
                               AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
                               Timeout(100), Timestamp.now(), True)
        self.ask_order2 = Order(OrderId(TraderId(b'9'), OrderNumber(12)),
                                AssetPair(AssetAmount(600, 'BTC'), AssetAmount(60, 'MB')),
                                Timeout(100), Timestamp.now(), True)

        self.bid_order = Order(OrderId(TraderId(b'9'), OrderNumber(13)),
                               AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
                               Timeout(100), Timestamp.now(), False)
        self.bid_order2 = Order(OrderId(TraderId(b'9'), OrderNumber(14)),
                                AssetPair(AssetAmount(6000, 'BTC'), AssetAmount(60, 'MB')),
                                Timeout(100), Timestamp.now(), False)
        self.order_book = OrderBook()
        self.price_time_strategy = PriceTimeStrategy(self.order_book)
Exemple #6
0
class AbstractTestOrderBook(AbstractServer):
    """
    Base class for the order book tests.
    """

    @inlineCallbacks
    def setUp(self):
        yield super(AbstractTestOrderBook, self).setUp()
        # Object creation
        self.ask = Ask(OrderId(TraderId('0'), OrderNumber(1)),
                       AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.invalid_ask = Ask(OrderId(TraderId('0'), OrderNumber(1)),
                               AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')), Timeout(0), Timestamp(0.0))
        self.ask2 = Ask(OrderId(TraderId('1'), OrderNumber(1)),
                        AssetPair(AssetAmount(400, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.bid = Bid(OrderId(TraderId('2'), OrderNumber(1)),
                       AssetPair(AssetAmount(200, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.invalid_bid = Bid(OrderId(TraderId('0'), OrderNumber(1)),
                               AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')), Timeout(0), Timestamp(0.0))
        self.bid2 = Bid(OrderId(TraderId('3'), OrderNumber(1)),
                        AssetPair(AssetAmount(300, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.trade = Trade.propose(TraderId('0'),
                                   OrderId(TraderId('0'), OrderNumber(1)),
                                   OrderId(TraderId('0'), OrderNumber(1)),
                                   AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')),
                                   Timestamp(1462224447.117))
        self.order_book = OrderBook()

    def tearDown(self):
        self.order_book.shutdown_task_manager()
        super(AbstractTestOrderBook, self).tearDown()
Exemple #7
0
    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 setUp(self):
        yield super(PriceTimeStrategyTestSuite, self).setUp()
        # Object creation
        self.ask = Ask(OrderId(TraderId('0'), OrderNumber(1)),
                       AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.ask2 = Ask(OrderId(TraderId('1'), OrderNumber(2)),
                        AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.ask3 = Ask(OrderId(TraderId('0'), OrderNumber(3)),
                        AssetPair(AssetAmount(40000, 'BTC'), AssetAmount(200, 'MB')), Timeout(100), Timestamp.now())
        self.ask4 = Ask(OrderId(TraderId('1'), OrderNumber(4)),
                        AssetPair(AssetAmount(3000, 'A'), AssetAmount(3000, 'MB')), Timeout(100), Timestamp.now())
        self.ask5 = Ask(OrderId(TraderId('1'), OrderNumber(4)),
                        AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'C')), Timeout(100), Timestamp.now())

        self.bid = Bid(OrderId(TraderId('0'), OrderNumber(5)),
                       AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.bid2 = Bid(OrderId(TraderId('0'), OrderNumber(6)),
                        AssetPair(AssetAmount(6000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())

        self.ask_order = Order(OrderId(TraderId('9'), OrderNumber(11)),
                               AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
                               Timeout(100), Timestamp.now(), True)
        self.ask_order2 = Order(OrderId(TraderId('9'), OrderNumber(12)),
                                AssetPair(AssetAmount(600, 'BTC'), AssetAmount(60, 'MB')),
                                Timeout(100), Timestamp.now(), True)

        self.bid_order = Order(OrderId(TraderId('9'), OrderNumber(13)),
                               AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
                               Timeout(100), Timestamp.now(), False)
        self.bid_order2 = Order(OrderId(TraderId('9'), OrderNumber(14)),
                                AssetPair(AssetAmount(6000, 'BTC'), AssetAmount(60, 'MB')),
                                Timeout(100), Timestamp.now(), False)
        self.order_book = OrderBook()
        self.price_time_strategy = PriceTimeStrategy(self.order_book)
Exemple #9
0
class AbstractTestOrderBook(AbstractServer):
    """
    Base class for the order book tests.
    """
    @inlineCallbacks
    def setUp(self):
        yield super(AbstractTestOrderBook, self).setUp()
        # Object creation
        self.ask = Ask(
            OrderId(TraderId(b'0'), OrderNumber(1)),
            AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(100), Timestamp.now())
        self.invalid_ask = Ask(
            OrderId(TraderId(b'0'), OrderNumber(1)),
            AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(0), Timestamp(0.0))
        self.ask2 = Ask(
            OrderId(TraderId(b'1'), OrderNumber(1)),
            AssetPair(AssetAmount(400, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(100), Timestamp.now())
        self.bid = Bid(
            OrderId(TraderId(b'2'), OrderNumber(1)),
            AssetPair(AssetAmount(200, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(100), Timestamp.now())
        self.invalid_bid = Bid(
            OrderId(TraderId(b'0'), OrderNumber(1)),
            AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(0), Timestamp(0.0))
        self.bid2 = Bid(
            OrderId(TraderId(b'3'), OrderNumber(1)),
            AssetPair(AssetAmount(300, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(100), Timestamp.now())
        self.trade = Trade.propose(
            TraderId(b'0'), OrderId(TraderId(b'0'), OrderNumber(1)),
            OrderId(TraderId(b'0'), OrderNumber(1)),
            AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')),
            Timestamp(1462224447.117))
        self.order_book = OrderBook()

    def tearDown(self):
        self.order_book.shutdown_task_manager()
        super(AbstractTestOrderBook, self).tearDown()
 def setUp(self, annotate=True):
     yield super(MatchingEngineTestSuite, self).setUp(annotate=annotate)
     # Object creation
     self.ask = Ask(
         MessageId(TraderId('1'), MessageNumber('message_number1')),
         OrderId(TraderId('2'), OrderNumber(1)), Price(100, 'BTC'),
         Quantity(30, 'MC'), Timeout(30), Timestamp.now())
     self.bid = Bid(
         MessageId(TraderId('3'), MessageNumber('message_number2')),
         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(MemoryMessageRepository('0'))
     self.matching_engine = MatchingEngine(
         PriceTimeStrategy(self.order_book))
    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
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(
            MessageId(TraderId('1'), MessageNumber('message_number1')),
            OrderId(TraderId('2'), OrderNumber(1)), Price(100, 'BTC'),
            Quantity(30, 'MC'), Timeout(30), Timestamp.now())
        self.bid = Bid(
            MessageId(TraderId('3'), MessageNumber('message_number2')),
            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(MemoryMessageRepository('0'))
        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.assertEquals([], self.matching_engine.match_order(self.bid_order))
        self.assertEquals([], self.matching_engine.match_order(self.ask_order))

    def test_match_order_bid(self):
        # Test for match bid order
        self.order_book.insert_ask(self.ask)
        proposed_trades = self.matching_engine.match_order(self.bid_order)
        self.assertEquals(1, len(proposed_trades))
        self.assertEquals(Price(100, 'BTC'), proposed_trades[0].price)
        self.assertEquals(Quantity(30, 'MC'), proposed_trades[0].quantity)

    def test_match_order_ask(self):
        # Test for match ask order
        self.order_book.insert_bid(self.bid)
        proposed_trades = self.matching_engine.match_order(self.ask_order)
        self.assertEquals(1, len(proposed_trades))
        self.assertEquals(Price(100, 'BTC'), proposed_trades[0].price)
        self.assertEquals(Quantity(30, 'MC'), proposed_trades[0].quantity)
Exemple #13
0
 def setUp(self):
     yield super(AbstractTestOrderBook, self).setUp()
     # Object creation
     self.ask = Ask(OrderId(TraderId('0'), OrderNumber(1)),
                    AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
     self.invalid_ask = Ask(OrderId(TraderId('0'), OrderNumber(1)),
                            AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')), Timeout(0), Timestamp(0.0))
     self.ask2 = Ask(OrderId(TraderId('1'), OrderNumber(1)),
                     AssetPair(AssetAmount(400, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
     self.bid = Bid(OrderId(TraderId('2'), OrderNumber(1)),
                    AssetPair(AssetAmount(200, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
     self.invalid_bid = Bid(OrderId(TraderId('0'), OrderNumber(1)),
                            AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')), Timeout(0), Timestamp(0.0))
     self.bid2 = Bid(OrderId(TraderId('3'), OrderNumber(1)),
                     AssetPair(AssetAmount(300, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
     self.trade = Trade.propose(TraderId('0'),
                                OrderId(TraderId('0'), OrderNumber(1)),
                                OrderId(TraderId('0'), OrderNumber(1)),
                                AssetPair(AssetAmount(100, 'BTC'), AssetAmount(30, 'MB')),
                                Timestamp(1462224447.117))
     self.order_book = OrderBook()
class PriceTimeStrategyTestSuite(AbstractServer):
    """Price time strategy test cases."""
    @blocking_call_on_reactor_thread
    @inlineCallbacks
    def setUp(self, annotate=True):
        yield super(PriceTimeStrategyTestSuite, self).setUp(annotate=annotate)
        # Object creation
        self.ask = Ask(OrderId(TraderId('0'), OrderNumber(1)),
                       Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                       Timestamp.now())
        self.ask2 = Ask(OrderId(TraderId('1'), OrderNumber(2)),
                        Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask3 = Ask(OrderId(TraderId('0'), OrderNumber(3)),
                        Price(200, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask4 = Ask(OrderId(TraderId('1'), OrderNumber(4)),
                        Price(50, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask5 = Ask(OrderId(TraderId('1'), OrderNumber(4)),
                        Price(100, 'A'), Quantity(30, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask6 = Ask(OrderId(TraderId('1'), OrderNumber(4)),
                        Price(100, 'BTC'), Quantity(30, 'A'), Timeout(100),
                        Timestamp.now())

        self.bid = Bid(OrderId(TraderId('0'), OrderNumber(5)),
                       Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                       Timestamp.now())
        self.bid2 = Bid(OrderId(TraderId('0'), OrderNumber(6)),
                        Price(200, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                        Timestamp.now())
        self.bid3 = Bid(OrderId(TraderId('0'), OrderNumber(7)),
                        Price(50, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())
        self.bid4 = Bid(OrderId(TraderId('0'), OrderNumber(8)),
                        Price(100, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())

        self.ask_order = Order(OrderId(TraderId('9'), OrderNumber(11)),
                               Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(100), Timestamp.now(), True)
        self.ask_order2 = Order(OrderId(TraderId('9'), OrderNumber(12)),
                                Price(10, 'BTC'), Quantity(60, 'MC'),
                                Timeout(100), Timestamp.now(), True)

        self.bid_order = Order(OrderId(TraderId('9'), OrderNumber(13)),
                               Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(100), Timestamp.now(), False)
        self.bid_order2 = Order(OrderId(TraderId('9'), OrderNumber(14)),
                                Price(100, 'BTC'), Quantity(60, 'MC'),
                                Timeout(100), Timestamp.now(), False)
        self.order_book = OrderBook()
        self.price_time_strategy = PriceTimeStrategy(self.order_book)

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

    def test_generate_match_id(self):
        """
        Test generation of a match id
        """
        def mocked_get_random_match_id():
            if not mocked_get_random_match_id.called:
                mocked_get_random_match_id.called = True
                return 'a' * 20
            else:
                return 'b' * 20

        mocked_get_random_match_id.called = False

        rand_id = self.price_time_strategy.get_unique_match_id()
        self.assertEqual(len(rand_id), 20)
        self.assertEqual(len(self.price_time_strategy.used_match_ids), 1)

        self.price_time_strategy.get_random_match_id = mocked_get_random_match_id
        self.price_time_strategy.used_match_ids.add('a' * 20)
        self.assertEqual(self.price_time_strategy.get_unique_match_id(),
                         'b' * 20)

    def test_empty_match_order(self):
        """
        Test for match order with an empty order book
        """
        self.assertEquals([],
                          self.price_time_strategy.match(
                              self.bid_order.order_id, self.bid_order.price,
                              self.bid_order.available_quantity, False))
        self.assertEquals([],
                          self.price_time_strategy.match(
                              self.ask_order.order_id, self.ask_order.price,
                              self.ask_order.available_quantity, True))

    def test_match_order_other_price(self):
        """
        Test whether two ticks with different price types are not matched
        """
        self.order_book.insert_ask(self.ask5)
        self.assertEqual([],
                         self.price_time_strategy.match(
                             self.bid_order.order_id, self.bid_order.price,
                             self.bid_order.available_quantity, False))

    def test_match_order_other_quantity(self):
        """
        Test whether two ticks with different quantity types are not matched
        """
        self.order_book.insert_ask(self.ask6)
        self.assertEqual([],
                         self.price_time_strategy.match(
                             self.bid_order.order_id, self.bid_order.price,
                             self.bid_order.available_quantity, False))

    def test_match_order_ask(self):
        """
        Test for match ask order
        """
        self.order_book.insert_bid(self.bid)
        matching_ticks = self.price_time_strategy.match(
            self.ask_order.order_id, self.ask_order.price,
            self.ask_order.available_quantity, True)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(self.order_book.get_tick(self.bid.order_id),
                          matching_ticks[0][1])
        self.assertEquals(Quantity(30, 'MC'), matching_ticks[0][2])

    def test_match_order_bid(self):
        """
        Test for match bid order
        """
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.price_time_strategy.match(
            self.bid_order.order_id, self.bid_order.price,
            self.bid_order.available_quantity, False)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(self.order_book.get_tick(self.ask.order_id),
                          matching_ticks[0][1])
        self.assertEquals(Quantity(30, 'MC'), matching_ticks[0][2])

    def test_match_order_divided(self):
        """
        Test for match order divided over two ticks
        """
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_ask(self.ask2)
        matching_ticks = self.price_time_strategy.match(
            self.bid_order2.order_id, self.bid_order2.price,
            self.bid_order2.available_quantity, False)
        self.assertEquals(2, len(matching_ticks))
        self.assertEquals(Quantity(30, 'MC'), matching_ticks[0][2])
        self.assertEquals(Quantity(30, 'MC'), matching_ticks[1][2])

    def test_match_order_partial_ask(self):
        """
        Test partial matching of a bid order with the matching engine
        """
        self.ask._quantity = Quantity(20, 'MC')
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.price_time_strategy.match(
            self.bid_order2.order_id, self.bid_order2.price,
            self.bid_order2.available_quantity, False)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(Quantity(20, 'MC'), matching_ticks[0][2])

    def test_match_order_partial_bid(self):
        """
        Test partial matching of an ask order with the matching engine
        """
        self.bid._quantity = Quantity(20, 'MC')
        self.order_book.insert_bid(self.bid)
        matching_ticks = self.price_time_strategy.match(
            self.ask_order2.order_id, self.ask_order2.price,
            self.ask_order2.available_quantity, True)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(Quantity(20, 'MC'), matching_ticks[0][2])

    def test_match_order_different_price_level(self):
        """
        Test for match order given an ask order and bid in different price levels
        """
        self.order_book.insert_bid(self.bid2)
        matching_ticks = self.price_time_strategy.match(
            self.ask_order.order_id, self.ask_order.price,
            self.ask_order.available_quantity, True)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(Price(200, 'BTC'), self.bid2.price)
        self.assertEquals(Quantity(30, 'MC'), matching_ticks[0][2])

    def test_search_for_quantity_in_order_book_partial_ask_low(self):
        """
        Test for protected search for quantity in order book partial ask when price is too low
        """
        self.order_book.insert_bid(self.bid)
        self.order_book.insert_bid(self.bid2)
        self.order_book.insert_bid(self.bid3)
        self.order_book.insert_bid(self.bid4)
        matching_ticks = self.price_time_strategy._search_for_quantity_in_order_book_partial_ask(
            self.ask_order2.order_id, Price(100, 'BTC'), Quantity(30, 'MC'),
            [], self.ask_order2.price, True)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(Quantity(30, 'MC'), matching_ticks[0][2])

    def test_search_for_quantity_in_order_book_partial_ask(self):
        """
        Test for protected search for quantity in order book partial ask
        """
        self.order_book.insert_bid(self.bid)
        self.order_book.insert_bid(self.bid2)
        self.order_book.insert_bid(self.bid3)
        self.order_book.insert_bid(self.bid4)
        matching_ticks = self.price_time_strategy._search_for_quantity_in_order_book_partial_ask(
            self.ask_order.order_id, Price(100, 'BTC'), Quantity(30, 'MC'), [],
            self.ask_order.price, True)
        self.assertEquals(0, len(matching_ticks))

    def test_search_for_quantity_in_order_book_partial_bid_high(self):
        """
        Test for protected search for quantity in order book partial bid when price is too high
        """
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_ask(self.ask2)
        self.order_book.insert_ask(self.ask3)
        self.order_book.insert_ask(self.ask4)
        matching_ticks = self.price_time_strategy._search_for_quantity_in_order_book_partial_bid(
            self.bid_order.order_id, Price(100, 'BTC'), Quantity(30, 'MC'), [],
            self.bid_order.price, False)
        self.assertEquals(0, len(matching_ticks))

    def test_search_for_quantity_in_order_book_partial_bid(self):
        """
        Test for protected search for quantity in order book partial bid
        """
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_ask(self.ask2)
        self.order_book.insert_ask(self.ask3)
        self.order_book.insert_ask(self.ask4)
        matching_ticks = self.price_time_strategy._search_for_quantity_in_order_book_partial_bid(
            self.bid_order.order_id, Price(50, 'BTC'), Quantity(30, 'MC'), [],
            self.bid_order.price, False)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(Quantity(30, 'MC'), matching_ticks[0][2])

    def test_search_for_quantity_in_price_level(self):
        """
        Test searching within a price level
        """
        self.bid_order._order_id = self.ask.order_id
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_ask(self.ask2)
        matching_ticks = self.price_time_strategy._search_for_quantity_in_price_level(
            self.bid_order.order_id, None, Quantity(10, 'MC'),
            self.bid_order.price, False)
        self.assertFalse(matching_ticks)

    def test_bid_blocked_for_matching(self):
        """
        Test whether a bid tick is not matched when blocked for matching
        """
        self.order_book.insert_bid(self.bid)
        self.order_book.get_tick(self.bid.order_id).block_for_matching(
            self.ask_order.order_id)
        matching_ticks = self.price_time_strategy.match(
            self.ask_order.order_id, self.ask_order.price,
            self.ask_order.available_quantity, True)
        self.assertEquals(0, len(matching_ticks))

    def test_ask_blocked_for_matching(self):
        """
        Test whether an ask tick is not matched when blocked for matching
        """
        self.order_book.insert_ask(self.ask)
        self.order_book.get_tick(self.ask.order_id).block_for_matching(
            self.bid_order.order_id)
        matching_ticks = self.price_time_strategy.match(
            self.bid_order.order_id, self.bid_order.price,
            self.bid_order.available_quantity, True)
        self.assertEquals(0, len(matching_ticks))
Exemple #15
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 PriceTimeStrategyTestSuite(AbstractServer):
    """Price time strategy test cases."""

    @inlineCallbacks
    def setUp(self):
        yield super(PriceTimeStrategyTestSuite, self).setUp()
        # Object creation
        self.ask = Ask(OrderId(TraderId('0'), OrderNumber(1)),
                       AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.ask2 = Ask(OrderId(TraderId('1'), OrderNumber(2)),
                        AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.ask3 = Ask(OrderId(TraderId('0'), OrderNumber(3)),
                        AssetPair(AssetAmount(40000, 'BTC'), AssetAmount(200, 'MB')), Timeout(100), Timestamp.now())
        self.ask4 = Ask(OrderId(TraderId('1'), OrderNumber(4)),
                        AssetPair(AssetAmount(3000, 'A'), AssetAmount(3000, 'MB')), Timeout(100), Timestamp.now())
        self.ask5 = Ask(OrderId(TraderId('1'), OrderNumber(4)),
                        AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'C')), Timeout(100), Timestamp.now())

        self.bid = Bid(OrderId(TraderId('0'), OrderNumber(5)),
                       AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())
        self.bid2 = Bid(OrderId(TraderId('0'), OrderNumber(6)),
                        AssetPair(AssetAmount(6000, 'BTC'), AssetAmount(30, 'MB')), Timeout(100), Timestamp.now())

        self.ask_order = Order(OrderId(TraderId('9'), OrderNumber(11)),
                               AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
                               Timeout(100), Timestamp.now(), True)
        self.ask_order2 = Order(OrderId(TraderId('9'), OrderNumber(12)),
                                AssetPair(AssetAmount(600, 'BTC'), AssetAmount(60, 'MB')),
                                Timeout(100), Timestamp.now(), True)

        self.bid_order = Order(OrderId(TraderId('9'), OrderNumber(13)),
                               AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
                               Timeout(100), Timestamp.now(), False)
        self.bid_order2 = Order(OrderId(TraderId('9'), OrderNumber(14)),
                                AssetPair(AssetAmount(6000, 'BTC'), AssetAmount(60, 'MB')),
                                Timeout(100), Timestamp.now(), False)
        self.order_book = OrderBook()
        self.price_time_strategy = PriceTimeStrategy(self.order_book)

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

    def test_generate_match_id(self):
        """
        Test generation of a match id
        """
        def mocked_get_random_match_id():
            if not mocked_get_random_match_id.called:
                mocked_get_random_match_id.called = True
                return 'a' * 20
            else:
                return 'b' * 20
        mocked_get_random_match_id.called = False

        rand_id = self.price_time_strategy.get_unique_match_id()
        self.assertEqual(len(rand_id), 20)
        self.assertEqual(len(self.price_time_strategy.used_match_ids), 1)

        self.price_time_strategy.get_random_match_id = mocked_get_random_match_id
        self.price_time_strategy.used_match_ids.add('a' * 20)
        self.assertEqual(self.price_time_strategy.get_unique_match_id(), 'b' * 20)

    def test_empty_match_order(self):
        """
        Test for match order with an empty order book
        """
        self.assertEquals([], self.price_time_strategy.match(self.bid_order.order_id,
                                                             self.bid_order.price,
                                                             self.bid_order.available_quantity, False))
        self.assertEquals([], self.price_time_strategy.match(self.ask_order.order_id,
                                                             self.ask_order.price,
                                                             self.ask_order.available_quantity, True))

    def test_match_order_other_price(self):
        """
        Test whether two ticks with different price types are not matched
        """
        self.order_book.insert_ask(self.ask4)
        self.assertEqual([], self.price_time_strategy.match(self.bid_order.order_id,
                                                            self.bid_order.price,
                                                            self.bid_order.available_quantity, False))

    def test_match_order_other_quantity(self):
        """
        Test whether two ticks with different quantity types are not matched
        """
        self.order_book.insert_ask(self.ask5)
        self.assertEqual([], self.price_time_strategy.match(self.bid_order.order_id,
                                                            self.bid_order.price,
                                                            self.bid_order.available_quantity, False))

    def test_match_order_ask(self):
        """
        Test for match ask order
        """
        self.order_book.insert_bid(self.bid)
        matching_ticks = self.price_time_strategy.match(self.ask_order.order_id, self.ask_order.price,
                                                        self.ask_order.available_quantity, True)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(self.order_book.get_tick(self.bid.order_id), matching_ticks[0][1])
        self.assertEquals(3000, matching_ticks[0][2])

    def test_match_order_bid(self):
        """
        Test for match bid order
        """
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.price_time_strategy.match(self.bid_order.order_id, self.bid_order.price,
                                                        self.bid_order.available_quantity, False)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(self.order_book.get_tick(self.ask.order_id), matching_ticks[0][1])
        self.assertEquals(3000, matching_ticks[0][2])

    def test_match_order_divided(self):
        """
        Test for match order divided over two ticks
        """
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_ask(self.ask2)
        matching_ticks = self.price_time_strategy.match(self.bid_order2.order_id,
                                                        self.bid_order2.price,
                                                        self.bid_order2.available_quantity, False)
        self.assertEquals(2, len(matching_ticks))
        self.assertEquals(3000, matching_ticks[0][2])
        self.assertEquals(3000, matching_ticks[1][2])

    def test_match_order_partial_ask(self):
        """
        Test partial matching of a bid order with the matching engine
        """
        self.ask.traded = 1000
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.price_time_strategy.match(self.bid_order.order_id,
                                                        self.bid_order.price,
                                                        self.bid_order.available_quantity, False)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(2000, matching_ticks[0][2])

    def test_match_order_partial_bid(self):
        """
        Test partial matching of an ask order with the matching engine
        """
        self.bid.traded = 1000
        self.order_book.insert_bid(self.bid)
        matching_ticks = self.price_time_strategy.match(self.ask_order.order_id,
                                                        self.ask_order.price,
                                                        self.ask_order.available_quantity, True)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(2000, matching_ticks[0][2])

    def test_bid_blocked_for_matching(self):
        """
        Test whether a bid tick is not matched when blocked for matching
        """
        self.order_book.insert_bid(self.bid)
        self.order_book.get_tick(self.bid.order_id).block_for_matching(self.ask_order.order_id)
        matching_ticks = self.price_time_strategy.match(self.ask_order.order_id, self.ask_order.price,
                                                        self.ask_order.available_quantity, True)
        self.assertEquals(0, len(matching_ticks))

    def test_ask_blocked_for_matching(self):
        """
        Test whether an ask tick is not matched when blocked for matching
        """
        self.order_book.insert_ask(self.ask)
        self.order_book.get_tick(self.ask.order_id).block_for_matching(self.bid_order.order_id)
        matching_ticks = self.price_time_strategy.match(self.bid_order.order_id, self.bid_order.price,
                                                        self.bid_order.available_quantity, False)
        self.assertEquals(0, len(matching_ticks))
Exemple #18
0
class PriceTimeStrategyTestSuite(AbstractServer):
    """Price time strategy test cases."""
    @blocking_call_on_reactor_thread
    @inlineCallbacks
    def setUp(self, annotate=True):
        yield super(PriceTimeStrategyTestSuite, self).setUp(annotate=annotate)
        # Object creation
        self.ask = Ask(
            OrderId(TraderId('0'), OrderNumber(1)),
            AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(100), Timestamp.now())
        self.ask2 = Ask(
            OrderId(TraderId('1'), OrderNumber(2)),
            AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(100), Timestamp.now())
        self.ask3 = Ask(
            OrderId(TraderId('0'), OrderNumber(3)),
            AssetPair(AssetAmount(40000, 'BTC'), AssetAmount(200, 'MB')),
            Timeout(100), Timestamp.now())
        self.ask4 = Ask(
            OrderId(TraderId('1'), OrderNumber(4)),
            AssetPair(AssetAmount(3000, 'A'), AssetAmount(3000, 'MB')),
            Timeout(100), Timestamp.now())
        self.ask5 = Ask(
            OrderId(TraderId('1'), OrderNumber(4)),
            AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'C')),
            Timeout(100), Timestamp.now())

        self.bid = Bid(
            OrderId(TraderId('0'), OrderNumber(5)),
            AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(100), Timestamp.now())
        self.bid2 = Bid(
            OrderId(TraderId('0'), OrderNumber(6)),
            AssetPair(AssetAmount(6000, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(100), Timestamp.now())

        self.ask_order = Order(
            OrderId(TraderId('9'), OrderNumber(11)),
            AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(100), Timestamp.now(), True)
        self.ask_order2 = Order(
            OrderId(TraderId('9'), OrderNumber(12)),
            AssetPair(AssetAmount(600, 'BTC'), AssetAmount(60, 'MB')),
            Timeout(100), Timestamp.now(), True)

        self.bid_order = Order(
            OrderId(TraderId('9'), OrderNumber(13)),
            AssetPair(AssetAmount(3000, 'BTC'), AssetAmount(30, 'MB')),
            Timeout(100), Timestamp.now(), False)
        self.bid_order2 = Order(
            OrderId(TraderId('9'), OrderNumber(14)),
            AssetPair(AssetAmount(6000, 'BTC'), AssetAmount(60, 'MB')),
            Timeout(100), Timestamp.now(), False)
        self.order_book = OrderBook()
        self.price_time_strategy = PriceTimeStrategy(self.order_book)

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

    def test_generate_match_id(self):
        """
        Test generation of a match id
        """
        def mocked_get_random_match_id():
            if not mocked_get_random_match_id.called:
                mocked_get_random_match_id.called = True
                return 'a' * 20
            else:
                return 'b' * 20

        mocked_get_random_match_id.called = False

        rand_id = self.price_time_strategy.get_unique_match_id()
        self.assertEqual(len(rand_id), 20)
        self.assertEqual(len(self.price_time_strategy.used_match_ids), 1)

        self.price_time_strategy.get_random_match_id = mocked_get_random_match_id
        self.price_time_strategy.used_match_ids.add('a' * 20)
        self.assertEqual(self.price_time_strategy.get_unique_match_id(),
                         'b' * 20)

    def test_empty_match_order(self):
        """
        Test for match order with an empty order book
        """
        self.assertEquals([],
                          self.price_time_strategy.match(
                              self.bid_order.order_id, self.bid_order.price,
                              self.bid_order.available_quantity, False))
        self.assertEquals([],
                          self.price_time_strategy.match(
                              self.ask_order.order_id, self.ask_order.price,
                              self.ask_order.available_quantity, True))

    def test_match_order_other_price(self):
        """
        Test whether two ticks with different price types are not matched
        """
        self.order_book.insert_ask(self.ask4)
        self.assertEqual([],
                         self.price_time_strategy.match(
                             self.bid_order.order_id, self.bid_order.price,
                             self.bid_order.available_quantity, False))

    def test_match_order_other_quantity(self):
        """
        Test whether two ticks with different quantity types are not matched
        """
        self.order_book.insert_ask(self.ask5)
        self.assertEqual([],
                         self.price_time_strategy.match(
                             self.bid_order.order_id, self.bid_order.price,
                             self.bid_order.available_quantity, False))

    def test_match_order_ask(self):
        """
        Test for match ask order
        """
        self.order_book.insert_bid(self.bid)
        matching_ticks = self.price_time_strategy.match(
            self.ask_order.order_id, self.ask_order.price,
            self.ask_order.available_quantity, True)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(self.order_book.get_tick(self.bid.order_id),
                          matching_ticks[0][1])
        self.assertEquals(3000, matching_ticks[0][2])

    def test_match_order_bid(self):
        """
        Test for match bid order
        """
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.price_time_strategy.match(
            self.bid_order.order_id, self.bid_order.price,
            self.bid_order.available_quantity, False)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(self.order_book.get_tick(self.ask.order_id),
                          matching_ticks[0][1])
        self.assertEquals(3000, matching_ticks[0][2])

    def test_match_order_divided(self):
        """
        Test for match order divided over two ticks
        """
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_ask(self.ask2)
        matching_ticks = self.price_time_strategy.match(
            self.bid_order2.order_id, self.bid_order2.price,
            self.bid_order2.available_quantity, False)
        self.assertEquals(2, len(matching_ticks))
        self.assertEquals(3000, matching_ticks[0][2])
        self.assertEquals(3000, matching_ticks[1][2])

    def test_match_order_partial_ask(self):
        """
        Test partial matching of a bid order with the matching engine
        """
        self.ask.traded = 1000
        self.order_book.insert_ask(self.ask)
        matching_ticks = self.price_time_strategy.match(
            self.bid_order.order_id, self.bid_order.price,
            self.bid_order.available_quantity, False)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(2000, matching_ticks[0][2])

    def test_match_order_partial_bid(self):
        """
        Test partial matching of an ask order with the matching engine
        """
        self.bid.traded = 1000
        self.order_book.insert_bid(self.bid)
        matching_ticks = self.price_time_strategy.match(
            self.ask_order.order_id, self.ask_order.price,
            self.ask_order.available_quantity, True)
        self.assertEquals(1, len(matching_ticks))
        self.assertEquals(2000, matching_ticks[0][2])

    def test_bid_blocked_for_matching(self):
        """
        Test whether a bid tick is not matched when blocked for matching
        """
        self.order_book.insert_bid(self.bid)
        self.order_book.get_tick(self.bid.order_id).block_for_matching(
            self.ask_order.order_id)
        matching_ticks = self.price_time_strategy.match(
            self.ask_order.order_id, self.ask_order.price,
            self.ask_order.available_quantity, True)
        self.assertEquals(0, len(matching_ticks))

    def test_ask_blocked_for_matching(self):
        """
        Test whether an ask tick is not matched when blocked for matching
        """
        self.order_book.insert_ask(self.ask)
        self.order_book.get_tick(self.ask.order_id).block_for_matching(
            self.bid_order.order_id)
        matching_ticks = self.price_time_strategy.match(
            self.bid_order.order_id, self.bid_order.price,
            self.bid_order.available_quantity, False)
        self.assertEquals(0, len(matching_ticks))
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 PriceTimeStrategyTestSuite(AbstractServer):
    """Price time strategy test cases."""
    @blocking_call_on_reactor_thread
    @inlineCallbacks
    def setUp(self, annotate=True):
        yield super(PriceTimeStrategyTestSuite, self).setUp(annotate=annotate)
        # Object creation
        self.ask = Ask(MessageId(TraderId('0'), MessageNumber('1')),
                       OrderId(TraderId('0'), OrderNumber(1)),
                       Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                       Timestamp.now())
        self.ask2 = Ask(MessageId(TraderId('1'), MessageNumber('1')),
                        OrderId(TraderId('1'), OrderNumber(2)),
                        Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask3 = Ask(MessageId(TraderId('3'), MessageNumber('1')),
                        OrderId(TraderId('0'), OrderNumber(3)),
                        Price(200, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask4 = Ask(MessageId(TraderId('4'), MessageNumber('1')),
                        OrderId(TraderId('1'), OrderNumber(4)),
                        Price(50, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask5 = Ask(MessageId(TraderId('4'), MessageNumber('1')),
                        OrderId(TraderId('1'), OrderNumber(4)),
                        Price(100, 'A'), Quantity(30, 'MC'), Timeout(100),
                        Timestamp.now())
        self.ask6 = Ask(MessageId(TraderId('4'), MessageNumber('1')),
                        OrderId(TraderId('1'), OrderNumber(4)),
                        Price(100, 'BTC'), Quantity(30, 'A'), Timeout(100),
                        Timestamp.now())

        self.bid = Bid(MessageId(TraderId('5'), MessageNumber('2')),
                       OrderId(TraderId('0'), OrderNumber(5)),
                       Price(100, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                       Timestamp.now())
        self.bid2 = Bid(MessageId(TraderId('6'), MessageNumber('2')),
                        OrderId(TraderId('0'), OrderNumber(6)),
                        Price(200, 'BTC'), Quantity(30, 'MC'), Timeout(100),
                        Timestamp.now())
        self.bid3 = Bid(MessageId(TraderId('7'), MessageNumber('2')),
                        OrderId(TraderId('0'), OrderNumber(7)),
                        Price(50, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())
        self.bid4 = Bid(MessageId(TraderId('8'), MessageNumber('2')),
                        OrderId(TraderId('0'), OrderNumber(8)),
                        Price(100, 'BTC'), Quantity(200, 'MC'), Timeout(100),
                        Timestamp.now())

        self.ask_order = Order(OrderId(TraderId('9'), OrderNumber(11)),
                               Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(100), Timestamp.now(), True)
        self.ask_order2 = Order(OrderId(TraderId('9'), OrderNumber(12)),
                                Price(10, 'BTC'), Quantity(60, 'MC'),
                                Timeout(100), Timestamp.now(), True)

        self.bid_order = Order(OrderId(TraderId('9'), OrderNumber(13)),
                               Price(100, 'BTC'), Quantity(30, 'MC'),
                               Timeout(100), Timestamp.now(), False)
        self.bid_order2 = Order(OrderId(TraderId('9'), OrderNumber(14)),
                                Price(100, 'BTC'), Quantity(60, 'MC'),
                                Timeout(100), Timestamp.now(), False)
        self.order_book = OrderBook(MemoryMessageRepository('0'))
        self.price_time_strategy = PriceTimeStrategy(self.order_book)

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

    def test_empty_match_order(self):
        # Test for match order with an empty order book
        self.assertEquals([],
                          self.price_time_strategy.match_order(self.bid_order))
        self.assertEquals([],
                          self.price_time_strategy.match_order(self.ask_order))

    def test_match_order_other_price(self):
        """
        Test whether two ticks with different price types are not matched
        """
        self.order_book.insert_ask(self.ask5)
        self.assertEqual([],
                         self.price_time_strategy.match_order(self.bid_order))

    def test_match_order_other_quantity(self):
        """
        Test whether two ticks with different quantity types are not matched
        """
        self.order_book.insert_ask(self.ask6)
        self.assertEqual([],
                         self.price_time_strategy.match_order(self.bid_order))

    def test_match_order_ask(self):
        # Test for match order
        self.order_book.insert_bid(self.bid)
        proposed_trades = self.price_time_strategy.match_order(self.ask_order)
        self.assertEquals(1, len(proposed_trades))
        self.assertEquals(Price(100, 'BTC'), proposed_trades[0].price)
        self.assertEquals(Quantity(30, 'MC'), proposed_trades[0].quantity)

    def test_match_order_bid(self):
        # Test for match order
        self.order_book.insert_ask(self.ask)
        proposed_trades = self.price_time_strategy.match_order(self.bid_order)
        self.assertEquals(1, len(proposed_trades))
        self.assertEquals(Price(100, 'BTC'), proposed_trades[0].price)
        self.assertEquals(Quantity(30, 'MC'), proposed_trades[0].quantity)

    def test_match_order_divided(self):
        # Test for match order divided over two ticks
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_ask(self.ask2)
        proposed_trades = self.price_time_strategy.match_order(self.bid_order2)
        self.assertEquals(2, len(proposed_trades))
        self.assertEquals(Price(100, 'BTC'), proposed_trades[0].price)
        self.assertEquals(Quantity(30, 'MC'), proposed_trades[0].quantity)
        self.assertEquals(Price(100, 'BTC'), proposed_trades[1].price)
        self.assertEquals(Quantity(30, 'MC'), proposed_trades[1].quantity)

    def test_match_order_partial_ask(self):
        """
        Test partial matching of a bid order with the matching engine
        """
        self.ask._quantity = Quantity(20, 'MC')
        self.order_book.insert_ask(self.ask)
        proposed_trades = self.price_time_strategy.match_order(self.bid_order2)
        self.assertEquals(1, len(proposed_trades))

    def test_match_order_partial_bid(self):
        """
        Test partial matching of an ask order with the matching engine
        """
        self.bid._quantity = Quantity(20, 'MC')
        self.order_book.insert_bid(self.bid)
        proposed_trades = self.price_time_strategy.match_order(self.ask_order2)
        self.assertEquals(1, len(proposed_trades))

    def test_match_order_different_price_level(self):
        # Test for match order given an ask order and bid in different price levels
        self.order_book.insert_bid(self.bid2)
        proposed_trades = self.price_time_strategy.match_order(self.ask_order)
        self.assertEquals(1, len(proposed_trades))
        self.assertEquals(Price(200, 'BTC'), proposed_trades[0].price)
        self.assertEquals(Quantity(30, 'MC'), proposed_trades[0].quantity)

    def test_search_for_quantity_in_order_book_partial_ask_low(self):
        # Test for protected search for quantity in order book partial ask when price is too low
        self.order_book.insert_bid(self.bid)
        self.order_book.insert_bid(self.bid2)
        self.order_book.insert_bid(self.bid3)
        self.order_book.insert_bid(self.bid4)
        quantity_to_trade, proposed_trades = self.price_time_strategy._search_for_quantity_in_order_book_partial_ask(
            Price(100, 'BTC'), Quantity(30, 'MC'), [], self.ask_order2)
        self.assertEquals(1, len(proposed_trades))
        self.assertEquals(Quantity(0, 'MC'), quantity_to_trade)

    def test_search_for_quantity_in_order_book_partial_ask(self):
        # Test for protected search for quantity in order book partial ask
        self.order_book.insert_bid(self.bid)
        self.order_book.insert_bid(self.bid2)
        self.order_book.insert_bid(self.bid3)
        self.order_book.insert_bid(self.bid4)
        quantity_to_trade, proposed_trades = self.price_time_strategy._search_for_quantity_in_order_book_partial_ask(
            Price(100, 'BTC'), Quantity(30, 'MC'), [], self.ask_order)
        self.assertEquals(0, len(proposed_trades))
        self.assertEquals(Quantity(30, 'MC'), quantity_to_trade)

    def test_search_for_quantity_in_order_book_partial_bid_high(self):
        # Test for protected search for quantity in order book partial bid when price is too high
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_ask(self.ask2)
        self.order_book.insert_ask(self.ask3)
        self.order_book.insert_ask(self.ask4)
        quantity_to_trade, proposed_trades = self.price_time_strategy._search_for_quantity_in_order_book_partial_bid(
            Price(100, 'BTC'), Quantity(30, 'MC'), [], self.bid_order)
        self.assertEquals(0, len(proposed_trades))
        self.assertEquals(Quantity(30, 'MC'), quantity_to_trade)

    def test_search_for_quantity_in_order_book_partial_bid(self):
        # Test for protected search for quantity in order book partial bid
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_ask(self.ask2)
        self.order_book.insert_ask(self.ask3)
        self.order_book.insert_ask(self.ask4)
        quantity_to_trade, proposed_trades = self.price_time_strategy._search_for_quantity_in_order_book_partial_bid(
            Price(50, 'BTC'), Quantity(30, 'MC'), [], self.bid_order)
        self.assertEquals(1, len(proposed_trades))
        self.assertEquals(Quantity(0, 'MC'), quantity_to_trade)

    def test_search_for_quantity_in_price_level(self):
        """
        Test searching within a price level
        """
        self.bid_order._order_id = self.ask.order_id
        self.order_book.insert_ask(self.ask)
        self.order_book.insert_ask(self.ask2)
        _, trades = self.price_time_strategy._search_for_quantity_in_price_level(
            None, Quantity(10, 'MC'), self.bid_order)
        self.assertFalse(trades)

        _, trades = self.price_time_strategy._search_for_quantity_in_price_level(
            self.order_book.get_tick(self.bid_order.order_id),
            Quantity(10, 'MC'), self.bid_order)
        self.assertFalse(trades)

        self.bid_order2.reserve_quantity_for_tick(self.ask2.order_id,
                                                  Quantity(60, 'MC'))
        _, trades = self.price_time_strategy._search_for_quantity_in_price_level(
            self.order_book.get_tick(self.ask2.order_id), Quantity(10, 'MC'),
            self.bid_order2)
        self.assertFalse(trades)
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)