Overall Statistics |
Total Trades 204 Average Win 1.67% Average Loss -1.30% Compounding Annual Return 26.661% Drawdown 10.600% Expectancy 0.745 Net Profit 157.545% Sharpe Ratio 1.55 Probabilistic Sharpe Ratio 83.848% Loss Rate 24% Win Rate 76% Profit-Loss Ratio 1.29 Alpha 0.11 Beta 0.69 Annual Standard Deviation 0.12 Annual Variance 0.014 Information Ratio 0.756 Tracking Error 0.1 Treynor Ratio 0.27 Total Fees $2205.00 Estimated Strategy Capacity $16000000.00 Lowest Capacity Asset SPY W7FVJCNHA4BQ|SPY R735QTJ8XC9X |
#region imports from AlgorithmImports import * #endregion class IBOptionMarginModel(OptionMarginModel): def __init__(self, algorithm): self.algorithm = algorithm def GetMarginRequirement(self, security, value): OptionMarginRequirement=1 option = security if (value == 0 or option.Close == 0 or option.StrikePrice == 0 or option.Underlying == None or option.Underlying.Close == 0): return 0 if (value > 0): return OptionMarginRequirement absValue = -value optionProperties = option.SymbolProperties underlying = option.Underlying multiplierRatio = underlying.SymbolProperties.ContractMultiplier / optionProperties.ContractMultiplier quantityRatio = optionProperties.ContractUnitOfTrade priceRatio = underlying.Close / (absValue / quantityRatio) underlyingValueRatio = multiplierRatio * quantityRatio * priceRatio if option.Right == OptionRight.Call: amountOTM = max(0, option.StrikePrice - underlying.Close) else: amountOTM= max(0, underlying.Close - option.StrikePrice) priceRatioOTM = amountOTM / (absValue / quantityRatio) underlyingValueRatioOTM = multiplierRatio * quantityRatio * priceRatioOTM result = OptionMarginRequirement +\ option.Holdings.AbsoluteQuantity * max(NakedPositionMarginRequirement * underlyingValueRatio, NakedPositionMarginRequirementOtm * underlyingValueRatio - underlyingValueRatioOTM) self.algorithm.Log("OPTION MARGIN MODEL, RESULT: " + str(result)) return result class CustomBuyingPowerModel(BuyingPowerModel): def __init__(self, algorithm): self.algorithm = algorithm # def HasSufficientBuyingPowerForOrder(self, parameters): # # custom behavior: this model will assume that there is always enough buying power # hasSufficientBuyingPowerForOrderResult = HasSufficientBuyingPowerForOrderResult(True) # return hasSufficientBuyingPowerForOrderResult # def GetInitialMarginRequiredForOrder(self, parameters): # fees = parameters.Security.FeeModel.GetOrderFee(parameters.Security, parameters.Order).Value # feesInAccountCurrency = parameters.CurrencyConverter.ConvertToAccountCurrency.Amount # orderMargin = self.GetInitialMarginRequirement(parameters.Security, parameters.Order.Quantity); # result=orderMargin + math.copysign(1,(orderMargin) * feesInAccountCurrency) # self.algorithm.Log("IN CUSTOM MODEL, RESULT: "+ str(result)) # return result
#region imports from AlgorithmImports import * import random import ast #endregion import queue from CustomModels import * class MuscularBlackLion(QCAlgorithm): def Initialize(self): #RECORDING SETTINGS: self.recordIVWindow = False self.IVWindow = queue.Queue(252) self.grabIVWindow("ivWindow_2011-04-01 00:00:00_2011-12-31 23:59:59.999999") #OPTION FILTER SETTINGS self.minDTE = 35 #int(self.GetParameter("minDTE")) #20-35 self.maxDTE = 60 self.marginPctToUse = 100 self.deltaTarget = 0.05 self.callDeltaRatio = 0.65 self.putDeltaRatio = 6.8 #VOLATILITY MANAGEMENT SETTINGS self.IVMetric = "logIVRP" #choices[int(IVChoice)] #0 self.IvrTarget= 0 #int(self.GetParameter("IvrTarget"))#0 self.IVRWaitimeDayTreshold = 20 #max days to wait after loss while monitoring IVMetric for reentry self.IvrDangerThreshold = 55 #int(self.GetParameter("IvrDangerThreshold")) #70 #RISK MANAGEMENT SETTINGS self.closeBeforeExpDate = 1 self.takeProfit = 60 #int(self.GetParameter("takeProfit"))#60 self.stopLoss = 175 #int(self.GetParameter("stopLoss"))#175 self.trailingStopPercent = 30 self.trailingStopPercentGain = 30 #int(self.GetParameter("trailingStopPercent"))#30 self.trailingStopPercentLoss = 250 #ROLLING SETTINGS self.rollingEnabled=True self.callStrengthDangerThreshold=35 self.putStrengthDangerThreshold=10 self.daysBetweenManagement= 10 self.rollCallRatio=2.5 self.rollPutRatio=1 self.breachedDaysThresholdCall = 1 self.breachedDaysThresholdPut = 1 self.SetStartDate(2012, 1, 1) # Set Start Date self.SetEndDate(2016, 1, 1) # Set Start Date self.SetCash(100000) # Set Strategy Cash self.equity = self.AddEquity("SPY", Resolution.Minute) self.equity.VolatilityModel = StandardDeviationOfReturnsVolatilityModel(30) option = self.AddOption("SPY", Resolution.Minute) option.SetFilter(lambda universe: universe.IncludeWeeklys().Strikes(-1, 1).Expiration(timedelta(0), timedelta(36))) option.PriceModel = OptionPriceModels.BjerksundStensland() self.strangleQty = 0 self.equity.SetDataNormalizationMode(DataNormalizationMode.Raw) self.symbol = option.Symbol self.benchmarkTicker = 'SPY' self.SetBenchmark(self.benchmarkTicker) self.initBenchmarkPrice = None self.start = datetime.now() self.end = datetime.now() self.expiry= None self.DTE = 45 self.SetWarmUp(TimeSpan.FromDays(50)) self.CostOfContract = 0 self.profitPercent=0 self.vix = self.AddData(CBOE, "VIX").Symbol self.putContract = None self.putCost=0 self.callCost=0 self.callContract = None self.lastManagedDatePut = self.StartDate self.lastManagedDateCall = self.StartDate self.Portfolio.MarginCallModel = MarginCallModel.Null self.previousMargin=0 self.daysNotTradingInARow=0 self.IVMetricWindow = queue.Queue(15) self.IVR=-1 self.IVP=-1 self.logIVRP=-1 self.currIv=0 self.dailyAverageIv=0 self.dailyAverageIvr=0 self.dailyAverageIvrCount=0 self.dailyAverageIvp=0 self.dailyAverageIvpCount=0 self.dailyAverageIvmetric = 0 self.dailyIvmetricCount = 0 self.dailyIvCount = 0 self.endOfDayReached=False self.daysBreached = 0 self.lastBreached = None self.daysBreachedPut = 0 self.lastBreachedPut = None self.currentDay = None self.expiryWeCantFindPutFor=self.StartDate self.callContracts= [] self.putContracts= [] self.rollingPutUp=False self.rollingCallDown=False self.waitUntilIVRLowers=False self.waitUntilIVRLowersDays=0 self.IvHours=[9,10,11,12,13,14,15] self.SetSecurityInitializer(self.securityInitializer) self.optionStep=0 self.minBuyBack = sys.maxsize self.maxProfit = -sys.maxsize - 1 self.activateTrailingStopLoss=False self.underlyingPriceAtStrangleSale=0 # self.ObjectStore.Save("test", str(self.IvHours)) self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) def OnEndOfAlgorithm(self): if self.recordIVWindow: key="ivWindow_"+str(self.StartDate)+"_"+str(self.EndDate) if not self.ObjectStore.ContainsKey(key): self.ObjectStore.Save(key, str(list(self.IVWindow.queue))) self.Debug("RECORDED IVWINDOW WITH KEY: "+key) def securityInitializer(self, security): security.SetLeverage(2) if security.Type == SecurityType.Option: security.SetMarginModel(IBOptionMarginModel(self)) security.SetBuyingPowerModel(CustomBuyingPowerModel(self)) def OnData(self, slice): '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. Arguments: slice: Slice object keyed by symbol containing the stock data ''' if self.Time.hour ==9 and self.Time.minute==31 and self.Time.second==0: self.start = datetime.now() if self.Portfolio.Invested: self.daysNotTradingInARow=0 if not self.IsWarmingUp and self.notBuggyDay(): # if self.Time.Day==self.StartDate.Day: self.calculateDailyIv() if self.IVWindow.qsize() > 1: self.currIv=self.getCurrentIV() self.calculateIVR() self.calculateIVP() self.logIVRP = self.calculateLogIVRP(self.IVR, self.IVP) # if self.LiveMode: # self.Debug("IVWindow size: " + str(self.IVWindow.qsize())) # self.Debug("CurrIV: " + str(self.currIv)) ''' We are either Recording, Rolling, Buying, or seeing if we need to sell. ''' if self.recordIVWindow: self.recordIVWindow #Rolling #Buying if we can elif self.buyCondition(self.IVMetric): if not self.callContract: if self.callContracts==[]: self.callContracts = self.optionsFilter(slice, OptionRight.Call, self.equity.Price*1.03, self.equity.Price*1.2) else: self.callContract = self.getCallContract(slice, self.getCallDelta()) if not self.putContract and self.callContract: if self.putContracts==[]: self.putContracts = self.optionsFilter(slice, OptionRight.Put, self.equity.Price*0.80, self.equity.Price*0.97) else: self.putContract = self.getPutContract(slice, self.getPutDelta()) elif self.callContract and self.putContract: self.putContracts=[] if self.notStale() and self.isTradeable(): self.sellToOpenStrangle(self.marginPctToUse) self.optionStep=0 self.expiryWeCantFindPutFor=self.StartDate else: self.putContract=None self.callContract=None self.cleanUp() #Seeing if we need to sell elif self.putContract and self.callContract: daysLeft =(self.callContract.Expiry - self.Time).days profitPercent = self.ProfitPercentage() self.checkIfNeedToRoll(0) if daysLeft == self.closeBeforeExpDate: self.buyToCloseStrangle() elif self.activateTrailingStopLoss and profitPercent > 0: self.stopLossManagement() elif profitPercent > self.takeProfit: self.activateTrailingStopLoss=True elif profitPercent < -self.stopLoss: self.buyToCloseStrangle() self.waitUntilIVRLowers=True elif self.rollingCallDown or self.rollingPutUp: self.rollIfNeeded() if self.Time.hour ==15 and self.Time.minute==58: self.end = datetime.now() def rollIfNeeded(self): if not self.rollingEnabled: return if self.rollingCallDown: if self.optionStep > 25: self.optionStep=0 self.callContracts=[] if self.callContracts==[]: self.callContracts = self.optionsFilter(slice, OptionRight.Call, self.equity.Price, self.equity.Price*1.5) else: contract = self.getRolledCall() if contract != None: self.callContract = contract self.lastManagedDateCall = self.Time self.rollingCallDown=False self.daysBreachedPut=0 return True elif self.rollingPutUp: if self.optionStep > 25: self.optionStep=0 self.putContracts=[] if self.putContracts==[]: self.putContracts = self.optionsFilter(slice, OptionRight.Put, self.equity.Price*0.5, self.equity.Price) else: contract = self.getRolledPut() if contract != None: self.putContract = contract self.lastManagedDatePut = self.Time self.rollingPutUp=False self.daysBreached=0 return True else: return False def expiringInAnHour(self): daysLeft = len(list(self.TradingCalendar.GetDaysByType(TradingDayType.BusinessDay, self.Time, self.Time + (self.callContract.Expiry - self.Time)))) if daysLeft == 1: return self.Time.hour == 15 and self.Time.minute == 59 and self.ProfitPercentage()<0 else: return False def notStale(self): keys = self.CurrentSlice.Keys if (self.putContract.Symbol not in keys) or (self.callContract.Symbol not in keys): return False if (self.CurrentSlice[self.callContract.Symbol]!=None and self.CurrentSlice[self.putContract.Symbol]!=None): isNotStale = (not self.CurrentSlice[self.callContract.Symbol].IsFillForward) \ and (not self.CurrentSlice[self.putContract.Symbol].IsFillForward) return isNotStale else: return False def isTradeable(self): return self.Securities[self.callContract.Symbol].IsTradable \ and self.Securities[self.putContract.Symbol].IsTradable def buyCondition(self, IVMetric): ivm = getattr(self, self.IVMetric) initialCondition = (not self.Portfolio.Invested and self.currIv!=0) if self.waitUntilIVRLowers: if (ivm < self.IvrDangerThreshold) or self.waitUntilIVRLowersDays >= self.IVRWaitimeDayTreshold: self.waitUntilIVRLowers=False self.waitUntilIVRLowersDays=0 return initialCondition else: return False else: return initialCondition and self.IvrTarget < ivm def cleanUp(self): minutesWithoutStrangle=self.optionStep/2 if minutesWithoutStrangle > 200 and not self.Portfolio.Invested: # self.expiryWeCantFindPutFor=self.callContract.Expiry self.callContract=None self.putContract=None self.optionStep=0 self.callContracts=[] self.putContracts=[] if(self.callContract) or self.isEven(self.optionStep): self.callContracts=[] if(self.putContract) or self.isEven(self.optionStep): self.putContracts=[] def isEven(self, num): return (num % 2) == 0 def stopLossManagement(self): profitPct=self.ProfitPercentage() profit = self.profit() totalCost = self.putCost + self.callCost profit = self.profit() if profit > self.maxProfit: self.maxProfit=profit profitLossCutOffPoint=self.maxProfit*(1-(self.trailingStopPercentGain/100)) if profitLossCutOffPoint!= 0 and 0 < profit < profitLossCutOffPoint: self.buyToCloseStrangle() def sellToOpenStrangle(self, marginPct): UC = self.Securities["SPY"].Price #call callCPC = self.callContract.BidPrice Strike = self.callContract.Strike #Effect call has on margin # callMEOLD = ((0.2*UC)-(Strike-UC)+callCPC)*1*100 callME = ((Strike*100)*0.2)-(callCPC*100) #put putCPC = self.putContract.BidPrice Strike = self.putContract.Strike #Effect put # putMEOLD = ((0.2*UC)-(UC-Strike)+putCPC)*1*100 putME=((Strike*100)*0.25)-(putCPC*100) totalME = max(putME+(callCPC*100), callME+ (putCPC*100)) # totalMEOLD = callMEOLD + putMEOLD self.strangleQty = math.floor((self.Portfolio.MarginRemaining * (self.marginPctToUse/100))/totalME) self.putCost=self.MarketOrder(self.putContract.Symbol, -self.strangleQty).AverageFillPrice*100*self.strangleQty self.callCost=self.MarketOrder(self.callContract.Symbol, -self.strangleQty).AverageFillPrice*100*self.strangleQty self.underlyingPriceAtStrangleSale = self.equity.Price return def buyToCloseStrangle(self): self.Liquidate() self.putContract = None self.callContract = None self.lastManagedDatePut = self.StartDate; self.lastManagedDateCall = self.StartDate; self.daysBreached = 0 self.lastBreached = None self.daysBreachedPut = 0 self.lastBreachedPut = None self.maxProfit = -sys.maxsize - 1 self.minBuyBack = sys.maxsize self.activateTrailingStopLoss=False self.rollingCallDown=False self.rollingPutUp=False def profit(self): totalCost=self.putCost + self.callCost amountToBuyPut = self.amountToBuyPut() amountToBuyCall = self.amountToBuyCall() profit = totalCost - (amountToBuyPut + amountToBuyCall) return profit def amountToBuyPut(self): return self.Securities[self.putContract.Symbol].BidPrice*100*self.strangleQty def amountToBuyCall(self): return self.Securities[self.callContract.Symbol].BidPrice*100*self.strangleQty def ProfitPercentage(self): profit = self.profit() totalcost = totalCost=self.putCost + self.callCost if(totalCost!=0 ): return (profit/totalCost) * 100 else: return 0 def withinPercent(self, number, target, pctTarget, absolute=True): # oldPct= (abs(target/number)-1)*100 if absolute: absNumber=abs(number) absTarget=abs(target) pctFromTarget = abs((absNumber/absTarget)-1)*100 return pctFromTarget < pctTarget def checkIfNeedToRoll(self, daysToWaitForManagement): if not self.rollingEnabled: return putStrength= self.putStrength() callStrength= self.callStrength() if (self.callContract.Expiry - self.Time).days > daysToWaitForManagement \ and putStrength < self.putStrengthDangerThreshold \ and (self.Time - self.lastManagedDateCall).days > self.daysBetweenManagement: if self.shouldRollCall(): self.rollingCallDown=True if (self.putContract.Expiry - self.Time).days > daysToWaitForManagement \ and callStrength < self.callStrengthDangerThreshold \ and (self.Time - self.lastManagedDatePut).days > self.daysBetweenManagement: if self.shouldRollPut(): self.rollingPutUp=True return def getRolledPut(self): expiry = self.putContract.Expiry newPut = self.getPutContract(self.CurrentSlice, self.getPutDelta()*self.rollPutRatio, expiry) if newPut: buyToCloseCost = self.MarketOrder(self.putContract.Symbol, self.strangleQty).AverageFillPrice*100*self.strangleQty buyToCloseProfit = self.putCost - buyToCloseCost ticket = self.MarketOrder(newPut.Symbol, -self.strangleQty) contractCost = ticket.AverageFillPrice*100*self.strangleQty self.putCost = contractCost - buyToCloseProfit return newPut def getRolledCall(self): expiry = self.callContract.Expiry newCall = self.getCallContract(self.CurrentSlice, self.getCallDelta()*self.rollCallRatio, expiry) if newCall: buyToCloseCost = self.MarketOrder(self.callContract.Symbol, self.strangleQty).AverageFillPrice*100*self.strangleQty buyToCloseProfit = self.callCost - buyToCloseCost contractCost = self.MarketOrder(newCall.Symbol, -self.strangleQty).AverageFillPrice*100*self.strangleQty self.callCost = contractCost - buyToCloseProfit return newCall def isWeekend(self, Time): return Time.weekday() == DayOfWeek.Sunday or Time.weekday() == DayOfWeek.Saturday def shouldRollPut(self): if self.isWeekend(self.Time): if self.lastBreachedPut!=None and not self.isWeekend(self.lastBreachedPut): self.lastBreachedPut = self.lastBreachedPut + timedelta(days=1) return False if self.daysBreachedPut < self.breachedDaysThresholdPut: timeSinceLastBreach = None if self.lastBreachedPut!=None: diff=(self.Time-self.lastBreachedPut) days, seconds = diff.days, diff.seconds timeSinceLastBreach = days * 24 + seconds // 3600 if timeSinceLastBreach == None or (timeSinceLastBreach >= 24 and timeSinceLastBreach <= 31): self.daysBreachedPut+=1 self.lastBreachedPut = self.Time elif timeSinceLastBreach > 31: self.daysBreachedPut = 0 self.lastBreachedPut = None return not (self.daysBreachedPut <= self.breachedDaysThresholdPut) else: return True def shouldRollCall(self): if self.isWeekend(self.Time): if self.lastBreached!=None and not self.isWeekend(self.lastBreached): self.lastBreached = self.lastBreached + timedelta(days=1) return False if self.daysBreached < self.breachedDaysThresholdCall: timeSinceLastBreach = None if self.lastBreached!=None: diff=(self.Time-self.lastBreached ) days, seconds = diff.days, diff.seconds timeSinceLastBreach = days * 24 + seconds // 3600 #if time since last breach is none, its because last breach is none, which means its our first breach moment if timeSinceLastBreach == None or (timeSinceLastBreach >= 24 and timeSinceLastBreach <= 31): self.daysBreached+=1 self.lastBreached = self.Time elif timeSinceLastBreach > 31: self.daysBreached = 0 self.lastBreached = None return not (self.daysBreached <= self.breachedDaysThresholdCall) return True def calculateIVV(self, IVMetric): lst = list(self.IVMetricWindow.queue) return averageVariance(lst) def averageVariance(numlist): devationSquared=varianceList(numlist) return math.sqrt(sum(deviationSquared) / len(deviationSquared)) def varianceList(self,numlist): mean = sum(numlist) / len(numlist) deviationSquared=[] for value in lst: deviationSquared.append((value-mean)**2) return deviationSquared def lastVariance(self, numlist): devationSquared=varianceList(numlist) return math.sqrt(deviationSquared[-1]) def updateIvMetricWindow(self, IVMetric): ivm = getattr(self, IVMetric) self.IVMetricWindow.put(ivm) def calculateIVR(self): if self.currIv == None: return nowIvList=list(self.IVWindow.queue) nowIvList.append(self.currIv) sorted_IVs = sorted(nowIvList, reverse=True) max_IV = sorted_IVs[0] min_IV = sorted_IVs[-1] self.IVR = (self.currIv - min_IV)*100 / (max_IV - min_IV) if self.IVR!=0: self.dailyAverageIvr+=self.IVR self.dailyAverageIvrCount+=1 def ivTransform(self, iv): if iv!=None and iv!=0: return math.log(iv) def calculateLogIVRP(self, ivr, ivp): IVRCoeffs=[0, 0.25, 0.5, 0.75, 1] IVRCoeff=IVRCoeffs[2] IVPCoeff=1-IVRCoeff if ivr!=0 and ivp!=0: return ((IVRCoeff*ivr)+(IVPCoeff*ivp)) else: # self.Debug("iv: " + str(self.currIv)+"ivr: "+str(ivr) + "ivp: "+str(ivp)) return 0 def calculateIVP(self): if self.currIv == None: return nowIvList=list(self.IVWindow.queue) tradingDaysUnder = len([x for x in nowIvList if x < self.currIv]) totalLength = len(nowIvList) if tradingDaysUnder == 0 or totalLength == 0: return # if self.IVR==0: # self.Debug("tradingDaysUnder: " +str(tradingDaysUnder) + " totalLength : "+ str(totalLength)) self.IVP = (tradingDaysUnder/totalLength)*100 if self.IVP!=0: self.dailyAverageIvp+=self.IVP self.dailyAverageIvpCount+=1 def getCurrentIV(self): option=self.getAtmOption() if option!=None: return self.ivTransform(option.ImpliedVolatility) # return random.uniform(0,1) def getAtmOption(self): for kvp in self.CurrentSlice.OptionChains: if kvp.Key != self.symbol: continue chain = kvp.Value spot_price = chain.Underlying.Price # Sort to find ATM contracts sorted_strikes = sorted(chain, key=lambda k:abs(k.Strike - spot_price), reverse=False) # sorted_strikes = [x for x in sorted_strikes if x.Expiry>self.Time] # # IV of ATM contract return sorted_strikes[0] def calculateDailyIv(self): currIv=self.getCurrentIV() if currIv!=None and currIv!= 0: self.dailyAverageIv += currIv self.dailyIvCount+=1 def OnEndOfDay(self, symbol): if symbol==list(self.ActiveSecurities.Keys)[0]: # self.removeUninvestedOptions() if self.waitUntilIVRLowers: self.waitUntilIVRLowersDays+=1 if not self.Portfolio.Invested: self.daysNotTradingInARow += 1 self.endOfDayReached=True if self.IVWindow.full(): self.IVWindow.get() if self.IVMetricWindow.full(): self.IVMetricWindow.get() if self.dailyAverageIv != 0: dailyIv = self.dailyAverageIv/self.dailyIvCount self.IVWindow.put(dailyIv) # self.Plot("IV", "iv", dailyIv) self.dailyAverageIv=0 self.dailyIvCount=0 if self.dailyAverageIvrCount!=0: ivr = self.dailyAverageIvr/self.dailyAverageIvrCount # self.Plot("IV Metrics", "ivr",ivr) self.dailyAverageIvr=0 self.dailyAverageIvrCount=0 if self.dailyAverageIvpCount!=0: ivp = self.dailyAverageIvp/self.dailyAverageIvpCount # self.Plot("IV Metrics", "IVP",ivp) self.dailyAverageIvp=0 self.dailyAverageIvpCount=0 self.Plot("IV Metrics", "LogIVRP", self.calculateLogIVRP(ivr, ivp)) self.updateIvMetricWindow(self.IVMetric) # self.Plot("IVV", "IVV", self.calculateIVV(self.IVMetric)) self.Plot("Data Chart", "SPY", self.Securities["SPY"].Close) if self.putContract: self.Plot("Data Chart", "Put Strike", self.putContract.Strike) self.Plot("Deltas", "Put Delta", self.putContract.Greeks.Delta) self.Plot("Deltas", "Delta Target", -self.putTarget) # self.Plot("DTE on Order", "Put DTE", (self.putContract.Expiry - self.Time).days) self.Plot("ITM Vulnerability", "Put Strength", self.putStrength()) if self.callContract: self.Plot("Data Chart", "Call Strike", self.callContract.Strike) self.Plot("Deltas", "Call Delta", self.callContract.Greeks.Delta) # self.Plot("DTE on Order", "Call DTE", (self.callContract.Expiry - self.Time).days) self.Plot("ITM Vulnerability", "Call Strength", self.callStrength()) # self.Plot("IVWindow", "Length", len(list(self.IVWindow.queue))) dm=divmod((datetime.now()-self.start).total_seconds(), 60) minutes=dm[0] seconds=dm[1] self.Plot("Daily Runtime", "Minutes", str(minutes+(seconds/100))) def callStrength(self): strike = self.callContract.Strike originalPrice = self.underlyingPriceAtStrangleSale currentPrice = self.equity.Price strength=((strike-currentPrice)/(strike-originalPrice))*100 return strength def putStrength(self): strike = self.putContract.Strike originalPrice = self.underlyingPriceAtStrangleSale currentPrice = self.equity.Price strength=((strike-currentPrice)/(strike-originalPrice))*100 # self.Debug("PUT STRENGTH Strike: " + str(strike)+" originalPrice :"+ str(originalPrice)+ " currentPrice: "+ str(currentPrice)+"CALCULATED PUT STRENGTH: "+str(strength)) return strength def optionsFilter(self, slice, right, minStrike, maxStrike): self.optionStep+=1 minDTE=self.minDTE if self.rollingPutUp or self.rollingCallDown: minDTE=0 results=[] contract_symbols = self.OptionChainProvider.GetOptionContractList(self.equity.Symbol, self.CurrentSlice.Time) contracts = [OptionContract(symbol, self.equity.Symbol) for symbol in contract_symbols] contracts = [x for x in contracts if minDTE < (x.Expiry-self.Time).days < self.maxDTE \ and x.Right == right and minStrike < x.Strike < maxStrike] for contract in contracts: option = self.AddOptionContract(contract.Symbol, Resolution.Minute) option.PriceModel = OptionPriceModels.BinomialTian() results.append(contract.Symbol) return results def getCallContract(self, slice, delta, expiry=None): self.optionStep+=1 for symbol, chain in slice.OptionChains.items(): chainContracts=chain.Contracts for c in self.callContracts: if slice.ContainsKey(c): contract = chainContracts[c] if expiry == None: if self.withinPercent(contract.Greeks.Delta, delta, 10) and contract.Expiry!=self.expiryWeCantFindPutFor: return contract else: if self.withinPercent(contract.Greeks.Delta, delta, 10) and contract.Expiry==expiry: return contract def getPutContract(self, slice, delta, expiry=None): self.optionStep+=1 for symbol, chain in slice.OptionChains.items(): chainContracts=chain.Contracts putContracts=[] for c in self.putContracts: if slice.ContainsKey(c): contract = chainContracts[c] if expiry == None: if self.callContract.Expiry and self.withinPercent(contract.Greeks.Delta, delta, 15) and contract.Expiry==self.callContract.Expiry: # if self.callContract.Expiry and self.withinPercent(contract.Greeks.Delta, delta, 15): self.putTarget=delta return contract else: if self.withinPercent(contract.Greeks.Delta, delta, 10) and contract.Expiry==expiry: self.Debug("Contract delta: " + str(contract.Greeks.Delta) + "Contract Expiry: "+str(contract.Expiry)+ "Wanted Expiry: "+str(expiry)) self.putTarget=delta return contract def getCallDelta(self): ivm = getattr(self, self.IVMetric) ivmRatio=ivm/100 #ivmRatio goes here ratioSide = (self.deltaTarget*self.callDeltaRatio)*ivmRatio targetSide = (self.deltaTarget)*(1-ivmRatio) return ratioSide+targetSide # return self.deltaTarget*self.callDeltaRatio def getPutDelta(self): ivm = getattr(self, self.IVMetric) ivmRatio=ivm/100 ratioSide = (self.deltaTarget*self.putDeltaRatio)*ivmRatio targetSide = (self.deltaTarget)*(1-ivmRatio) return ratioSide+targetSide # return self.deltaTarget*self.putDeltaRatio def removeUninvestedOptions(self): for x in self.ActiveSecurities: if x.Value.Type == SecurityType.Option and x.Value.Invested == False: if self.callContract and x.Value.Symbol == self.callContract.Symbol: continue if self.putContract and x.Value.Symbol == self.putContract.Symbol: continue self.RemoveOptionContract(x.Value.Symbol) def notBuggyDay(self): return not (self.Time.year==2010 and self.Time.month==4 and self.Time.day==21) def grabIVWindow(self, key): if self.ObjectStore.ContainsKey(key) and not self.recordIVWindow: value=self.ObjectStore.Read(key) grabbedIVWindow = ast.literal_eval(value) for x in grabbedIVWindow: self.IVWindow.put(x) if len(list(self.IVWindow.queue))!=0: self.Debug("Successfully grabbed IVWindow from key: "+key)
#region imports from AlgorithmImports import * #endregion #Put all volatility info here # Your New Python File