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 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 __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 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)
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'])))