Path: blob/master/src/strategies/ShortStraddleBNF.py
300 views
import logging1from datetime import datetime23from instruments.Instruments import Instruments4from models.Direction import Direction5from models.ProductType import ProductType6from strategies.BaseStrategy import BaseStrategy7from utils.Utils import Utils8from trademgmt.Trade import Trade9from trademgmt.TradeManager import TradeManager1011# Each strategy has to be derived from BaseStrategy12class ShortStraddleBNF(BaseStrategy):13__instance = None1415@staticmethod16def getInstance(): # singleton class17if ShortStraddleBNF.__instance == None:18ShortStraddleBNF()19return ShortStraddleBNF.__instance2021def __init__(self):22if ShortStraddleBNF.__instance != None:23raise Exception("This class is a singleton!")24else:25ShortStraddleBNF.__instance = self26# Call Base class constructor27super().__init__("ShortStraddleBNF")28# Initialize all the properties specific to this strategy29self.productType = ProductType.MIS30self.symbols = []31self.slPercentage = 3032self.targetPercentage = 033self.startTimestamp = Utils.getTimeOfToDay(11, 0, 0) # When to start the strategy. Default is Market start time34self.stopTimestamp = Utils.getTimeOfToDay(14, 0, 0) # This is not square off timestamp. This is the timestamp after which no new trades will be placed under this strategy but existing trades continue to be active.35self.squareOffTimestamp = Utils.getTimeOfToDay(14, 30, 0) # Square off time36self.capital = 100000 # Capital to trade (This is the margin you allocate from your broker account for this strategy)37self.leverage = 038self.maxTradesPerDay = 2 # (1 CE + 1 PE) Max number of trades per day under this strategy39self.isFnO = True # Does this strategy trade in FnO or not40self.capitalPerSet = 100000 # Applicable if isFnO is True (1 set means 1CE/1PE or 2CE/2PE etc based on your strategy logic)4142def canTradeToday(self):43# Even if you remove this function canTradeToday() completely its same as allowing trade every day44return True4546def process(self):47now = datetime.now()48if now < self.startTimestamp:49return50if len(self.trades) >= self.maxTradesPerDay:51return5253# Get current market price of Nifty Future54futureSymbol = Utils.prepareMonthlyExpiryFuturesSymbol('BANKNIFTY')55quote = self.getQuote(futureSymbol)56if quote == None:57logging.error('%s: Could not get quote for %s', self.getName(), futureSymbol)58return5960ATMStrike = Utils.getNearestStrikePrice(quote.lastTradedPrice, 100)61logging.info('%s: Nifty CMP = %f, ATMStrike = %d', self.getName(), quote.lastTradedPrice, ATMStrike)6263ATMCESymbol = Utils.prepareWeeklyOptionsSymbol("BANKNIFTY", ATMStrike, 'CE')64ATMPESymbol = Utils.prepareWeeklyOptionsSymbol("BANKNIFTY", ATMStrike, 'PE')65logging.info('%s: ATMCESymbol = %s, ATMPESymbol = %s', self.getName(), ATMCESymbol, ATMPESymbol)66# create trades67self.generateTrades(ATMCESymbol, ATMPESymbol)6869def generateTrades(self, ATMCESymbol, ATMPESymbol):70numLots = self.calculateLotsPerTrade()71quoteATMCESymbol = self.getQuote(ATMCESymbol)72quoteATMPESymbol = self.getQuote(ATMPESymbol)73if quoteATMCESymbol == None or quoteATMPESymbol == None:74logging.error('%s: Could not get quotes for option symbols', self.getName())75return7677self.generateTrade(ATMCESymbol, numLots, quoteATMCESymbol.lastTradedPrice)78self.generateTrade(ATMPESymbol, numLots, quoteATMPESymbol.lastTradedPrice)79logging.info('%s: Trades generated.', self.getName())8081def generateTrade(self, optionSymbol, numLots, lastTradedPrice):82trade = Trade(optionSymbol)83trade.strategy = self.getName()84trade.isOptions = True85trade.direction = Direction.SHORT # Always short here as option selling only86trade.productType = self.productType87trade.placeMarketOrder = True88trade.requestedEntry = lastTradedPrice89trade.timestamp = Utils.getEpoch(self.startTimestamp) # setting this to strategy timestamp9091isd = Instruments.getInstrumentDataBySymbol(optionSymbol) # Get instrument data to know qty per lot92trade.qty = isd['lot_size'] * numLots9394trade.stopLoss = Utils.roundToNSEPrice(trade.requestedEntry + trade.requestedEntry * self.slPercentage / 100)95trade.target = 0 # setting to 0 as no target is applicable for this trade9697trade.intradaySquareOffTimestamp = Utils.getEpoch(self.squareOffTimestamp)98# Hand over the trade to TradeManager99TradeManager.addNewTrade(trade)100101def shouldPlaceTrade(self, trade, tick):102# First call base class implementation and if it returns True then only proceed103if super().shouldPlaceTrade(trade, tick) == False:104return False105# We dont have any condition to be checked here for this strategy just return True106return True107108def getTrailingSL(self, trade):109if trade == None:110return 0111if trade.entry == 0:112return 0113lastTradedPrice = TradeManager.getLastTradedPrice(trade.tradingSymbol)114if lastTradedPrice == 0:115return 0116117trailSL = 0118profitPoints = int(trade.entry - lastTradedPrice)119if profitPoints >= 5:120factor = int(profitPoints / 5)121trailSL = Utils.roundToNSEPrice(trade.initialStopLoss - factor * 5)122logging.info('%s: %s Returning trail SL %f', self.getName(), trade.tradingSymbol, trailSL)123return trailSL124125126127