def restore_tracking_states(self, saved_states: Dict[str, any]):
     """
     Restore in-flight orders from saved tracking states, this is st the connector can pick up on where it left off
     when it disconnects.
     :param saved_states: The saved tracking_states.
     """
     self._in_flight_orders.update({
         key: AscendExInFlightOrder.from_json(value)
         for key, value in saved_states.items()
     })
 def start_tracking_order(self, order_id: str, exchange_order_id: str,
                          trading_pair: str, trade_type: TradeType,
                          price: Decimal, amount: Decimal,
                          order_type: OrderType):
     """
     Starts tracking an order by simply adding it into _in_flight_orders dictionary.
     """
     self._in_flight_orders[order_id] = AscendExInFlightOrder(
         client_order_id=order_id,
         exchange_order_id=exchange_order_id,
         trading_pair=trading_pair,
         order_type=order_type,
         trade_type=trade_type,
         price=price,
         amount=amount)
Esempio n. 3
0
    def test_open_status(self):
        order = AscendExInFlightOrder(client_order_id="1",
                                      exchange_order_id="2",
                                      trading_pair="BTC-USDT",
                                      order_type=OrderType.LIMIT,
                                      trade_type=TradeType.BUY,
                                      price=Decimal("40000"),
                                      amount=Decimal("1"),
                                      initial_state="NewLocal")

        self.assertFalse(order.is_open)

        order.update_status("New")
        self.assertTrue(order.is_open)
        order.update_status("PendingNew")
        self.assertTrue(order.is_open)
        order.update_status("PartiallyFilled")
        self.assertTrue(order.is_open)

        order.update_status("Filled")
        self.assertFalse(order.is_open)
        order.update_status("Rejected")
        self.assertFalse(order.is_open)
        order.update_status("Canceled")
        self.assertFalse(order.is_open)
    def _process_order_message(self, order_msg: AscendExOrder):
        """
        Updates in-flight order and triggers cancellation or failure event if needed.
        :param order_msg: The order response from either REST or web socket API (they are of the same format)
        """
        exchange_order_id = order_msg.orderId
        client_order_id = None

        for in_flight_order in self._in_flight_orders.values():
            if in_flight_order.exchange_order_id == exchange_order_id:
                client_order_id = in_flight_order.client_order_id

        if client_order_id is None:
            return

        tracked_order: AscendExInFlightOrder = self._in_flight_orders[
            client_order_id]
        # This could happen for Ack request type when placing new order, we don't know if the order is open until
        # we get order status update
        if tracked_order.is_locally_new and AscendExInFlightOrder.is_open_status(
                order_msg.status):
            self.trigger_order_created_event(tracked_order)
        tracked_order.update_status(order_msg.status)

        if tracked_order.executed_amount_base != Decimal(
                order_msg.cumFilledQty):
            # Update the relevant order information when there is fill event
            new_filled_amount = Decimal(
                order_msg.cumFilledQty) - tracked_order.executed_amount_base
            new_fee_paid = Decimal(order_msg.cumFee) - tracked_order.fee_paid

            tracked_order.executed_amount_base = Decimal(
                order_msg.cumFilledQty)
            tracked_order.executed_amount_quote = Decimal(
                order_msg.avgPx) * tracked_order.executed_amount_base
            tracked_order.fee_paid = Decimal(order_msg.cumFee)
            tracked_order.fee_asset = order_msg.feeAsset

            self.trigger_event(
                MarketEvent.OrderFilled,
                OrderFilledEvent(
                    self.current_timestamp, client_order_id,
                    tracked_order.trading_pair,
                    tracked_order.trade_type, tracked_order.order_type,
                    Decimal(order_msg.avgPx), new_filled_amount,
                    TradeFee(0.0, [(tracked_order.fee_asset, new_fee_paid)]),
                    exchange_order_id))

        if tracked_order.is_cancelled:
            self.logger().info(
                f"Successfully cancelled order {client_order_id}.")
            self.trigger_event(
                MarketEvent.OrderCancelled,
                OrderCancelledEvent(self.current_timestamp, client_order_id,
                                    exchange_order_id))
            tracked_order.cancelled_event.set()
            self.stop_tracking_order(client_order_id)
        elif tracked_order.is_failure:
            self.logger().info(
                f"Order {client_order_id} has failed according to order status API. "
                f"API order response: {order_msg}")
            self.trigger_event(
                MarketEvent.OrderFailure,
                MarketOrderFailureEvent(self.current_timestamp,
                                        client_order_id,
                                        tracked_order.order_type))
            self.stop_tracking_order(client_order_id)
        elif tracked_order.is_filled:
            event_tag = MarketEvent.BuyOrderCompleted if tracked_order.trade_type is TradeType.BUY else MarketEvent.SellOrderCompleted
            event_class = BuyOrderCompletedEvent if tracked_order.trade_type is TradeType.BUY else SellOrderCompletedEvent
            self.trigger_event(
                event_tag,
                event_class(self.current_timestamp, client_order_id,
                            tracked_order.base_asset,
                            tracked_order.quote_asset, tracked_order.fee_asset,
                            tracked_order.executed_amount_base,
                            tracked_order.executed_amount_quote,
                            tracked_order.fee_paid, tracked_order.order_type,
                            exchange_order_id))
            self.stop_tracking_order(client_order_id)