def test_order_cancel_all(self):
        trading_pair = TradingPair("ETHUSDT", "ETH", "USDT")
        base_quantity = 2.0
        starting_base_balance = 200
        starting_quote_balance = 2000
        self.market.set_balance(trading_pair.base_asset, starting_base_balance)
        self.market.set_balance(trading_pair.quote_asset,
                                starting_quote_balance)
        best_ask_price = self.market.order_books[
            trading_pair.trading_pair].get_price(False)
        self.market.sell(trading_pair.trading_pair, base_quantity,
                         OrderType.LIMIT, best_ask_price)
        best_bid_price = self.market.order_books[
            trading_pair.trading_pair].get_price(True)
        self.market.buy(trading_pair.trading_pair, base_quantity,
                        OrderType.LIMIT, best_bid_price)

        # Market should track limit orders
        self.assertEqual(2, len(self.market.limit_orders))

        asyncio.get_event_loop().run_until_complete(self.market.cancel_all(0))

        # Market should remove all canceled orders
        self.assertEqual(0, len(self.market.limit_orders))

        matched_order_cancel_events = TestUtils.get_match_events(
            self.market_logger.event_log, OrderCancelledEvent, {})
        # Market should emit cancel event
        self.assertEqual(2, len(matched_order_cancel_events))
    def test_order_cancellation(self):
        trading_pair = TradingPair("ETHUSDT", "ETH", "USDT")
        base_quantity = 2.0
        starting_base_balance = 200
        starting_quote_balance = 2000
        self.market.set_balance(trading_pair.base_asset, starting_base_balance)
        self.market.set_balance(trading_pair.quote_asset,
                                starting_quote_balance)
        best_ask_price = self.market.order_books[
            trading_pair.trading_pair].get_price(False)
        ask_client_order_id = self.market.sell(trading_pair.trading_pair,
                                               base_quantity, OrderType.LIMIT,
                                               best_ask_price)
        best_bid_price = self.market.order_books[
            trading_pair.trading_pair].get_price(True)
        bid_client_order_id = self.market.buy(trading_pair.trading_pair,
                                              base_quantity, OrderType.LIMIT,
                                              best_bid_price)

        # Market should track limit orders
        self.assertEqual(2, len(self.market.limit_orders))
        self.market.cancel(trading_pair.trading_pair, ask_client_order_id)

        matched_limit_orders = TestUtils.get_match_limit_orders(
            self.market.limit_orders, {
                "client_order_id": ask_client_order_id,
                "symbol": trading_pair.trading_pair,
                "is_buy": False,
                "base_currency": trading_pair.base_asset,
                "quote_currency": trading_pair.quote_asset,
                "price": best_ask_price,
                "quantity": base_quantity
            })

        # Market should remove canceled orders
        self.assertEqual(0, len(matched_limit_orders))

        matched_order_cancel_events = TestUtils.get_match_events(
            self.market_logger.event_log, OrderCancelledEvent,
            {"order_id": ask_client_order_id})
        # Market should emit cancel event
        self.assertEqual(1, len(matched_order_cancel_events))
    def test_ask_limit_order_trade_match(self):
        """
        Test ask limit order fill and balance simulation, and market events emission
        """
        trading_pair = TradingPair("ETHUSDT", "ETH", "USDT")
        base_quantity = 2.0
        starting_base_balance = 200
        starting_quote_balance = 2000
        self.market.set_balance(trading_pair.base_asset, starting_base_balance)
        self.market.set_balance(trading_pair.quote_asset,
                                starting_quote_balance)

        best_ask_price = self.market.order_books[
            trading_pair.trading_pair].get_price(False)
        client_order_id = self.market.sell(trading_pair.trading_pair,
                                           base_quantity, OrderType.LIMIT,
                                           best_ask_price)

        matched_limit_orders = TestUtils.get_match_limit_orders(
            self.market.limit_orders, {
                "client_order_id": client_order_id,
                "symbol": trading_pair.trading_pair,
                "is_buy": False,
                "base_currency": trading_pair.base_asset,
                "quote_currency": trading_pair.quote_asset,
                "price": best_ask_price,
                "quantity": base_quantity
            })
        # Market should track limit orders
        self.assertEqual(1, len(matched_limit_orders))

        # Market should on hold balance for the created order
        self.assertAlmostEqual(
            float(self.market.on_hold_balances[trading_pair.base_asset]),
            base_quantity)
        # Market should reflect on hold balance in available balance
        self.assertAlmostEqual(
            self.market.get_available_balance(trading_pair.base_asset),
            starting_base_balance - base_quantity)

        matched_order_create_events = TestUtils.get_match_events(
            self.market_logger.event_log, SellOrderCreatedEvent, {
                "type": OrderType.LIMIT,
                "amount": base_quantity,
                "price": best_ask_price,
                "order_id": client_order_id
            })
        # Market should emit BuyOrderCreatedEvent
        self.assertEqual(1, len(matched_order_create_events))

        async def delay_trigger_event2():
            await asyncio.sleep(1)
            trade_event = OrderBookTradeEvent(symbol=trading_pair.trading_pair,
                                              timestamp=time.time(),
                                              type=TradeType.BUY,
                                              price=best_ask_price - 1,
                                              amount=base_quantity)
            self.market.order_books[trading_pair.trading_pair].apply_trade(
                trade_event)

        safe_ensure_future(delay_trigger_event2())

        self.run_parallel(self.market_logger.wait_for(SellOrderCompletedEvent))

        placed_ask_orders: List[LimitOrder] = [
            o for o in self.market.limit_orders if not o.is_buy
        ]

        # Market should delete limit order when it is filled
        self.assertEqual(0, len(placed_ask_orders))

        matched_order_complete_events = TestUtils.get_match_events(
            self.market_logger.event_log, SellOrderCompletedEvent, {
                "order_type": OrderType.LIMIT,
                "quote_asset_amount": base_quantity * base_quantity,
                "order_id": client_order_id
            })
        # Market should emit BuyOrderCompletedEvent
        self.assertEqual(1, len(matched_order_complete_events))

        matched_order_fill_events = TestUtils.get_match_events(
            self.market_logger.event_log, OrderFilledEvent, {
                "order_type": OrderType.LIMIT,
                "trade_type": TradeType.SELL,
                "symbol": trading_pair.trading_pair,
                "order_id": client_order_id
            })
        # Market should emit OrderFilledEvent
        self.assertEqual(1, len(matched_order_fill_events))

        # Market should have no more on hold balance
        self.assertAlmostEqual(
            float(self.market.on_hold_balances[trading_pair.base_asset]), 0)
        # Market should update balance for the filled order
        self.assertAlmostEqual(
            self.market.get_available_balance(trading_pair.base_asset),
            starting_base_balance - base_quantity)