Esempio n. 1
0
    async def _create_order(self,
                            trade_type: TradeType,
                            order_id: str,
                            trading_pair: str,
                            amount: Decimal,
                            price: Decimal = s_decimal_0,
                            order_type: OrderType = OrderType.MARKET):
        """
        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 price: The order price
        :param order_type: The order type
        """
        trading_rule: TradingRule = self._trading_rules[trading_pair]

        trading_pair_ids: Dict[
            str,
            int] = await self._order_book_tracker.data_source.get_instrument_ids(
            )

        try:
            amount: Decimal = self.quantize_order_amount(trading_pair, amount)
            if amount < trading_rule.min_order_size:
                raise ValueError(
                    f"{trade_type.name} order amount {amount} is lower than the minimum order size "
                    f"{trading_rule.min_order_size}.")

            params = {
                "InstrumentId": trading_pair_ids[trading_pair],
                "OMSId": 1,
                "AccountId": await self.initialized_account_id(),
                "ClientOrderId": int(order_id),
                "Side": 0 if trade_type == TradeType.BUY else 1,
                "Quantity": amount,
                "TimeInForce": 1,  # GTC
            }

            if order_type.is_limit_type():
                price: Decimal = self.quantize_order_price(trading_pair, price)

                params.update({
                    "OrderType": 2,  # Limit
                    "LimitPrice": price,
                })
            else:
                params.update({
                    "OrderType": 1  # Market
                })

            self.start_tracking_order(order_id, None, trading_pair, trade_type,
                                      price, amount, order_type)

            send_order_results = await self._api_request(
                method="POST",
                path_url=CONSTANTS.SEND_ORDER_PATH_URL,
                data=params,
                is_auth_required=True)

            if send_order_results["status"] == "Rejected":
                raise ValueError(
                    f"Order is rejected by the API. "
                    f"Parameters: {params} Error Msg: {send_order_results['errormsg']}"
                )

            exchange_order_id = str(send_order_results["OrderId"])
            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)

        except asyncio.CancelledError:
            raise
        except Exception as e:
            self.stop_tracking_order(order_id)
            self.trigger_event(
                MarketEvent.OrderFailure,
                MarketOrderFailureEvent(self.current_timestamp, order_id,
                                        order_type))
            self.logger().network(
                f"Error submitting {trade_type.name} {order_type.name} order to NDAX for "
                f"{amount} {trading_pair} {price}. Error: {str(e)}",
                exc_info=True,
                app_warning_msg="Error submitting order to NDAX. ")
Esempio n. 2
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))
Esempio n. 3
0
    async def execute_sell(self,
                           order_id: str,
                           trading_pair: str,
                           amount: Decimal,
                           order_type: OrderType,
                           price: Optional[Decimal] = s_decimal_0):

        trading_rule = self._trading_rules[trading_pair]

        if not order_type.is_limit_type():
            self.trigger_event(
                self.MARKET_ORDER_FAILURE_EVENT_TAG,
                MarketOrderFailureEvent(self.current_timestamp, order_id,
                                        order_type))
            raise Exception(f"Unsupported order type: {order_type}")

        decimal_price = self.quantize_order_price(trading_pair, price)
        decimal_amount = self.quantize_order_amount(trading_pair, amount,
                                                    decimal_price)

        if decimal_price * decimal_amount < trading_rule.min_notional_size:
            self.trigger_event(
                self.MARKET_ORDER_FAILURE_EVENT_TAG,
                MarketOrderFailureEvent(self.current_timestamp, order_id,
                                        order_type))
            raise ValueError(
                f"Sell order amount {decimal_amount} is lower than the notional size "
            )

        try:
            exchange_order_id = await self.place_order(order_id, trading_pair,
                                                       decimal_amount, False,
                                                       order_type,
                                                       decimal_price)
            self.start_tracking_order(order_id=order_id,
                                      exchange_order_id=exchange_order_id,
                                      trading_pair=trading_pair,
                                      order_type=order_type,
                                      trade_type=TradeType.SELL,
                                      price=decimal_price,
                                      amount=decimal_amount)
            tracked_order = self._in_flight_orders.get(order_id)
            if tracked_order is not None:
                self.logger().info(
                    f"Created {order_type.name.upper()} sell order {order_id} for {decimal_amount} {trading_pair}."
                )
            self.trigger_event(
                self.MARKET_SELL_ORDER_CREATED_EVENT_TAG,
                SellOrderCreatedEvent(self.current_timestamp, order_type,
                                      trading_pair, decimal_amount,
                                      decimal_price, order_id))
        except asyncio.CancelledError:
            raise
        except Exception as ex:
            self.stop_tracking_order(order_id)
            order_type_str = order_type.name.lower()
            self.logger().network(
                f"Error submitting sell {order_type_str} order to Mexc for "
                f"{decimal_amount} {trading_pair} "
                f"{decimal_price if order_type is OrderType.LIMIT else ''}."
                f"{decimal_price}." + ",ex:" + repr(ex),
                exc_info=True,
                app_warning_msg=
                "Failed to submit sell order to Mexc. Check API key and network connection."
            )
            self.trigger_event(
                self.MARKET_ORDER_FAILURE_EVENT_TAG,
                MarketOrderFailureEvent(self.current_timestamp, order_id,
                                        order_type))
Esempio n. 4
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}.")
        order_type_str = order_type.name.lower().split("_")[0]
        api_params = {"market": convert_to_exchange_trading_pair(trading_pair),
                      "side": trade_type.name.lower(),
                      "ord_type": order_type_str,
                      "price": f"{price:f}",
                      "volume": f"{amount:f}",
                      }
        # if order_type is OrderType.LIMIT_MAKER:
        #     api_params["postOnly"] = "true"
        self.start_tracking_order(order_id, None, trading_pair, trade_type, price, amount, order_type)
        try:
            order_result = await self._api_request("POST", Constants.ENDPOINT["ORDER_CREATE"], api_params, True)
            exchange_order_id = str(order_result["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)
            if trade_type is TradeType.BUY:
                event_tag = MarketEvent.BuyOrderCreated
                event_cls = BuyOrderCreatedEvent
            else:
                event_tag = MarketEvent.SellOrderCreated
                event_cls = SellOrderCreatedEvent
            self.trigger_event(event_tag,
                               event_cls(self.current_timestamp, order_type, trading_pair, amount, price, order_id))
        except asyncio.CancelledError:
            raise
        except AltmarketsAPIError as e:
            error_reason = e.error_payload.get('error', {}).get('message')
            self.stop_tracking_order(order_id)
            self.logger().network(
                f"Error submitting {trade_type.name} {order_type.name} order to {Constants.EXCHANGE_NAME} for "
                f"{amount} {trading_pair} {price} - {error_reason}.",
                exc_info=True,
                app_warning_msg=(f"Error submitting order to {Constants.EXCHANGE_NAME} - {error_reason}.")
            )
            self.trigger_event(MarketEvent.OrderFailure,
                               MarketOrderFailureEvent(self.current_timestamp, order_id, order_type))
    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 (aka 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}")
        ascend_ex_trading_rule = self._ascend_ex_trading_rules[trading_pair]

        amount = self.quantize_order_amount(trading_pair, amount)
        price = self.quantize_order_price(trading_pair, price)

        try:
            # ascend_ex has a unique way of determening if the order has enough "worth" to be posted
            # see https://ascendex.github.io/ascendex-pro-api/#place-order
            notional = Decimal(price * amount)
            if notional < ascend_ex_trading_rule.minNotional or notional > ascend_ex_trading_rule.maxNotional:
                raise ValueError(
                    f"Notional amount {notional} is not withing the range of {ascend_ex_trading_rule.minNotional}-{ascend_ex_trading_rule.maxNotional}."
                )

            # TODO: check balance
            [exchange_order_id, timestamp
             ] = ascend_ex_utils.gen_exchange_order_id(self._account_uid,
                                                       order_id)

            api_params = {
                "id":
                exchange_order_id,
                "time":
                timestamp,
                "symbol":
                ascend_ex_utils.convert_to_exchange_trading_pair(trading_pair),
                "orderPrice":
                f"{price:f}",
                "orderQty":
                f"{amount:f}",
                "orderType":
                "limit",
                "side":
                trade_type.name
            }

            self.start_tracking_order(order_id, exchange_order_id,
                                      trading_pair, trade_type, price, amount,
                                      order_type)

            await self._api_request("post",
                                    "cash/order",
                                    api_params,
                                    True,
                                    force_auth_path_url="order")
            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}.")

            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,
                            exchange_order_id=exchange_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 AscendEx 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))
    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 (aka 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}")
        amount = self.quantize_order_amount(trading_pair, amount)
        price = self.quantize_order_price(trading_pair, price)
        if amount <= s_decimal_0:
            raise ValueError("Order amount must be greater than zero.")
        try:
            timestamp = ascend_ex_utils.get_ms_timestamp()
            api_params = {
                "id":
                order_id,
                "time":
                timestamp,
                "symbol":
                ascend_ex_utils.convert_to_exchange_trading_pair(trading_pair),
                "orderPrice":
                f"{price:f}",
                "orderQty":
                f"{amount:f}",
                "orderType":
                "limit",
                "side":
                "buy" if trade_type == TradeType.BUY else "sell",
                "respInst":
                "ACCEPT",
            }
            self.start_tracking_order(order_id, None, trading_pair, trade_type,
                                      price, amount, order_type)
            resp = await self._api_request(method="post",
                                           path_url=CONSTANTS.ORDER_PATH_URL,
                                           data=api_params,
                                           is_auth_required=True,
                                           force_auth_path_url="order")
            exchange_order_id = str(resp["data"]["info"]["orderId"])
            tracked_order: AscendExInFlightOrder = self._in_flight_orders.get(
                order_id)
            tracked_order.update_exchange_order_id(exchange_order_id)
            if resp["data"]["status"] == "Ack":
                # Ack status means the server has received the request
                return
            tracked_order.update_status(resp["data"]["info"]["status"])
            if tracked_order.is_failure:
                raise Exception(
                    f'Failed to create an order, reason: {resp["data"]["info"]["errorCode"]}'
                )

            self.logger().info(
                f"Created {order_type.name} {trade_type.name} order {order_id} for "
                f"{amount} {trading_pair}.")
            self.trigger_order_created_event(tracked_order)
        except asyncio.CancelledError:
            raise
        except Exception:
            self.stop_tracking_order(order_id)
            msg = f"Error submitting {trade_type.name} {order_type.name} order to AscendEx for " \
                  f"{amount} {trading_pair} " \
                  f"{price}."
            self.logger().network(msg, exc_info=True, app_warning_msg=msg)
            self.trigger_event(
                MarketEvent.OrderFailure,
                MarketOrderFailureEvent(self.current_timestamp, order_id,
                                        order_type))
Esempio n. 7
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"Order amount {amount} is lower than the minimum order size "
                f"{trading_rule.min_order_size}.")

        api_params = {
            "tempid": order_id,
            "symbol": k2_utils.convert_to_exchange_trading_pair(trading_pair),
            "price": f"{price:f}",
            "quantity": f"{amount:f}",
            "type": trade_type.name.lower(
            ),  # `type` parameter here refers to Side i.e. Buy or Sell
        }

        self.start_tracking_order(order_id, None, trading_pair, trade_type,
                                  price, amount, order_type)
        try:
            order_result = await self._api_request(
                method="POST",
                path_url=constants.PLACE_ORDER,
                data=api_params,
                is_auth_required=True)
            exchange_order_id = str(order_result["data"]["orderids"][0]["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 K2 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))
Esempio n. 8
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)

        try:
            if amount < trading_rule.min_order_size:
                raise ValueError(f"{trade_type.name} order amount {amount} is lower than the minimum order size "
                                 f"{trading_rule.min_order_size}.")

            order_value: Decimal = amount * price
            if order_value < trading_rule.min_order_value:
                raise ValueError(f"{trade_type.name} order value {order_value} is lower than the minimum order value "
                                 f"{trading_rule.min_order_value}")

            body_params = {
                "market_id": trading_pair,
                "type": "limit",  # ProBit Order Types ["limit", "market"}
                "side": trade_type.name.lower(),  # ProBit Order Sides ["buy", "sell"]
                "time_in_force": "gtc",  # gtc = Good-Til-Cancelled
                "limit_price": str(price),
                "quantity": str(amount),
                "client_order_id": order_id
            }

            self.start_tracking_order(order_id,
                                      None,
                                      trading_pair,
                                      trade_type,
                                      price,
                                      amount,
                                      order_type
                                      )

            order_result = await self._api_request(
                method="POST",
                path_url=CONSTANTS.NEW_ORDER_URL,
                data=body_params,
                is_auth_required=True
            )
            exchange_order_id = str(order_result["data"]["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 ProBit 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))
Esempio n. 9
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:
            self.logger().warning(
                f"{trade_type.name.title()} order amount {amount} is lower than the minimum order size "
                f"{trading_rule.min_order_size}.")
        else:
            order_type_str = order_type.name.lower().split("_")[0]
            api_params = {
                "text": order_id,
                "currency_pair":
                convert_to_exchange_trading_pair(trading_pair),
                "side": trade_type.name.lower(),
                "type": order_type_str,
                "price": f"{price:f}",
                "amount": f"{amount:f}",
            }
            self.start_tracking_order(order_id, None, trading_pair, trade_type,
                                      price, amount, order_type)
            try:
                order_result = await self._api_request(
                    "POST", CONSTANTS.ORDER_CREATE_PATH_URL, api_params, True)
                if order_result.get('status') in {
                        "cancelled", "expired", "failed"
                }:
                    raise GateIoAPIError({
                        'label': 'ORDER_REJECTED',
                        'message': 'Order rejected.'
                    })
                else:
                    exchange_order_id = str(order_result["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)
                        if trade_type is TradeType.BUY:
                            event_tag = MarketEvent.BuyOrderCreated
                            event_cls = BuyOrderCreatedEvent
                        else:
                            event_tag = MarketEvent.SellOrderCreated
                            event_cls = SellOrderCreatedEvent
                        self.trigger_event(
                            event_tag,
                            event_cls(self.current_timestamp, order_type,
                                      trading_pair, amount, price, order_id,
                                      exchange_order_id))
            except asyncio.CancelledError:
                raise
            except GateIoAPIError as e:
                error_reason = e.error_message
                self.stop_tracking_order(order_id)
                self.logger().network(
                    f"Error submitting {trade_type.name} {order_type.name} order to {CONSTANTS.EXCHANGE_NAME} for "
                    f"{amount} {trading_pair} {price} - {error_reason}.",
                    exc_info=True,
                    app_warning_msg=
                    (f"Error submitting order to {CONSTANTS.EXCHANGE_NAME} - {error_reason}."
                     ))
                self.trigger_event(
                    MarketEvent.OrderFailure,
                    MarketOrderFailureEvent(self.current_timestamp, order_id,
                                            order_type))
Esempio n. 10
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 (aka 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}")
        amount = self.quantize_order_amount(trading_pair, amount)
        price = self.quantize_order_price(trading_pair, price)
        if amount <= s_decimal_0:
            raise ValueError("Order amount must be greater than zero.")
        try:
            timestamp = ascend_ex_utils.get_ms_timestamp()
            # Order UUID is strictly used to enable AscendEx to construct a unique(still questionable) exchange_order_id
            order_uuid = f"{ascend_ex_utils.HBOT_BROKER_ID}-{ascend_ex_utils.uuid32()}"[:32]
            api_params = {
                "id": order_uuid,
                "time": timestamp,
                "symbol": ascend_ex_utils.convert_to_exchange_trading_pair(trading_pair),
                "orderPrice": f"{price:f}",
                "orderQty": f"{amount:f}",
                "orderType": "limit",
                "side": "buy" if trade_type == TradeType.BUY else "sell",
                "respInst": "ACCEPT",
            }
            self.start_tracking_order(
                order_id=order_id,
                trading_pair=trading_pair,
                trade_type=trade_type,
                price=price,
                amount=amount,
                order_type=order_type,
            )

            try:
                resp = await self._api_request(
                    method="post",
                    path_url=CONSTANTS.ORDER_PATH_URL,
                    data=api_params,
                    is_auth_required=True,
                    force_auth_path_url="order",
                )

                resp_status = resp["data"]["status"].upper()

                order_data = resp["data"]["info"]
                if resp_status == "ACK":
                    # Ack request status means the server has received the request
                    return

                order_update = None
                if resp_status == "ACCEPT":
                    order_update: OrderUpdate = OrderUpdate(
                        client_order_id=order_id,
                        exchange_order_id=str(order_data["orderId"]),
                        trading_pair=trading_pair,
                        update_timestamp=order_data["lastExecTime"],
                        new_state=OrderState.OPEN,
                    )
                elif resp_status == "DONE":
                    order_update: OrderUpdate = OrderUpdate(
                        client_order_id=order_id,
                        exchange_order_id=str(order_data["orderId"]),
                        trading_pair=trading_pair,
                        update_timestamp=order_data["lastExecTime"],
                        new_state=CONSTANTS.ORDER_STATE[order_data["status"]],
                        fill_price=Decimal(order_data["avgPx"]),
                        executed_amount_base=Decimal(order_data["cumFilledQty"]),
                        executed_amount_quote=Decimal(order_data["avgPx"]) * Decimal(order_data["cumFilledQty"]),
                        fee_asset=order_data["feeAsset"],
                        cumulative_fee_paid=Decimal(order_data["cumFee"]),
                    )
                elif resp_status == "ERR":
                    order_update: OrderUpdate = OrderUpdate(
                        client_order_id=order_id,
                        exchange_order_id=str(order_data["orderId"]),
                        trading_pair=trading_pair,
                        update_timestamp=order_data["lastExecTime"],
                        new_state=OrderState.FAILED,
                    )
                self._in_flight_order_tracker.process_order_update(order_update)
            except IOError:
                self.logger().exception(f"The request to create the order {order_id} failed")
                self.stop_tracking_order(order_id)
        except asyncio.CancelledError:
            raise
        except Exception:
            msg = (f"Error submitting {trade_type.name} {order_type.name} order to AscendEx for "
                   f"{amount} {trading_pair} {price}.")
            self.logger().exception(msg)
Esempio n. 11
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 (aka 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}")
        amount = self.quantize_order_amount(trading_pair, amount)
        price = self.quantize_order_price(trading_pair, price)
        if amount <= s_decimal_0:
            raise ValueError("Order amount must be greater than zero.")
        try:
            # TODO: check balance
            [exchange_order_id, timestamp
             ] = ascend_ex_utils.gen_exchange_order_id(self._account_uid,
                                                       order_id)

            api_params = {
                "id":
                exchange_order_id,
                "time":
                timestamp,
                "symbol":
                ascend_ex_utils.convert_to_exchange_trading_pair(trading_pair),
                "orderPrice":
                f"{price:f}",
                "orderQty":
                f"{amount:f}",
                "orderType":
                "limit",
                "side":
                trade_type.name
            }

            self.start_tracking_order(order_id, exchange_order_id,
                                      trading_pair, trade_type, price, amount,
                                      order_type)

            await self._api_request(method="post",
                                    path_url="cash/order",
                                    params=api_params,
                                    is_auth_required=True,
                                    force_auth_path_url="order")
            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}.")

            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,
                            exchange_order_id=exchange_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 AscendEx 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))