Exemplo n.º 1
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()))
Exemplo n.º 2
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")
Exemplo n.º 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"))
Exemplo n.º 4
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() >= mooquant.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"))
Exemplo n.º 5
0
    def _onUserTrades(self, trades):
        ret = False
        for trade in trades:
            order = self.__activeOrders.get(trade.getOrderId())
            if order is not None:
                filled = order.getFilled()
                avgPrice = order.getAvgFillPrice()
                newQuantity = trade.getBTC() - filled
                if order.isBuy():
                    newQuantity -= trade.getFee()
                newQuantity = liveUtils.CoinRound(newQuantity)
                if newQuantity == 0:
                    continue
                ret = True
                newFillPrice = trade.getBTCUSD()
                if avgPrice is not None:
                    newFillPrice = (newFillPrice * trade.getBTC() -
                                    order.getFilled() * avgPrice) / newQuantity
                newFee = trade.getFee() - order.getCommissions()
                newDateTime = trade.getDateTime()

                logger.info('newTrade: price:%f btc:%f fee:%s time:%s' %
                            (newFillPrice, newQuantity, newFee, newDateTime))

                # Update cash and shares.
                self.refreshAccountBalance()
                # Update the order.
                orderExecutionInfo = broker.OrderExecutionInfo(
                    newFillPrice, abs(newQuantity), newFee, newDateTime)
                order.addExecutionInfo(orderExecutionInfo)
                if trade.isFilled():
                    order.setState(order.State.FILLED)
#                order.updateExecutionInfo(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:
                logger.info("Trade refered to order %d that is not active" %
                            (trade.getOrderId()))
        return ret
Exemplo n.º 6
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
Exemplo n.º 7
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"))
Exemplo n.º 8
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)
Exemplo n.º 9
0
    def dispatch(self):
        # Switch orders from SUBMITTED to ACCEPTED.
        ordersToProcess = list(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:
                return self._onUserTrades(eventData)
            else:
                logger.error("Invalid event received to dispatch: %s - %s" %
                             (eventType, eventData))
        except queue.Empty:
            pass
Exemplo n.º 10
0
    def commitOrderExecution(self, order, dateTime, fillInfo):
        """Tries to commit an order execution. """

        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()))