예제 #1
0
    def test_get_new_order_book(self, mock_api):
        mock_response = {
            "code": 200,
            "data": {
                "asks": [{
                    "price": "57974.06",
                    "quantity": "0.247421"
                }],
                "bids": [{
                    "price": "57974.01",
                    "quantity": "0.201635"
                }],
                "version": "562370278"
            }
        }
        trading_pair = convert_to_exchange_trading_pair(self.trading_pair)
        tick_url = CONSTANTS.MEXC_DEPTH_URL.format(trading_pair=trading_pair)
        url = CONSTANTS.MEXC_BASE_URL + tick_url
        mock_api.get(url, body=json.dumps(mock_response))

        results = self.async_run_with_timeout(
            asyncio.gather(
                self.data_source.get_new_order_book(self.trading_pair)))
        result: OrderBook = results[0]

        self.assertTrue(type(result) == OrderBook)
예제 #2
0
    async def place_order(self, order_id: str, trading_pair: str,
                          amount: Decimal, is_buy: bool, order_type: OrderType,
                          price: Decimal) -> str:

        if order_type is OrderType.LIMIT:
            order_type_str = "LIMIT_ORDER"
        elif order_type is OrderType.LIMIT_MAKER:
            order_type_str = "POST_ONLY"

        data = {
            'client_order_id': order_id,
            'order_type': order_type_str,
            'trade_type': "BID" if is_buy else "ASK",
            'symbol': convert_to_exchange_trading_pair(trading_pair),
            'quantity': str(amount),
            'price': str(price)
        }

        exchange_order_id = await self._api_request(
            "POST",
            path_url=CONSTANTS.MEXC_PLACE_ORDER,
            params={},
            data=data,
            is_auth_required=True)

        return str(exchange_order_id.get('data'))
    async def get_last_traded_prices(
        cls,
        trading_pairs: List[str],
        throttler: Optional[AsyncThrottler] = None,
        shared_client: Optional[aiohttp.ClientSession] = None
    ) -> Dict[str, float]:
        client = shared_client or cls._get_session_instance()
        throttler = throttler or cls._get_throttler_instance()
        async with throttler.execute_task(CONSTANTS.MEXC_TICKERS_URL):
            url = CONSTANTS.MEXC_BASE_URL + CONSTANTS.MEXC_TICKERS_URL
            async with client.get(url) as products_response:
                products_response: aiohttp.ClientResponse = products_response
                if products_response.status != 200:
                    # raise IOError(f"Error get tickers from MEXC markets. HTTP status is {products_response.status}.")
                    return {}
                data = await products_response.json()
                data = data['data']
                all_markets: pd.DataFrame = pd.DataFrame.from_records(
                    data=data)
                all_markets.set_index("symbol", inplace=True)

                out: Dict[str, float] = {}

                for trading_pair in trading_pairs:
                    exchange_trading_pair = convert_to_exchange_trading_pair(
                        trading_pair)
                    out[trading_pair] = float(
                        all_markets['last'][exchange_trading_pair])
                return out
예제 #4
0
    def test_get_order_book_data(self, mock_api, ms_mock):
        ms_mock.return_value = 1
        mock_response = {
            "code": 200,
            "data": {
                "asks": [{
                    "price": "57974.06",
                    "quantity": "0.247421"
                }],
                "bids": [{
                    "price": "57974.01",
                    "quantity": "0.201635"
                }],
                "ts": 1,
                "version": "562370278"
            }
        }
        trading_pair = convert_to_exchange_trading_pair(self.trading_pair)
        tick_url = CONSTANTS.MEXC_DEPTH_URL.format(trading_pair=trading_pair)
        url = CONSTANTS.MEXC_BASE_URL + tick_url
        mock_api.get(url, body=json.dumps(mock_response))

        results = self.async_run_with_timeout(
            asyncio.gather(
                self.data_source.get_snapshot(self.data_source._shared_client,
                                              self.trading_pair)))
        result = results[0]

        self.assertTrue("asks" in result)
        self.assertGreaterEqual(len(result), 0)
        self.assertEqual(mock_response.get("data"), result)
예제 #5
0
    def test_get_order_book_data_raises_exception_when_response_has_error_code(self, mock_api):
        mock_response = "Erroneous response"
        trading_pair = convert_to_exchange_trading_pair(self.trading_pair)
        tick_url = CONSTANTS.MEXC_DEPTH_URL.format(trading_pair=trading_pair)
        url = CONSTANTS.MEXC_BASE_URL + tick_url
        mock_api.get(url, body=json.dumps(mock_response), status=100)

        with self.assertRaises(IOError) as context:
            self.async_run_with_timeout(self.data_source.get_snapshot(self.data_source._shared_client, self.trading_pair))

        self.assertEqual(str(context.exception),
                         f'Error fetching MEXC market snapshot for {self.trading_pair.replace("-", "_")}. '
                         f'HTTP status is {100}.')
예제 #6
0
    def test_can_get_price_after_order_book_init(self, mock_api):
        trading_pair = convert_to_exchange_trading_pair(self.trading_pair)
        tick_url = CONSTANTS.MEXC_DEPTH_URL.format(trading_pair=trading_pair)
        url = CONSTANTS.MEXC_BASE_URL + tick_url
        mock_api.get(url, body=json.dumps(self.mock_data))

        init_order_books_task = self.ev_loop.create_task(
            self.tracker._init_order_books()
        )
        self.async_run_with_timeout(init_order_books_task)

        ob = self.tracker.order_books[self.trading_pair]
        ask_price = ob.get_price(True)
        self.assertEqual(Decimal("56454.0"), ask_price)
예제 #7
0
    def test_listen_for_snapshots_cancelled_when_fetching_snapshot(self, mock_api):
        trading_pair = convert_to_exchange_trading_pair(self.trading_pair)
        tick_url = CONSTANTS.MEXC_DEPTH_URL.format(trading_pair=trading_pair)
        url = CONSTANTS.MEXC_BASE_URL + tick_url
        mock_api.get(url, exception=asyncio.CancelledError)

        msg_queue: asyncio.Queue = asyncio.Queue()
        with self.assertRaises(asyncio.CancelledError):
            self.listening_task = self.ev_loop.create_task(
                self.data_source.listen_for_order_book_snapshots(self.ev_loop, msg_queue)
            )
            self.async_run_with_timeout(self.listening_task)

        self.assertEqual(msg_queue.qsize(), 0)
예제 #8
0
    def test_listen_for_snapshots_successful(self, mock_api, mock_sleep):
        # the queue and the division by zero error are used just to synchronize the test
        sync_queue = deque()
        sync_queue.append(1)

        mock_response = {"code": 200, "data": {"asks": [{"price": "57974.06", "quantity": "0.247421"}],
                                               "bids": [{"price": "57974.01", "quantity": "0.201635"}],
                                               "version": "562370278"}}
        trading_pair = convert_to_exchange_trading_pair(self.trading_pair)
        tick_url = CONSTANTS.MEXC_DEPTH_URL.format(trading_pair=trading_pair)
        url = CONSTANTS.MEXC_BASE_URL + tick_url
        mock_api.get(url, body=json.dumps(mock_response))

        mock_sleep.side_effect = lambda delay: 1 / 0 if len(sync_queue) == 0 else sync_queue.pop()

        msg_queue: asyncio.Queue = asyncio.Queue()
        with self.assertRaises(ZeroDivisionError):
            self.listening_task = self.ev_loop.create_task(
                self.data_source.listen_for_order_book_snapshots(self.ev_loop, msg_queue))
            self.async_run_with_timeout(self.data_source.listen_for_order_book_snapshots(self.ev_loop, msg_queue))

        self.assertEqual(msg_queue.qsize(), 1)
    async def get_snapshot(
            client: aiohttp.ClientSession,
            trading_pair: str,
            throttler: Optional[AsyncThrottler] = None) -> Dict[str, Any]:
        throttler = throttler or MexcAPIOrderBookDataSource._get_throttler_instance(
        )
        async with throttler.execute_task(CONSTANTS.MEXC_DEPTH_URL):
            trading_pair = convert_to_exchange_trading_pair(trading_pair)
            tick_url = CONSTANTS.MEXC_DEPTH_URL.format(
                trading_pair=trading_pair)
            url = CONSTANTS.MEXC_BASE_URL + tick_url
            async with client.get(url) as response:
                response: aiohttp.ClientResponse = response
                status = response.status
                if status != 200:
                    raise IOError(
                        f"Error fetching MEXC market snapshot for {trading_pair}. "
                        f"HTTP status is {status}.")
                api_data = await response.json()
                data = api_data['data']
                data['ts'] = microseconds()

                return data
예제 #10
0
    def test_init_order_books(self, mock_api):
        trading_pair = convert_to_exchange_trading_pair(self.trading_pair)
        tick_url = CONSTANTS.MEXC_DEPTH_URL.format(trading_pair=trading_pair)
        url = CONSTANTS.MEXC_BASE_URL + tick_url
        mock_api.get(url, body=json.dumps(self.mock_data))

        self.tracker._order_books_initialized.clear()
        self.tracker._tracking_message_queues.clear()
        self.tracker._tracking_tasks.clear()
        self.tracker._order_books.clear()

        self.assertEqual(0, len(self.tracker.order_books))
        self.assertEqual(0, len(self.tracker._tracking_message_queues))
        self.assertEqual(0, len(self.tracker._tracking_tasks))
        self.assertFalse(self.tracker._order_books_initialized.is_set())

        init_order_books_task = self.ev_loop.create_task(
            self.tracker._init_order_books()
        )

        self.async_run_with_timeout(init_order_books_task)

        self.assertIsInstance(self.tracker.order_books[self.trading_pair], OrderBook)
        self.assertTrue(self.tracker._order_books_initialized.is_set())
    async def subscribe_to_order_book_streams(self, trading_pairs: List[str]):
        try:
            for trading_pair in trading_pairs:
                trading_pair = mexc_utils.convert_to_exchange_trading_pair(trading_pair)
                subscribe_deal_request: Dict[str, Any] = {
                    "op": "sub.deal",
                    "symbol": trading_pair,
                }
                async with self._throttler.execute_task(CONSTANTS.MEXC_WS_URL_PUBLIC):
                    await self.send_request_str(json.dumps(subscribe_deal_request))
                subscribe_depth_request: Dict[str, Any] = {
                    "op": "sub.depth",
                    "symbol": trading_pair,
                }
                async with self._throttler.execute_task(CONSTANTS.MEXC_WS_URL_PUBLIC):
                    await self.send_request_str(json.dumps(subscribe_depth_request))

        except asyncio.CancelledError:
            raise
        except Exception:
            self.logger().error(
                "Unexpected error occurred subscribing to order book trading and delta streams...", exc_info=True
            )
            raise