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