def __str__(self): return 'orderSide ' + (OrderSideMapper.getDbValue(self.orderSide) if self.orderSide else str(None)) \ + ', orderType ' + (OrderTypeMapper.getDbValue(self.orderType) if self.orderType else str(None)) \ + ', qty ' + str(self.qty) \ + ', price ' + str(self.price) \ + ', stopPrice ' + str(self.stopPrice) \ + ', orderState ' + (OrderStateMapper.getDbValue(self.orderState) if self.orderState else str(None)) \ + ', orderId ' + str(self.orderId)
def setFromEntity(self, orderEntity): self.orderSide = OrderSideMapper.getCretenValue(orderEntity.order_side) self.orderType = OrderTypeMapper.getCretenValue(orderEntity.order_type) self.qty = orderEntity.qty self.price = orderEntity.price self.stopPrice = orderEntity.stop_price self.orderState = OrderStateMapper.getCretenValue( orderEntity.order_state) self.orderId = orderEntity.order_id self.tradeId = orderEntity.trade_id self.intOrderRef = orderEntity.int_order_ref self.initTmstmp = orderEntity.init_tmstmp self.openTmstmp = orderEntity.open_tmstmp self.filledTmstmp = orderEntity.filled_tmstmp
def _calcTradePerf(self, trade): orders = TradeManager.getAllOrders(tradeId = trade.trade_id, orderState = OrderStateMapper.getDbValue(OrderState.FILLED)) buyPrice = Decimal(0.0) sellPrice = Decimal(0.0) for order in orders: if order.order_side == OrderSideMapper.getDbValue(OrderSide.BUY): buyPrice += order.qty * Decimal(order.price) else: sellPrice += order.qty * Decimal(order.price) diff = sellPrice - buyPrice rules = self.marketRulesManager.getSymbolRules(trade.base_asset, trade.quote_asset) if diff < 0: color = Style.BRIGHT + Fore.LIGHTWHITE_EX + Back.RED else: color = Style.BRIGHT + Fore.LIGHTWHITE_EX + Back.GREEN self.log.info(color + 'Gain: ' + str(('{:.' + str(rules.quoteAssetPrecision) + 'f}').format(diff)) + Style.RESET_ALL)
def openOrder(self, trade, candle, orders): self.log.debug('Orders to be created: ' + str(len(orders))) # adjust quantity and price such that it meets market rules if self.shapeNewOrders: self._shapeOrders(candle.getBaseAsset(), candle.getQuoteAsset(), orders) # validate orders before sending them to the exchange if self.validateOrders: self._validateOrders(candle.getBaseAsset(), candle.getQuoteAsset(), orders) # make sure that limit orders are not executed immediately if self.preventImmediateLimitOrder: self._validateImmediateLimitOrder(candle, orders) for order in orders: try: dbOrder = Orders() dbOrder.trade_id = trade.trade_id dbOrder.qty = order.getQty() dbOrder.stop_price = order.getStopPrice() if order.getOrderType() == OrderType.MARKET: dbOrder.price = candle.getClose() else: dbOrder.price = order.getPrice() dbOrder.order_side = OrderSideMapper.getDbValue(order.getOrderSide()) dbOrder.order_type = OrderTypeMapper.getDbValue(order.getOrderType()) dbOrder.order_state = OrderStateMapper.getDbValue(OrderState.OPEN_PENDING_INT) dbOrder.init_tmstmp = candle.getCloseTime() self.storeOrder(dbOrder) # save the generated order id order.setOrderId(dbOrder.order_id) # save the order state (for print) order.setOrderState(OrderState.OPEN_PENDING_INT) self.log.info('Order: ' + str(order)) except: self.log.error('Could not create order ' + str(order)) raise
def processOrderUpdate(self, orderResponse): # update order in the database based on the update response order = TradeManager.getOrder(intOrderRef = orderResponse.getClientOrderId()) order.order_state = OrderStateMapper.getDbValue(orderResponse.getOrderState()) order.lst_upd_tmstmp = datetime.now() if orderResponse.getOrderState() == OrderState.OPENED: order.open_tmstmp = orderResponse.getOrderTmstmp() if orderResponse.getOrderState() == OrderState.FILLED: self.log.debug('Order ' + str(order.order_id) + ' FILLED.') order.filled_tmstmp = orderResponse.getOrderTmstmp() if orderResponse.getOrderState() == OrderState.CANCELED: self.log.debug('Order ' + str(order.order_id) + ' CANCELLED.') # update trade in the database based on the state of orders trade = TradeManager.getTrade(tradeId = order.trade_id) if trade.trade_type == TradeTypeMapper.getDbValue(TradeType.LONG): # open trade when first confirmed BUY is received if orderResponse.getOrderSide() == OrderSide.BUY and \ orderResponse.getOrderState() == OrderState.OPENED and \ trade.trade_state == TradeStateMapper.getDbValue(TradeState.OPEN_PENDING): trade.trade_state = TradeStateMapper.getDbValue(TradeState.OPENED) trade.open_tmstmp = orderResponse.getOrderTmstmp() # close trade when no pending order is left elif orderResponse.getOrderState() in [OrderState.CANCELED, OrderState.REJECTED, OrderState.EXPIRED]: openOrders = TradeManager.getPendOrders(trade.trade_id) if len(openOrders) == 0: self.closeTrade(trade, orderResponse.getOrderTmstmp()) # handle closing of the trade based on the defined strategy elif orderResponse.getOrderState() == OrderState.FILLED: tradeCloseType = self.strategyManager.getStrategy(trade.strategy_exec_id).getTradeCloseType() TradeCloseStrategy.evalTradeClose(tradeCloseType, trade, orderResponse, self) else: raise Exception('Short trades not supported!') self.storeOrder(order) self._storeTrade(trade)
def sendOrders(self, cretenExecDetlId): ordersToBeSent = TradeManager.getAllOrders(cretenExecDetlId = cretenExecDetlId, orderState = OrderStateMapper.getDbValue([OrderState.OPEN_PENDING_INT, OrderState.CANCEL_PENDING_INT])) for dbOrder in ordersToBeSent: if dbOrder.order_state == OrderStateMapper.getDbValue(OrderState.OPEN_PENDING_INT): try: order = Order() order.setFromEntity(dbOrder) self.log.debug('Processing order [' + str(order) + ']') trade = TradeManager.getTrade(tradeId = dbOrder.trade_id) rules = self.marketRulesManager.getSymbolRules(trade.base_asset, trade.quote_asset) qty = ('{:.' + str(rules.baseAssetPrecision) + 'f}').format(order.getQty()) price = ('{:.' + str(rules.quoteAssetPrecision) + 'f}').format(order.getPrice()) if order.getPrice() else None stopPrice = ('{:.' + str(rules.quoteAssetPrecision) + 'f}').format(order.getStopPrice()) if order.getStopPrice() else None self.log.debug('Values to be sent: qty [' + str(qty) + '], price [' + str(price) + '], stop price [' + str(stopPrice) + ']') response = self.exchangeClient.createOrder(order.getOrderSide(), order.getOrderType(), trade.base_asset, trade.quote_asset, qty, stopPrice, price, order.getIntOrderRef()) self.log.debug('Response: ' + str(response.getRawData())) if not response.getOrderState() in [OrderState.OPENED, OrderState.FILLED]: raise Exception('Unexpected response received for order [' + str(order) + ']! Expected state [' + str([OrderState.OPENED, OrderState.FILLED]) + '], received [' + str(response.getOrderState()) + ']') if order.getOrderType() == OrderType.MARKET: dbOrder.price = response.getPrice() dbOrder.ext_order_ref = response.getExtOrderRef() dbOrder.order_state = OrderStateMapper.getDbValue(OrderState.OPEN_PENDING_EXT) self.storeOrder(dbOrder) except: self.log.error('Error while creating orders!') dbOrder.order_state = OrderStateMapper.getDbValue(OrderState.OPEN_FAILED) self.storeOrder(dbOrder) raise elif dbOrder.order_state == OrderStateMapper.getDbValue(OrderState.CANCEL_PENDING_INT): try: order = Order() order.setFromEntity(dbOrder) self.log.debug('Cancelling order [' + str(order) + ']') trade = TradeManager.getTrade(tradeId = dbOrder.trade_id) response = self.exchangeClient.cancelOrder(baseAsset = trade.base_asset, quoteAsset = trade.quote_asset, clientOrderId = order.getIntOrderRef()) self.log.debug('Response: ' + str(response.getRawData())) if not response.getOrderState() in [OrderState.OPENED]: raise Exception('Unexpected response received for order [' + str(order) + ']! Expected state [' + str([OrderState.OPENED, OrderState.FILLED]) + '], received [' + str(response.getOrderState()) + ']') dbOrder.ext_order_ref = response.getExtOrderRef() dbOrder.order_state = OrderStateMapper.getDbValue(OrderState.CANCEL_PENDING_EXT) self.storeOrder(dbOrder) except: self.log.error('Error while cancelling orders!') dbOrder.order_state = OrderStateMapper.getDbValue(OrderState.CANCEL_FAILED) self.storeOrder(dbOrder) raise else: raise Exception('Creating orders for unsupporterd order state!')
def evalTradeClose(tradeCloseType, trade, orderResponse, orderManager): # ORDER DRIVEN closing strategy # close trade when: # - first SELL order is filled, or # - first STOP LOSS SELL order is filled if TradeCloseTypeMapper.getCretenValue( tradeCloseType) == TradeCloseType.ORDER_DRIVEN: if orderResponse.getOrderSide() == OrderSide.SELL and \ orderResponse.getOrderState() == OrderState.FILLED and \ orderResponse.getOrderType() in [OrderType.LIMIT, OrderType.MARKET, OrderType.TAKE_PROFIT_LIMIT, OrderType.TAKE_PROFIT_MARKET]: pendSellOrders = TradeManager.getAllOrders( tradeId=trade.trade_id, orderSide=OrderSideMapper.getDbValue(OrderSide.SELL), orderType=OrderTypeMapper.getDbValue([ OrderType.LIMIT, OrderType.MARKET, OrderType.TAKE_PROFIT_LIMIT, OrderType.TAKE_PROFIT_MARKET ]), orderState=OrderStateMapper.getDbValue( [OrderState.OPENED, OrderState.OPEN_PENDING_EXT])) if len(pendSellOrders) == 0: openOrders = TradeManager.getPendOrders(trade.trade_id) if len(openOrders) > 0: TradeCloseStrategy.log.debug('Trade ' + str(trade.trade_id) + ' CLOSING.') trade.trade_state = TradeStateMapper.getDbValue( TradeState.CLOSE_PENDING) for openOrder in openOrders: openOrder.order_state = OrderStateMapper.getDbValue( OrderState.CANCEL_PENDING_INT) orderManager.storeOrder(openOrder) else: orderManager.closeTrade(trade, orderResponse.getOrderTmstmp()) # start closing trade when first STOP_LOSS_SELL is filled elif orderResponse.getOrderSide() == OrderSide.SELL and \ orderResponse.getOrderState() == OrderState.FILLED and \ orderResponse.getOrderType() in [OrderType.STOP_LOSS_LIMIT, OrderType.STOP_LOSS_MARKET]: openOrders = TradeManager.getPendOrders(trade.trade_id) if len(openOrders) > 0: TradeCloseStrategy.log.debug('Trade ' + str(trade.trade_id) + ' CLOSING.') trade.trade_state = TradeStateMapper.getDbValue( TradeState.CLOSE_PENDING) for openOrder in openOrders: openOrder.order_state = OrderStateMapper.getDbValue( OrderState.CANCEL_PENDING_INT) orderManager.storeOrder(openOrder) else: orderManager.closeTrade(trade, orderResponse.getOrderTmstmp()) # QUANTITY DRIVEN closing strategy # close trade when: # - sum of bought and sold quantities nets elif TradeCloseTypeMapper.getCretenValue( tradeCloseType) == TradeCloseType.QUANTITY_DRIVEN: TradeCloseStrategy.log.debug( 'Evaluate quantity driven trade close condition...') filledOrders = TradeManager.getAllOrders( tradeId=trade.trade_id, orderState=OrderStateMapper.getDbValue([OrderState.FILLED])) qty = Decimal(0) for o in filledOrders: TradeCloseStrategy.log.debug( str(o.order_side) + ' ' + str(o.qty)) if o.order_side == OrderSideMapper.getDbValue(OrderSide.BUY): qty += o.qty else: qty -= o.qty TradeCloseStrategy.log.debug('Remaining quantity [' + ('{:.' + str(10) + 'f}').format(qty) + ']') if qty == 0: openOrders = TradeManager.getPendOrders(trade.trade_id) if len(openOrders) > 0: TradeCloseStrategy.log.debug('Trade ' + str(trade.trade_id) + ' CLOSING.') trade.trade_state = TradeStateMapper.getDbValue( TradeState.CLOSE_PENDING) for openOrder in openOrders: openOrder.order_state = OrderStateMapper.getDbValue( OrderState.CANCEL_PENDING_INT) orderManager.storeOrder(openOrder) else: orderManager.closeTrade(trade, orderResponse.getOrderTmstmp()) else: raise Exception("Unrecognized trade close type [" + tradeCloseType + "]!")