示例#1
0
    def testPartialFill(self):
        order = self.__buildAcceptedLimitOrder(broker.Order.Action.BUY, 2, 11)
        self.assertEqual(order.getRemaining(), 11)
        self.assertEqual(order.getFilled(), 0)
        self.assertEqual(order.getAvgFillPrice(), None)
        self.assertEqual(order.getExecutionInfo(), None)

        order.addExecutionInfo(broker.OrderExecutionInfo(1, 8, 0, datetime.datetime.now()))
        self.assertTrue(order.isPartiallyFilled())
        self.assertEqual(order.getRemaining(), 3)
        self.assertEqual(order.getFilled(), 8)
        self.assertEqual(order.getAvgFillPrice(), 1)
        self.assertEqual(order.getExecutionInfo().getQuantity(), 8)
        self.assertEqual(order.getExecutionInfo().getPrice(), 1)

        order.addExecutionInfo(broker.OrderExecutionInfo(1.5, 1, 0, datetime.datetime.now()))
        self.assertTrue(order.isPartiallyFilled())
        self.assertEqual(order.getRemaining(), 2)
        self.assertEqual(order.getFilled(), 9)
        self.assertEqual(round(order.getAvgFillPrice(), 4), round(1.055555556, 4))
        self.assertEqual(order.getExecutionInfo().getQuantity(), 1)
        self.assertEqual(order.getExecutionInfo().getPrice(), 1.5)

        order.addExecutionInfo(broker.OrderExecutionInfo(1.123, 2, 0, datetime.datetime.now()))
        self.assertTrue(order.isFilled())
        self.assertEqual(order.getRemaining(), 0)
        self.assertEqual(order.getFilled(), 11)
        self.assertEqual(round(order.getAvgFillPrice(), 4), round(1.067818182, 4))
        self.assertEqual(order.getExecutionInfo().getQuantity(), 2)
        self.assertEqual(order.getExecutionInfo().getPrice(), 1.123)
示例#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 commitOrderExecution(self, order, price, quantity, dateTime):
		if order.getAction() in [broker.Order.Action.BUY, broker.Order.Action.BUY_TO_COVER]:
			cost = price * quantity * -1
			assert(cost < 0)
			sharesDelta = quantity
		elif order.getAction() in [broker.Order.Action.SELL, broker.Order.Action.SELL_SHORT]:
			cost = price * quantity
			assert(cost > 0)
			sharesDelta = quantity * -1
		else: # Unknown action
			assert(False)

		ret = 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:
			# Commit the order execution.
			self.setCash(resultingCash)
			self.__shares[order.getInstrument()] = self.getShares(order.getInstrument()) + sharesDelta
			ret = True

			# Update the order.
			orderExecutionInfo = broker.OrderExecutionInfo(price, quantity, commission, dateTime)
			order.setExecuted(orderExecutionInfo)

		return ret
示例#4
0
    def commitOrderExecution(self, order, dateTime, fillInfo):
        if order.getId() is not None:
            self.__logger.debug('commitOrderExecution, order[%d] = %s' %
                                (order.getId(), str(order)))
        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()))
示例#5
0
 def _onUserTrades(self, msg_dict):
     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))
         
         self.__mongo.tradedb.trades.insert_one(msg_dict)
         
         # Update cash and shares.
         self.__api.qryAccount()
     else:
         logger.info("Trade %d refered to order %d that is not active" % (int(msg_dict['trade_id']), int(msg_dict['order_id'])))
 def __getFilledMarketOrder(self, quantity, price):
     order = backtesting.MarketOrder(broker.Order.Action.BUY,
                                     BaseTestCase.TestInstrument, quantity,
                                     False, broker.IntegerTraits())
     order.setState(broker.Order.State.ACCEPTED)
     order.addExecutionInfo(
         broker.OrderExecutionInfo(price, quantity, 0,
                                   datetime.datetime.now()))
     return order
示例#7
0
 def testCompleteFillInvalidSize(self):
     order = self.__buildAcceptedLimitOrder(broker.Order.Action.BUY, 1, 1)
     with self.assertRaises(Exception):
         order.addExecutionInfo(broker.OrderExecutionInfo(1, 1.001, 0, datetime.datetime.now()))
     self.assertTrue(order.isAccepted())
     self.assertEqual(order.getRemaining(), 1)
     self.assertEqual(order.getFilled(), 0)
     self.assertEqual(order.getAvgFillPrice(), None)
     self.assertEqual(order.getExecutionInfo(), None)
示例#8
0
    def commitOrderExecution(self, order, dateTime, fillInfo):
        instrument = order.getInstrument()
        instrumentSymbol = instrument.symbol
        priceCurrency = instrument.priceCurrency

        # Calculate deltas.
        price = fillInfo.getPrice()
        quantity = fillInfo.getQuantity()
        if order.isBuy():
            cost = price * quantity * -1
            assert (cost < 0)
            baseDelta = quantity
        else:
            assert order.isSell()
            cost = price * quantity
            assert (cost > 0)
            baseDelta = quantity * -1

        # Update the cost with the commission.
        commission = self.getCommission().calculate(order, price, quantity)
        cost -= commission

        baseBalanceFinal = self.getInstrumentTraits().round(
            self.getBalance(instrumentSymbol) + baseDelta, instrumentSymbol)
        quoteBalanceFinal = self.getInstrumentTraits().round(
            self.getBalance(priceCurrency) + cost, priceCurrency)

        if quoteBalanceFinal >= 0:
            # 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._balances[priceCurrency] = quoteBalanceFinal
            self._balances[instrumentSymbol] = baseBalanceFinal

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

            # Notify the order update
            if order.isFilled():
                self._unregisterOrder(order)
                eventType = broker.OrderEvent.Type.FILLED
            else:
                assert order.isPartiallyFilled(
                ), "Order was neither filled completely nor partially"
                eventType = broker.OrderEvent.Type.PARTIALLY_FILLED
            self.notifyOrderEvent(
                broker.OrderEvent(order, eventType, orderExecutionInfo))
        else:
            action = "buy" if order.isBuy() else "sell"
            self._logger.debug("Not enough %s to %s %s %s [order %s]" %
                               (priceCurrency, action, order.getQuantity(),
                                instrumentSymbol, order.getId()))
 def __getFilledMarketOrder(self, quantity, price):
     order = backtesting.MarketOrder(
         broker.Order.Action.BUY,
         INSTRUMENT,
         quantity,
         False,
         backtesting.DefaultInstrumentTraits()
     )
     order.setState(broker.Order.State.ACCEPTED)
     order.addExecutionInfo(broker.OrderExecutionInfo(price, quantity, 0, datetime.datetime.now()))
     return order
示例#10
0
    def testCompleteFill(self):
        order = self.__buildAcceptedLimitOrder(broker.Order.Action.BUY, 1, 1)
        self.assertEqual(order.getRemaining(), 1)
        self.assertEqual(order.getFilled(), 0)
        self.assertEqual(order.getAvgFillPrice(), None)
        self.assertEqual(order.getExecutionInfo(), None)

        order.addExecutionInfo(broker.OrderExecutionInfo(0.9, 1, 0, datetime.datetime.now()))
        self.assertTrue(order.isFilled())
        self.assertEqual(order.getRemaining(), 0)
        self.assertEqual(order.getFilled(), 1)
        self.assertEqual(order.getAvgFillPrice(), 0.9)
示例#11
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
            self.__shares[order.getInstrument()] = self.getShares(
                order.getInstrument()) + sharesDelta

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

            # Notify the order update
            if order.isFilled():
                del self.__activeOrders[order.getId()]
                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 money to fill order %s" % (order))
示例#12
0
    def __orderStatusHandler(self, msg):
        order = self.__activeOrders.get(msg.orderId)
        if order == None:
            return

        #watch out for dupes - don't submit state changes or events if they were already submitted

        eventType = None
        if msg.status == 'Filled' and order.getState(
        ) != broker.Order.State.FILLED:
            eventType = broker.OrderEvent.Type.FILLED
            self._unregisterOrder(order)
            #order.setState(broker.Order.State.FILLED)
        if msg.status == 'Submitted' and msg.filled > 0:
            eventType = broker.OrderEvent.Type.PARTIALLY_FILLED
            #may already be partially filled
            #if order.getState() != broker.Order.State.PARTIALLY_FILLED:
            #    order.setState(broker.Order.State.PARTIALLY_FILLED)
        if msg.status == 'Cancelled' and order.getState(
        ) != broker.Order.State.CANCELED:
            #self._unregisterOrder(order)
            eventType = broker.OrderEvent.Type.CANCELED
            #order.setState(broker.Order.State.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"))

        orderExecutionInfo = None
        if eventType == broker.OrderEvent.Type.FILLED or eventType == broker.OrderEvent.Type.PARTIALLY_FILLED:
            orderExecutionInfo = broker.OrderExecutionInfo(
                msg.avgFillPrice, abs(msg.filled), 0, datetime.datetime.now())

            order.addExecutionInfo(orderExecutionInfo)

            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))
示例#13
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
示例#14
0
    def _order_filled(self, trade, order):
        fee = trade.get_fee()
        # 获取成交价
        fillPrice = float(trade.get_avg_price())
        # 获取成交量
        btcAmount = float(trade.get_amount_original())
        # 获取交易时间
        dateTime = trade.get_datetime()

        exe_info = broker.OrderExecutionInfo(fillPrice, abs(btcAmount), fee,
                                             dateTime)
        order.addExecutionInfo(exe_info)
        if order.isFilled():
            eventType = broker.OrderEvent.Type.FILLED
        else:
            eventType = broker.OrderEvent.Type.PARTIALLY_FILLED
        if not order.isActive():
            self._unregisterOrder(order)
        self.notifyOrderEvent(broker.OrderEvent(order, eventType, exe_info))
示例#15
0
    def onExecution(self, data):
        order = self.__activeOrders.get(data.getId())
        if order is not None:
            self.onOrder(data)
            if order.isSubmitted():
                try:
                    order.switchState(broker.Order.State.ACCEPTED)
                    self.notifyOrderEvent(
                        broker.OrderEvent(order,
                                          broker.OrderEvent.Type.ACCEPTED,
                                          None))
                except Exception as e:
                    common.logger.info('onExecution accept: ' + str(e))

            fee = 0
            fillPrice = data.getPrice()
            btcAmount = data.getFilledQty()
            dateTime = data.getDateTime()
            old_state = order.getState()

            # Update the order.
            if btcAmount > 0 and (
                    order.getExecutionInfo() is None or order.getExecutionInfo().getDateTime() != dateTime) and 'Trade' in \
                    data.getData().get('execType', 'Trade'):
                self.updateCash(order, fillPrice, btcAmount)
                orderExecutionInfo = broker.OrderExecutionInfo(
                    fillPrice, btcAmount, fee, dateTime)
                order.addExecutionInfo(orderExecutionInfo)

            if data.getData()['ordStatus'] == 'New' and data.getFilledQty(
            ) == 0:
                new_state = broker.Order.State.ACCEPTED
                orderExecutionInfo = "New"
            elif order.isFilled():
                new_state = broker.Order.State.FILLED
            elif order.getFilled() != 0:
                new_state = broker.Order.State.PARTIALLY_FILLED
            elif data.getData()['ordStatus'] in ['Canceled', 'Rejected'
                                                 ] and order.getFilled() == 0:
                new_state = broker.Order.State.CANCELED
                orderExecutionInfo = data.getData()['text']
            else:
                common.logger.error('onExecution', data.getData()['ordStatus'])

            try:
                if new_state != order.getState():
                    order.switchState(new_state)
            except Exception as e:
                common.logger.info('onExecution switchstate: ' + str(e))
            if old_state != order.getState():
                try:
                    self.notifyOrderEvent(
                        broker.OrderEvent(order, new_state - 1,
                                          orderExecutionInfo))
                except Exception as e:
                    common.logger.error('onExecution notifyOrderEvent: ' +
                                        str(e))
                    self.notifyOrderEvent(
                        broker.OrderEvent(order, new_state - 1,
                                          orderExecutionInfo))
            if not order.isActive() and order.getId() in self.__activeOrders:
                self._unregisterOrder(order)