Path: blob/master/src/strategies/OptionSelling.py
301 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 OptionSelling(BaseStrategy):13__instance = None1415@staticmethod16def getInstance(): # singleton class17if OptionSelling.__instance == None:18OptionSelling()19return OptionSelling.__instance2021def __init__(self):22if OptionSelling.__instance != None:23raise Exception("This class is a singleton!")24else:25OptionSelling.__instance = self26# Call Base class constructor27super().__init__("OptionSelling")28# Initialize all the properties specific to this strategy29self.productType = ProductType.MIS30self.symbols = []31self.slPercentage = 5032self.targetPercentage = 033self.startTimestamp = Utils.getTimeOfToDay(9, 30, 0) # When to start the strategy. Default is Market start time34self.stopTimestamp = Utils.getTimeOfToDay(14, 30, 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(15, 15, 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):43if Utils.isTodayOneDayBeforeWeeklyExpiryDay() == True:44logging.info('%s: Today is one day before weekly expiry date hence going to trade this strategy', self.getName())45return True46if Utils.isTodayWeeklyExpiryDay() == True:47logging.info('%s: Today is weekly expiry day hence going to trade this strategy today', self.getName())48return True49logging.info('%s: Today is neither day before expiry nor expiry day. Hence NOT going to trade this strategy today', self.getName())50return False5152def process(self):53now = datetime.now()54if now < self.startTimestamp:55return56if len(self.trades) >= self.maxTradesPerDay:57return5859# Get current market price of Nifty Future60futureSymbol = Utils.prepareMonthlyExpiryFuturesSymbol('NIFTY')61quote = self.getQuote(futureSymbol)62if quote == None:63logging.error('%s: Could not get quote for %s', self.getName(), futureSymbol)64return6566ATMStrike = Utils.getNearestStrikePrice(quote.lastTradedPrice, 50)67logging.info('%s: Nifty CMP = %f, ATMStrike = %d', self.getName(), quote.lastTradedPrice, ATMStrike)6869ATMPlus50CESymbol = Utils.prepareWeeklyOptionsSymbol("NIFTY", ATMStrike + 50, 'CE')70ATMMinus50PESymbol = Utils.prepareWeeklyOptionsSymbol("NIFTY", ATMStrike - 50, 'PE')71logging.info('%s: ATMPlus50CE = %s, ATMMinus50PE = %s', self.getName(), ATMPlus50CESymbol, ATMMinus50PESymbol)72# create trades73self.generateTrades(ATMPlus50CESymbol, ATMMinus50PESymbol)7475def generateTrades(self, ATMPlus50CESymbol, ATMMinus50PESymbol):76numLots = self.calculateLotsPerTrade()77quoteATMPlus50CESymbol = self.getQuote(ATMPlus50CESymbol)78quoteATMMinus50PESymbol = self.getQuote(ATMMinus50PESymbol)79if quoteATMPlus50CESymbol == None or quoteATMMinus50PESymbol == None:80logging.error('%s: Could not get quotes for option symbols', self.getName())81return8283self.generateTrade(ATMPlus50CESymbol, numLots, quoteATMPlus50CESymbol.lastTradedPrice)84self.generateTrade(ATMMinus50PESymbol, numLots, quoteATMMinus50PESymbol.lastTradedPrice)85logging.info('%s: Trades generated.', self.getName())8687def generateTrade(self, optionSymbol, numLots, lastTradedPrice):88trade = Trade(optionSymbol)89trade.strategy = self.getName()90trade.isOptions = True91trade.direction = Direction.SHORT # Always short here as option selling only92trade.productType = self.productType93trade.placeMarketOrder = True94trade.requestedEntry = lastTradedPrice95trade.timestamp = Utils.getEpoch(self.startTimestamp) # setting this to strategy timestamp9697isd = Instruments.getInstrumentDataBySymbol(optionSymbol) # Get instrument data to know qty per lot98trade.qty = isd['lot_size'] * numLots99100trade.stopLoss = Utils.roundToNSEPrice(trade.requestedEntry + trade.requestedEntry * self.slPercentage / 100)101trade.target = 0 # setting to 0 as no target is applicable for this trade102103trade.intradaySquareOffTimestamp = Utils.getEpoch(self.squareOffTimestamp)104# Hand over the trade to TradeManager105TradeManager.addNewTrade(trade)106107def shouldPlaceTrade(self, trade, tick):108# First call base class implementation and if it returns True then only proceed109if super().shouldPlaceTrade(trade, tick) == False:110return False111# We dont have any condition to be checked here for this strategy just return True112return True113114115