Пример #1
0
    def commitOrderExecution(self, order, dateTime, fillInfo):
        price = fillInfo.getPrice()
        quantity = fillInfo.getQuantity()

        if order.isBuy():
            cost = price * quantity * -1
            assert (cost < 0)
            sharesDelta = quantity
        elif order.isSell():
            cost = price * quantity
            assert (cost > 0)
            sharesDelta = quantity * -1
        else:  # Unknown action
            assert (False)

        commission = self.getCommission().calculate(order, price, quantity)
        cost -= commission
        resultingCash = self.getCash() + cost

        # Check that we're ok on cash after the commission.
        if resultingCash >= 0 or self.__allowNegativeCash:

            # Update the order before updating internal state since addExecutionInfo may raise.
            # addExecutionInfo should switch the order state.
            orderExecutionInfo = broker.OrderExecutionInfo(
                price, quantity, commission, dateTime)
            order.addExecutionInfo(orderExecutionInfo)

            # Commit the order execution.
            self.__cash = resultingCash
            updatedShares = order.getInstrumentTraits().roundQuantity(
                self.getShares(order.getInstrument()) + sharesDelta)
            if updatedShares == 0:
                del self.__shares[order.getInstrument()]
            else:
                self.__shares[order.getInstrument()] = updatedShares

            # Let the strategy know that the order was filled.
            self.__fillStrategy.onOrderFilled(self, order)

            # Notify the order update
            if order.isFilled():
                self._unregisterOrder(order)
                self.notifyOrderEvent(
                    broker.OrderEvent(order, broker.OrderEvent.Type.FILLED,
                                      orderExecutionInfo))
            elif order.isPartiallyFilled():
                self.notifyOrderEvent(
                    broker.OrderEvent(order,
                                      broker.OrderEvent.Type.PARTIALLY_FILLED,
                                      orderExecutionInfo))
            else:
                assert (False)
        else:
            self.__logger.debug(
                "Not enough cash to fill %s order [%s] for %s share/s" %
                (order.getInstrument(), order.getId(), order.getRemaining()))
Пример #2
0
    def _onUserTrades(self, trades):
        for trade in trades:
            order = self.__activeOrders.get(trade.getOrderId())
            if order is not None:
                fee = trade.getFee()
                fillPrice = trade.getBTCUSD()
                btcAmount = trade.getBTC()
                dateTime = trade.getDateTime()

                # Update cash and shares.
                self.refreshAccountBalance()
                # Update the order.
                orderExecutionInfo = broker.OrderExecutionInfo(
                    fillPrice, abs(btcAmount), fee, dateTime)
                order.addExecutionInfo(orderExecutionInfo)
                if not order.isActive():
                    self._unregisterOrder(order)
                # Notify that the order was updated.
                if order.isFilled():
                    eventType = broker.OrderEvent.Type.FILLED
                else:
                    eventType = broker.OrderEvent.Type.PARTIALLY_FILLED
                self.notifyOrderEvent(
                    broker.OrderEvent(order, eventType, orderExecutionInfo))
            else:
                common.logger.info(
                    "Trade %d refered to order %d that is not active" %
                    (trade.getId(), trade.getOrderId()))
Пример #3
0
    def cancelOrder(self, order):
        activeOrder = self.__activeOrders.get(order.getId())
        if activeOrder is None:
            raise Exception("The order is not active anymore")
        if activeOrder.isFilled():
            raise Exception("Can't cancel order that has already been filled")

        self._unregisterOrder(activeOrder)
        activeOrder.switchState(broker.Order.State.CANCELED)
        self.notifyOrderEvent(
            broker.OrderEvent(activeOrder, broker.OrderEvent.Type.CANCELED,
                              "User requested cancellation"))
Пример #4
0
 def submitOrder(self, order):
     if order.isInitial():
         order.setSubmitted(self._getNextOrderId(),
                            self._getCurrentDateTime())
         self._registerOrder(order)
         # Switch from INITIAL -> SUBMITTED
         order.switchState(broker.Order.State.SUBMITTED)
         self.notifyOrderEvent(
             broker.OrderEvent(order, broker.OrderEvent.Type.SUBMITTED,
                               None))
     else:
         raise Exception("The order was already processed")
Пример #5
0
    def _onOrderAction(self, msg_dict):
        order = self.__activeOrders.get(msg_dict['order_id'])
        if msg_dict['action'] == 'canceled':
            self._unregisterOrder(order)
            order.switchState(broker.Order.State.CANCELED)

            # Notify that the order was canceled.
            self.notifyOrderEvent(
                broker.OrderEvent(order, broker.OrderEvent.Type.CANCELED,
                                  "User requested cancellation"))

            # Update cash and shares.
            self.__api.qryAccount()

            # Update position.
            self.__api.qryPosition()
Пример #6
0
    def __postProcessOrder(self, order, bar_):
        # For non-GTC orders and daily (or greater) bars we need to check if orders should expire right now
        # before waiting for the next bar.
        if not order.getGoodTillCanceled():
            expired = False
            if self.__barFeed.getFrequency() >= engine.bar.Frequency.DAY:
                expired = bar_.getDateTime().date(
                ) >= order.getAcceptedDateTime().date()

            # Cancel the order if it will expire in the next bar.
            if expired:
                self._unregisterOrder(order)
                order.switchState(broker.Order.State.CANCELED)
                self.notifyOrderEvent(
                    broker.OrderEvent(order, broker.OrderEvent.Type.CANCELED,
                                      "Expired"))
Пример #7
0
    def __preProcessOrder(self, order, bar_):
        ret = True

        # For non-GTC orders we need to check if the order has expired.
        if not order.getGoodTillCanceled():
            expired = bar_.getDateTime().date() > order.getAcceptedDateTime(
            ).date()

            # Cancel the order if it is expired.
            if expired:
                ret = False
                self._unregisterOrder(order)
                order.switchState(broker.Order.State.CANCELED)
                self.notifyOrderEvent(
                    broker.OrderEvent(order, broker.OrderEvent.Type.CANCELED,
                                      "Expired"))

        return ret
Пример #8
0
    def cancelOrder(self, order):
        activeOrder = self.__activeOrders.get(order.getId())
        if activeOrder is None:
            raise Exception("The order is not active anymore")
        if activeOrder.isFilled():
            raise Exception("Can't cancel order that has already been filled")

        self.__httpClient.cancelOrder(order.getId())
        self._unregisterOrder(order)
        order.switchState(broker.Order.State.CANCELED)

        # Update cash and shares.
        self.refreshAccountBalance()

        # Notify that the order was canceled.
        self.notifyOrderEvent(
            broker.OrderEvent(order, broker.OrderEvent.Type.CANCELED,
                              "User requested cancellation"))
Пример #9
0
    def __onBarsImpl(self, order, bars):
        # IF WE'RE DEALING WITH MULTIPLE INSTRUMENTS WE SKIP ORDER PROCESSING IF THERE IS NO BAR FOR THE ORDER'S
        # INSTRUMENT TO GET THE SAME BEHAVIOUR AS IF WERE BE PROCESSING ONLY ONE INSTRUMENT.
        bar_ = bars.getBar(order.getInstrument())
        if bar_ is not None:
            # Switch from SUBMITTED -> ACCEPTED
            if order.isSubmitted():
                order.setAcceptedDateTime(bar_.getDateTime())
                order.switchState(broker.Order.State.ACCEPTED)
                self.notifyOrderEvent(
                    broker.OrderEvent(order, broker.OrderEvent.Type.ACCEPTED,
                                      None))

            if order.isActive():
                # This may trigger orders to be added/removed from __activeOrders.
                self.__processOrder(order, bar_)
            else:
                # If an order is not active it should be because it was canceled in this same loop and it should
                # have been removed.
                assert (order.isCanceled())
                assert (order not in self.__activeOrders)
Пример #10
0
    def _onUserTrades(self, msg_dict):
        print "_onUserTrades"
        order = self.__activeOrders.get(msg_dict['order_id'])
        if order is not None:
            commision = self.getInstrumentTraits().getCommission(
                msg_dict['instrument_id'])
            fill_price = msg_dict['price']
            volume = msg_dict['volume']
            datetime = msg_dict['datetime']

            # Update the order.
            orderExecutionInfo = broker.OrderExecutionInfo(
                fill_price, abs(volume), commision, datetime)
            order.addExecutionInfo(orderExecutionInfo)
            if not order.isActive():
                self._unregisterOrder(order)
            # Notify that the order was updated.
            if order.isFilled():
                eventType = broker.OrderEvent.Type.FILLED
            else:
                eventType = broker.OrderEvent.Type.PARTIALLY_FILLED
            self.notifyOrderEvent(
                broker.OrderEvent(order, eventType, orderExecutionInfo))

            print msg_dict
            self.__TradeDetailDB.update(
                {'strategy_id': find_strategy(get_task_id())},
                msg_dict,
                upsert=True)

            # Update cash and shares.
            self.__api.qryAccount()

            # Update position.
            self.__api.qryPosition()

        else:
            logger.info("Trade %d refered to order %d that is not active" %
                        (int(msg_dict['trade_id']), int(msg_dict['order_id'])))
Пример #11
0
    def dispatch(self):
        # Switch orders from SUBMITTED to ACCEPTED.
        ordersToProcess = self.__activeOrders.values()
        for order in ordersToProcess:
            if order.isSubmitted():
                order.switchState(broker.Order.State.ACCEPTED)
                self.notifyOrderEvent(
                    broker.OrderEvent(order, broker.OrderEvent.Type.ACCEPTED,
                                      None))

        # Dispatch events from the trade monitor.
        try:
            eventType, eventData = self.__tradeMonitor.getQueue().get(
                True, LiveBroker.QUEUE_TIMEOUT)

            if eventType == TradeMonitor.ON_USER_TRADE:
                self._onUserTrades(eventData)
            else:
                common.logger.error(
                    "Invalid event received to dispatch: %s - %s" %
                    (eventType, eventData))
        except Queue.Empty:
            pass
Пример #12
0
    def dispatch(self):
        # Switch orders from SUBMITTED to ACCEPTED.
        ordersToProcess = self.__activeOrders.values()
        for order in ordersToProcess:
            if order.isSubmitted():
                order.switchState(broker.Order.State.ACCEPTED)
                self.notifyOrderEvent(
                    broker.OrderEvent(order, broker.OrderEvent.Type.ACCEPTED,
                                      None))

        # Dispatch events from the trade monitor.
        while self.__msg_queue.qsize() > 0:
            msg = self.__msg_queue.get(True, LiveBroker.QUEUE_TIMEOUT)

            if msg['event_type'] == CTPTdApi.EventType.ON_TRADE:
                self._onUserTrades(msg)
            elif msg['event_type'] == CTPTdApi.EventType.ON_QUERY_ACCOUNT:
                self.refreshAccountBalance(msg)
            elif msg['event_type'] == CTPTdApi.EventType.ON_ORDER_ACTION:
                self._onOrderAction(msg)
            elif msg['event_type'] == CTPTdApi.EventType.ON_QUERY_POSITION:
                self.refreshStrategInfo(msg)
            else:
                pass