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()