Beispiel #1
0
 async def _execute_cancel(self, trading_pair: str, order_id: str) -> str:
     """
     Executes order cancellation process by first calling cancel-order API. The API result doesn't confirm whether
     the cancellation is successful, it simply states it receives the request.
     :param trading_pair: The market trading pair
     :param order_id: The internal order id
     order.last_state to change to CANCELED
     """
     try:
         tracked_order = self._in_flight_orders.get(order_id)
         if tracked_order is None:
             raise ValueError(
                 f"Failed to cancel order - {order_id}. Order not found.")
         if tracked_order.exchange_order_id is None:
             await tracked_order.get_exchange_order_id()
         ex_order_id = tracked_order.exchange_order_id
         await self._api_request(
             "post", "private/cancel-order", {
                 "instrument_name":
                 crypto_com_utils.convert_to_exchange_trading_pair(
                     trading_pair),
                 "order_id":
                 ex_order_id
             }, True)
         return order_id
     except asyncio.CancelledError:
         raise
     except Exception as e:
         self.logger().network(
             f"Failed to cancel order {order_id}: {str(e)}",
             exc_info=True,
             app_warning_msg=
             f"Failed to cancel the order {order_id} on CryptoCom. "
             f"Check API key and network connection.")
    async def get_order_book_data(
            trading_pair: str,
            throttler: Optional[AsyncThrottler] = None) -> Dict[str, any]:
        """
        Retrieves the JSON order book data of the specified trading pair using the exchange's REST API.
        :param trading_pair: Specified trading pair.
        :param throttler: Optional AsyncThrottler used to throttle the API request.
        """
        throttler = throttler or CryptoComAPIOrderBookDataSource._get_throttler_instance(
        )
        async with aiohttp.ClientSession() as client:
            async with throttler.execute_task(
                    CONSTANTS.GET_ORDER_BOOK_PATH_URL):
                url = crypto_com_utils.get_rest_url(
                    CONSTANTS.GET_ORDER_BOOK_PATH_URL)
                params = {
                    "depth":
                    150,
                    "instrument_name":
                    crypto_com_utils.convert_to_exchange_trading_pair(
                        trading_pair),
                }
                orderbook_response = await client.get(url=url, params=params)

                if orderbook_response.status != 200:
                    raise IOError(
                        f"Error fetching OrderBook for {trading_pair} at {CONSTANTS.EXCHANGE_NAME}. "
                        f"HTTP status is {orderbook_response.status}.")

                orderbook_data: List[Dict[str, Any]] = await safe_gather(
                    orderbook_response.json())
                orderbook_data = orderbook_data[0]["result"]["data"][0]

            return orderbook_data
 def setUpClass(cls) -> None:
     super().setUpClass()
     cls.ev_loop = asyncio.get_event_loop()
     cls.base_asset = "COINALPHA"
     cls.quote_asset = "HBOT"
     cls.trading_pair = f"{cls.base_asset}-{cls.quote_asset}"
     cls.ex_trading_pair = crypto_com_utils.convert_to_exchange_trading_pair(
         cls.trading_pair)
Beispiel #4
0
    async def cancel_all(self, timeout_seconds: float):
        """
        Cancels all in-flight orders and waits for cancellation results.
        Used by bot's top level stop and exit commands (cancelling outstanding orders on exit)
        :param timeout_seconds: The timeout at which the operation will be canceled.
        :returns List of CancellationResult which indicates whether each order is successfully cancelled.
        """
        if self._trading_pairs is None:
            raise Exception(
                "cancel_all can only be used when trading_pairs are specified."
            )
        tracked_orders: Dict[
            str,
            CryptoComInFlightOrder] = self._in_flight_orders.copy().items()
        cancellation_results = []
        try:
            tasks = []

            for _, order in tracked_orders:
                api_params = {
                    "instrument_name":
                    crypto_com_utils.convert_to_exchange_trading_pair(
                        order.trading_pair),
                    "order_id":
                    order.exchange_order_id,
                }
                tasks.append(
                    self._api_request(method="post",
                                      path_url=CONSTANTS.CANCEL_ORDER_PATH_URL,
                                      params=api_params,
                                      is_auth_required=True))

            await safe_gather(*tasks)

            open_orders = await self.get_open_orders()
            for cl_order_id, tracked_order in tracked_orders:
                open_order = [
                    o for o in open_orders if o.client_order_id == cl_order_id
                ]
                if not open_order:
                    cancellation_results.append(
                        CancellationResult(cl_order_id, True))
                    self.trigger_event(
                        MarketEvent.OrderCancelled,
                        OrderCancelledEvent(self.current_timestamp,
                                            cl_order_id))
                    self.stop_tracking_order(cl_order_id)
                else:
                    cancellation_results.append(
                        CancellationResult(cl_order_id, False))
        except Exception:
            self.logger().network(
                "Failed to cancel all orders.",
                exc_info=True,
                app_warning_msg=
                "Failed to cancel all orders on Crypto.com. Check API key and network connection."
            )
        return cancellation_results
Beispiel #5
0
 async def cancel_all(self, timeout_seconds: float):
     """
     Cancels all in-flight orders and waits for cancellation results.
     Used by bot's top level stop and exit commands (cancelling outstanding orders on exit)
     :param timeout_seconds: The timeout at which the operation will be canceled.
     :returns List of CancellationResult which indicates whether each order is successfully cancelled.
     """
     if self._trading_pairs is None:
         raise Exception(
             "cancel_all can only be used when trading_pairs are specified."
         )
     cancellation_results = []
     try:
         for trading_pair in self._trading_pairs:
             await self._api_request(
                 "post", "private/cancel-all-orders", {
                     "instrument_name":
                     crypto_com_utils.convert_to_exchange_trading_pair(
                         trading_pair)
                 }, True)
         open_orders = await self.get_open_orders()
         for cl_order_id, tracked_order in self._in_flight_orders.items():
             open_order = [
                 o for o in open_orders if o.client_order_id == cl_order_id
             ]
             if not open_order:
                 cancellation_results.append(
                     CancellationResult(cl_order_id, True))
                 self.trigger_event(
                     MarketEvent.OrderCancelled,
                     OrderCancelledEvent(self.current_timestamp,
                                         cl_order_id))
             else:
                 cancellation_results.append(
                     CancellationResult(cl_order_id, False))
     except Exception:
         self.logger().network(
             "Failed to cancel all orders.",
             exc_info=True,
             app_warning_msg=
             "Failed to cancel all orders on Crypto.com. Check API key and network connection."
         )
     return cancellation_results
Beispiel #6
0
    async def _create_order(self, trade_type: TradeType, order_id: str,
                            trading_pair: str, amount: Decimal,
                            order_type: OrderType, price: Decimal):
        """
        Calls create-order API end point to place an order, starts tracking the order and triggers order created event.
        :param trade_type: BUY or SELL
        :param order_id: Internal order id (also called client_order_id)
        :param trading_pair: The market to place order
        :param amount: The order amount (in base token value)
        :param order_type: The order type
        :param price: The order price
        """
        if not order_type.is_limit_type():
            raise Exception(f"Unsupported order type: {order_type}")
        trading_rule = self._trading_rules[trading_pair]

        amount = self.quantize_order_amount(trading_pair, amount)
        price = self.quantize_order_price(trading_pair, price)
        if amount < trading_rule.min_order_size:
            raise ValueError(
                f"Buy order amount {amount} is lower than the minimum order size "
                f"{trading_rule.min_order_size}.")
        api_params = {
            "instrument_name":
            crypto_com_utils.convert_to_exchange_trading_pair(trading_pair),
            "side":
            trade_type.name,
            "type":
            "LIMIT",
            "price":
            f"{price:f}",
            "quantity":
            f"{amount:f}",
            "client_oid":
            order_id
        }
        if order_type is OrderType.LIMIT_MAKER:
            api_params["exec_inst"] = "POST_ONLY"
        self.start_tracking_order(order_id, None, trading_pair, trade_type,
                                  price, amount, order_type)
        try:
            order_result = await self._api_request("post",
                                                   "private/create-order",
                                                   api_params, True)
            exchange_order_id = str(order_result["result"]["order_id"])
            tracked_order = self._in_flight_orders.get(order_id)
            if tracked_order is not None:
                self.logger().info(
                    f"Created {order_type.name} {trade_type.name} order {order_id} for "
                    f"{amount} {trading_pair}.")
                tracked_order.update_exchange_order_id(exchange_order_id)

            event_tag = MarketEvent.BuyOrderCreated if trade_type is TradeType.BUY else MarketEvent.SellOrderCreated
            event_class = BuyOrderCreatedEvent if trade_type is TradeType.BUY else SellOrderCreatedEvent
            self.trigger_event(
                event_tag,
                event_class(self.current_timestamp, order_type, trading_pair,
                            amount, price, order_id))
        except asyncio.CancelledError:
            raise
        except Exception as e:
            self.stop_tracking_order(order_id)
            self.logger().network(
                f"Error submitting {trade_type.name} {order_type.name} order to Crypto.com for "
                f"{amount} {trading_pair} "
                f"{price}.",
                exc_info=True,
                app_warning_msg=str(e))
            self.trigger_event(
                MarketEvent.OrderFailure,
                MarketOrderFailureEvent(self.current_timestamp, order_id,
                                        order_type))