def tickerListener(tick): # logging.info('tickerLister: new tick received for %s = %f', tick.tradingSymbol, tick.lastTradedPrice); TradeManager.symbolToCMPMap[ tick. tradingSymbol] = tick.lastTradedPrice # Store the latest tick in map # On each new tick, get a created trade and call its strategy whether to place trade or not for strategy in TradeManager.strategyToInstanceMap: longTrade = TradeManager.getUntriggeredTrade( tick.tradingSymbol, strategy, Direction.LONG) shortTrade = TradeManager.getUntriggeredTrade( tick.tradingSymbol, strategy, Direction.SHORT) if longTrade == None and shortTrade == None: continue strategyInstance = TradeManager.strategyToInstanceMap[strategy] if longTrade != None: if strategyInstance.shouldPlaceTrade(longTrade, tick): # place the longTrade isSuccess = TradeManager.executeTrade(longTrade) if isSuccess == True: # set longTrade state to ACTIVE longTrade.tradeState = TradeState.ACTIVE longTrade.startTimestamp = Utils.getEpoch() continue if shortTrade != None: if strategyInstance.shouldPlaceTrade(shortTrade, tick): # place the shortTrade isSuccess = TradeManager.executeTrade(shortTrade) if isSuccess == True: # set shortTrade state to ACTIVE shortTrade.tradeState = TradeState.ACTIVE shortTrade.startTimestamp = Utils.getEpoch()
def generateTrade(self, tradingSymbol, direction, high, low): trade = Trade(tradingSymbol) trade.strategy = self.getName() trade.isFutures = True trade.direction = direction trade.productType = self.productType trade.placeMarketOrder = True trade.requestedEntry = high if direction == Direction.LONG else low trade.timestamp = Utils.getEpoch( self.startTimestamp) # setting this to strategy timestamp # Calculate lots numLots = self.calculateLotsPerTrade() isd = Instruments.getInstrumentDataBySymbol( tradingSymbol) # Get instrument data to know qty per lot trade.qty = isd['lot_size'] trade.stopLoss = low if direction == Direction.LONG else high slDiff = high - low # target is 1.5 times of SL if direction == 'LONG': trade.target = Utils.roundToNSEPrice(trade.requestedEntry + 1.5 * slDiff) else: trade.target = Utils.roundToNSEPrice(trade.requestedEntry - 1.5 * slDiff) trade.intradaySquareOffTimestamp = Utils.getEpoch( self.squareOffTimestamp) # Hand over the trade to TradeManager TradeManager.addNewTrade(trade)
def placeOrder(self, orderInputParams): message = "{0}: Going to place order with params {1}".format( self.broker, orderInputParams) Utils.sendMessageTelegramBot(message) logging.info(message) kite = self.brokerHandle try: orderId = kite.place_order( variety=kite.VARIETY_REGULAR, exchange=kite.EXCHANGE_NFO if orderInputParams.isFnO == True else kite.EXCHANGE_NSE, tradingsymbol=orderInputParams.tradingSymbol, transaction_type=self.convertToBrokerDirection( orderInputParams.direction), quantity=orderInputParams.qty, price=orderInputParams.price, trigger_price=orderInputParams.triggerPrice, product=self.convertToBrokerProductType( orderInputParams.productType), order_type=self.convertToBrokerOrderType( orderInputParams.orderType)) message = "{0}: Order placed successfully, orderId {1}".format( self.broker, orderId) Utils.sendMessageTelegramBot(message) logging.info(message) order = Order(orderInputParams) order.orderId = orderId order.orderPlaceTimestamp = Utils.getEpoch() order.lastOrderUpdateTimestamp = Utils.getEpoch() return order except Exception as e: logging.info('%s Order placement failed: %s', self.broker, str(e)) raise Exception(str(e))
def generateTrade(self, optionSymbol, numLots, lastTradedPrice, counterPosition): trade = Trade(optionSymbol) trade.strategy = self.getName() trade.isOptions = True trade.direction = Direction.SHORT # Always short here as option selling only trade.productType = self.productType trade.placeMarketOrder = True trade.requestedEntry = lastTradedPrice trade.timestamp = Utils.getEpoch( self.startTimestamp) # setting this to strategy timestamp trade.slPercentage = 25 trade.moveToCost = True trade.counterPosition = counterPosition isd = Instruments.getInstrumentDataBySymbol( optionSymbol) # Get instrument data to know qty per lot trade.qty = isd['lot_size'] * numLots trade.stopLoss = Utils.roundToNSEPrice(trade.requestedEntry + trade.requestedEntry * self.slPercentage / 100) trade.target = 0 # setting to 0 as no target is applicable for this trade trade.intradaySquareOffTimestamp = Utils.getEpoch( self.squareOffTimestamp) # Hand over the trade to TradeManager TradeManager.addNewTrade(trade)
def setTradeToCompleted(trade, exit, exitReason = None): trade.tradeState = TradeState.COMPLETED trade.exit = exit trade.exitReason = exitReason if trade.exitReason == None else trade.exitReason trade.endTimestamp = Utils.getEpoch() trade = Utils.calculateTradePnl(trade) logging.info('TradeManager: setTradeToCompleted strategy = %s, symbol = %s, qty = %d, entry = %f, exit = %f, pnl = %f, exit reason = %s', trade.strategy, trade.tradingSymbol, trade.filledQty, trade.entry, trade.exit, trade.pnl, trade.exitReason)
def __init__(self, tradingSymbol=None): self.exchange = "NSE" self.tradeID = Utils.generateTradeID() # Unique ID for each trade self.tradingSymbol = tradingSymbol self.strategy = "" self.direction = "" self.productType = ProductType.MIS self.isFutures = False # Futures trade self.isOptions = False # Options trade self.optionType = None # CE/PE. Applicable only if isOptions is True self.placeMarketOrder = False # True means place the entry order with Market Order Type self.intradaySquareOffTimestamp = None # Can be strategy specific. Some can square off at 15:00:00 some can at 15:15:00 etc. self.requestedEntry = 0 # Requested entry self.entry = 0 # Actual entry. This will be different from requestedEntry if the order placed is Market order self.qty = 0 # Requested quantity self.filledQty = 0 # In case partial fill qty is not equal to filled quantity self.initialStopLoss = 0 # Initial stop loss self.stopLoss = 0 # This is the current stop loss. In case of trailing SL the current stopLoss and initialStopLoss will be different after some time self.target = 0 # Target price if applicable self.cmp = 0 # Last traded price self.tradeState = TradeState.CREATED # state of the trade self.timestamp = None # Set this timestamp to strategy timestamp if you are not sure what to set self.createTimestamp = Utils.getEpoch( ) # Timestamp when the trade is created (Not triggered) self.startTimestamp = None # Timestamp when the trade gets triggered and order placed self.endTimestamp = None # Timestamp when the trade ended self.pnl = 0 # Profit loss of the trade. If trade is Active this shows the unrealized pnl else realized pnl self.pnlPercentage = 0 # Profit Loss in percentage terms self.exit = 0 # Exit price of the trade self.exitReason = None # SL/Target/SquareOff/Any Other self.entryOrder = None # Object of Type ordermgmt.Order self.slOrder = None # Object of Type ordermgmt.Order self.targetOrder = None # Object of Type ordermgmt.Order
def run(self): # NOTE: This should not be overriden in Derived class if self.enabled == False: logging.warn("%s: Not going to run strategy as its not enabled.", self.getName()) return if Utils.isMarketClosedForTheDay(): message="{}: Not going to run strategy as market is closed.".format(self.getName()) Utils.sendMessageTelegramBot(message) logging.warn(message) return now = datetime.now() if now < Utils.getMarketStartTime(): Utils.waitTillMarketOpens(self.getName()) if self.canTradeToday() == False: logging.warn("%s: Not going to run strategy as it cannot be traded today.", self.getName()) return now = datetime.now() if now < self.startTimestamp: waitSeconds = Utils.getEpoch(self.startTimestamp) - Utils.getEpoch(now) message="{0} Waiting for {1} seconds till startegy start timestamp reaches...".format(self.getName(),waitSeconds) Utils.sendMessageTelegramBot(message) logging.info(message) if waitSeconds > 0: time.sleep(waitSeconds) # Run in an loop and keep processing while True: if Utils.isMarketClosedForTheDay(): logging.warn("%s: Exiting the strategy as market closed.", self.getName()) break # Derived class specific implementation will be called when process() is called self.process() # Sleep and wake up on every 30th second now = datetime.now() waitSeconds = 30 - (now.second % 30) time.sleep(waitSeconds)
def trackAndUpdateAllTrades(): for trade in TradeManager.trades: if trade.tradeState == TradeState.ACTIVE: if trade.intradaySquareOffTimestamp != None: nowEpoch = Utils.getEpoch() if nowEpoch >= trade.intradaySquareOffTimestamp: TradeManager.squareOffTrade(trade, TradeExitReason.SQUARE_OFF) TradeManager.trackEntryOrder(trade) TradeManager.trackSLOrder(trade) TradeManager.trackTargetOrder(trade)
def generateTrade(self, tradingSymbol, direction, breakoutPrice, cmp): trade = Trade(tradingSymbol) trade.strategy = self.getName() trade.direction = direction trade.productType = self.productType trade.placeMarketOrder = True trade.requestedEntry = breakoutPrice trade.timestamp = Utils.getEpoch( self.startTimestamp) # setting this to strategy timestamp trade.qty = int(self.calculateCapitalPerTrade() / breakoutPrice) if trade.qty == 0: trade.qty = 1 # Keep min 1 qty if direction == 'LONG': trade.stopLoss = Utils.roundToNSEPrice(breakoutPrice - breakoutPrice * self.slPercentage / 100) if cmp < trade.stopLoss: trade.stopLoss = Utils.roundToNSEPrice(cmp - cmp * 1 / 100) else: trade.stopLoss = Utils.roundToNSEPrice(breakoutPrice + breakoutPrice * self.slPercentage / 100) if cmp > trade.stopLoss: trade.stopLoss = Utils.roundToNSEPrice(cmp + cmp * 1 / 100) if direction == 'LONG': trade.target = Utils.roundToNSEPrice(breakoutPrice + breakoutPrice * self.targetPerncetage / 100) else: trade.target = Utils.roundToNSEPrice(breakoutPrice - breakoutPrice * self.targetPerncetage / 100) trade.intradaySquareOffTimestamp = Utils.getEpoch( self.squareOffTimestamp) # Hand over the trade to TradeManager TradeManager.addNewTrade(trade) # add symbol to created list self.tradesCreatedSymbols.append(tradingSymbol)
def shouldFetchFromServer(): timestamps = getTimestampsData() if 'instrumentsLastSavedAt' not in timestamps: return True lastSavedTimestamp = timestamps['instrumentsLastSavedAt'] nowEpoch = Utils.getEpoch() if nowEpoch - lastSavedTimestamp >= 24 * 60 * 60: logging.info( "Instruments: shouldFetchFromServer() returning True as its been 24 hours since last fetch." ) return True return False
def cancelOrder(self, order): logging.info('%s Going to cancel order %s', self.broker, order.orderId) kite = self.brokerHandle try: orderId = kite.cancel_order(variety=kite.VARIETY_REGULAR, order_id=order.orderId) logging.info('%s Order cancelled successfully, orderId = %s', self.broker, orderId) order.lastOrderUpdateTimestamp = Utils.getEpoch() return order except Exception as e: logging.info('%s Order cancel failed: %s', self.broker, str(e)) raise Exception(str(e))
def modifyOrderToMarket(self, order): logging.info('%s: Going to modify order with params %s', self.broker) kite = self.brokerHandle try: orderId = kite.modify_order( variety=kite.VARIETY_REGULAR, order_id=order.orderId, order_type=kite.ORDER_TYPE_MARKET) logging.info('%s Order modified successfully to MARKET for orderId = %s', self.broker, orderId) order.lastOrderUpdateTimestamp = Utils.getEpoch() return order except Exception as e: logging.info('%s Order modify to market failed: %s', self.broker, str(e)) raise Exception(str(e))
def modifyOrder(self, order, orderModifyParams): logging.info('%s: Going to modify order with params %s', self.broker, orderModifyParams) kite = self.brokerHandle try: orderId = kite.modify_order( variety=kite.VARIETY_REGULAR, order_id=order.orderId, quantity=orderModifyParams.newQty if orderModifyParams.newQty > 0 else None, price=orderModifyParams.newPrice if orderModifyParams.newPrice > 0 else None, trigger_price=orderModifyParams.newTriggerPrice if orderModifyParams.newTriggerPrice > 0 else None, order_type=orderModifyParams.newOrderType if orderModifyParams.newOrderType != None else None) logging.info('%s Order modified successfully for orderId = %s', self.broker, orderId) order.lastOrderUpdateTimestamp = Utils.getEpoch() return order except Exception as e: logging.info('%s Order modify failed: %s', self.broker, str(e)) raise Exception(str(e))
def updateLastSavedTimestamp(): timestamps = getTimestampsData() timestamps['instrumentsLastSavedAt'] = Utils.getEpoch() saveTimestampsData(timestamps)