Overall Statistics
Total Trades
2170
Average Win
0.02%
Average Loss
-0.01%
Compounding Annual Return
-0.867%
Drawdown
2.000%
Expectancy
-0.265
Net Profit
-1.851%
Sharpe Ratio
-2.824
Probabilistic Sharpe Ratio
0.000%
Loss Rate
79%
Win Rate
21%
Profit-Loss Ratio
2.48
Alpha
-0.007
Beta
0.001
Annual Standard Deviation
0.003
Annual Variance
0
Information Ratio
-0.554
Tracking Error
0.227
Treynor Ratio
-5.03
Total Fees
$4495.99
class ResistanceVentralCircuit(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2018, 6, 17)  # Set Start Date
        self.SetCash(1000000)  # Set Strategy Cash
        
        self.symbol = self.AddEquity('SPY', Resolution.Minute).Symbol
        
        self.UniverseSettings.Resolution = Resolution.Minute
        self.AddUniverse(self.CoarseFilter)
        
        self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.BeforeMarketClose(self.symbol, 10), self.BeforeClose)

        self.num_securities = 50
        
        self.Gaps = {}
        
        self.curr_day = -1
        
        self.days = 0
        self.symbols = None

    def CoarseFilter(self, coarse):
        if self.days % 7 == 0:
            sortedByDollarVolume = sorted(coarse, key=lambda c: c.DollarVolume, reverse=True)[:self.num_securities]
            self.symbols = [x.Symbol for x in sortedByDollarVolume]
        self.days += 1
        return self.symbols
    
    def OnData(self, data):
        if not self.IsMarketOpen(self.symbol):
            return
        
        # get current day open
        if self.curr_day != self.Time.day:
            for symbol in self.Gaps:
                self.Gaps[symbol].StopTrading = False
                self.Gaps[symbol].MadeTrade = False
                if data.ContainsKey(symbol) and data[symbol] is not None:
                    self.Gaps[symbol].Open = data[symbol].Close
                else:
                    self.Gaps[symbol].Open = -1
            self.curr_day = self.Time.day
      
        for symbol, gap in self.Gaps.items():
            if gap.StopTrading:
                continue
            # if we don't have sufficient data, don't trade
            elif gap.Open < 0 or gap.Close < 0:
                gap.StopTrading = True
                continue
            # if gap down doesn't meet our -1% threshold, don't trade
            elif gap.Open / gap.Close > .99:
                gap.StopTrading = True
                continue
            # elif not data.ContainsKey(symbol) or data[symbol] is None:
            #     continue
            else:
                curr_price = data[symbol].Close
                
                # breakout past yesterday's close
                if not gap.MadeTrade and curr_price > gap.Close:
                    self.SetHoldings(symbol, .02)
                    #self.MarketOrder(symbol, 1)
                    gap.MadeTrade = True
                
                elif gap.MadeTrade and (curr_price < gap.Close or curr_price > 1.01 * gap.Close):
                    self.Liquidate(symbol)
                    gap.StopTrading = True
        
    def BeforeClose(self):
        self.Liquidate()
        for symbol in self.Gaps:
            if self.CurrentSlice.ContainsKey(symbol) and self.CurrentSlice[symbol] is not None:
                self.Gaps[symbol].Close = self.Securities[symbol].Price
            else:
                self.Gaps[symbol].Close = -1
            self.Gaps[symbol].StopTrading = True
            
    def OnSecuritiesChanged(self, changed):
        for security in changed.RemovedSecurities:
            self.Gaps.pop(security.Symbol)
        
        for security in changed.AddedSecurities:
            self.Gaps[security.Symbol] = Gap()
        
class Gap:
    def __init__(self):
        self.Close = -1
        self.Open = -1
        self.MadeTrade = False
        self.StopTrading = False