Overall Statistics |
Total Trades 1012 Average Win 0.82% Average Loss -0.91% Compounding Annual Return -36.080% Drawdown 41.500% Expectancy -0.087 Net Profit -36.158% Sharpe Ratio -1.169 Probabilistic Sharpe Ratio 0.755% Loss Rate 52% Win Rate 48% Profit-Loss Ratio 0.90 Alpha -0.344 Beta 0.166 Annual Standard Deviation 0.284 Annual Variance 0.08 Information Ratio -1.337 Tracking Error 0.302 Treynor Ratio -1.994 Total Fees $2877.51 |
class FadingTheGap(QCAlgorithm): def Initialize(self): #Backtesting parameters self.SetStartDate(2017, 11, 1) self.SetEndDate(2018, 11, 1) self.SetCash(100000) self.minimumDollar = 100 self.maximumDollar = 5000 self.topVolume = 100 # Universe Settings self.UniverseSettings.Resolution = Resolution.Minute self.AddUniverse(self.CoarseSelectionFunction) # Securities list that is dynamically changes by the universe coarse filter self.SecuritiesList = [] # Schedules self.AddEquity("SPY", Resolution.Minute) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen("SPY", 1), self.OpeningBar) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen("SPY", 45), self.ClosePositions) def CoarseSelectionFunction(self, coarse): # Sort equities by volume - highest volume first sortedByDollarVolume = sorted(coarse, key=lambda c: c.DollarVolume, reverse=True) # Filter equities by price filteredByPrice = [c.Symbol for c in sortedByDollarVolume if c.Price > self.minimumDollar and c.Price < self.maximumDollar] # Retrieve top equities self.SecuritiesList = filteredByPrice[:self.topVolume] return self.SecuritiesList def OpeningBar(self): securityDelta = {} securitySTD = {} securityDeviations = {} # Go through all the top traded securities of the day for symbol in self.SecuritiesList: # Retrieve the previous closing price of those securities history = self.History(symbol, 2, Resolution.Daily) if history.empty: continue previousClose = history.iloc[len(history.index) - 2]['close'] if previousClose <= 0: continue # Retrieve the current day open of the same securities if not self.Securities.ContainsKey(symbol): continue if self.Securities[symbol] is None: continue if self.Securities[symbol].Open <= 0: continue currentOpen = self.Securities[symbol].Open delta = 0 if currentOpen < previousClose: # Record the delta if the open is less than the previous close in securityDelta dictionary delta = currentOpen - previousClose else: continue # Retrieve the standard deviation of the security for the past 60 minutes velocityHistory = self.History(symbol, 60, Resolution.Minute) std = velocityHistory.loc[:, 'close'].std() # Calculate and record the deviation if it is 3 deviations away # 68% (1 sigma deviation) # 95% (2 sigma deviation) # 99.7% (3 sigma deviation) # < -3 says that the drop is a .3% deviation deviation = delta / std if deviation < -3: securityDeviations[symbol] = deviation self.Log(deviation) if len(securityDeviations) > 0: # Sort any notable deviations by ascending order - strongest deviations first sortedDeviations = sorted(securityDeviations.items(), key=lambda x: x[1]) # Retrieve the top two winners topDeviations = sortedDeviations[:2] # Invest 100% in the security with the biggest deviation for security in topDeviations: self.SetHoldings(security[0], 1) def ClosePositions(self): self.Liquidate()