Overall Statistics
Total Trades
6
Average Win
0%
Average Loss
-0.34%
Compounding Annual Return
-71.573%
Drawdown
1.000%
Expectancy
-1
Net Profit
-1.028%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
100%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-18.527
Tracking Error
0.087
Treynor Ratio
0
Total Fees
$6.00
Estimated Strategy Capacity
$15000000.00
'''
Gap and Go Strategy 
-calculate best support options and weight for each
    -make sure supports are different
-take profit:
    -New 1 min candle to make new low
        -Add a buffer (.03?)
    -at a certain level
-Stop loss
    -Change from trailing to next support level below
-Liquidate after 90 min
-Relative vol filter?
'''
class MeasuredRedSalmon(QCAlgorithm):
    
    success_count = 1
    loss_count = 1
    success_countt = 1
    loss_countt = 1
        
    def Initialize(self):
        self.SetStartDate(2021, 3, 10)  # Set Start Date
        self.SetEndDate(2021, 3, 12)
        self.SetCash(100000)  # Set Strategy Cash
        #self.nvx = self.AddEquity("NVAX", Resolution.Minute, Market.USA, True, 1.0, True)
        self.spy = self.AddEquity("SPY", Resolution.Minute, Market.USA, True, 1.0, True)
        
        self.UniverseSettings.Resolution = Resolution.Minute
        self.UniverseSettings.ExtendedMarketHours = True
        
        self.AddUniverse(self.Coarse, self.Fine)
        
        self.SetRiskManagement(MaximumDrawdownPercentPerSecurity(0.05))
        
        self.Schedule.On(self.DateRules.EveryDay("SPY"),
                 self.TimeRules.AfterMarketOpen("SPY", 0),
                 self.collectPreMarketData)
                 
        self.Schedule.On(self.DateRules.EveryDay("SPY"),
                 self.TimeRules.AfterMarketOpen("SPY", 1),
                 self.trackMarket)
                 
        self.Schedule.On(self.DateRules.EveryDay("SPY"),
                 self.TimeRules.AfterMarketOpen("SPY", 90),
                 self.endMarket)
                 
        self.Schedule.On(self.DateRules.EveryDay("SPY"),
                 self.TimeRules.AfterMarketOpen("SPY", 100),
                 self.LiquidatePositions)
        
        self.isPreMarket = False
        self.isMarket = False
        self.lastPrePrice = -1
        self.highestPreMarket = 0
        self.yesterday = -1
        self.isGapped = False
        self.maxTraded = 5
        self.securityWeight = .2
        self.lastMonth = -1
        self.activeSecurities = {}
        self.tradedToday = []
        self.tradingSecurities = {}
        self.oneMinuteHigh = {}
        self.quarterPositions = {}
        self.oneMinuteLow = {}

        
        
        self.SetWarmUp(timedelta(days = 2))
        
    def endMarket(self):
        self.isMarket = False
        self.tradedToday = []
        self.tradingSecurities = {}
        self.oneMinuteHigh

    def trackMarket(self):
        sortedByGap = [x for x in self.activeSecurities.keys()]
        gapPercentBySymbol = {x.Symbol:x.isGapPercent for x in self.activeSecurities.values()}
        sortedByGap = sorted(sortedByGap, key = lambda x: self.activeSecurities[x].isGapPercent, reverse = True)
        
        finalGap = sortedByGap[:self.maxTraded]
        for symbol in finalGap:
            self.tradingSecurities[symbol] = self.activeSecurities[symbol]
            self.oneMinuteHigh[symbol] = self.Securities[symbol].High
            
        self.isMarket = True
            
    def collectPreMarketData(self):
        remove = []
        
        for symbol, symbolData in self.activeSecurities.items():
            symbolData.Open = self.Securities[symbol].Price
            historyMinute = self.History(symbol, 180, Resolution.Minute)
            historyDay = self.History(symbol, 1, Resolution.Daily)
            try:
                symbolData.YesterdayClose = float(historyDay["close"])
            except:
                remove.append(symbol)
                continue
            preMarketHigh = -1
            support1 = 100000
            support2 = 100000
            support3 = 100000
            counter = 0
            premarketvol = 0
            
            for tuple in historyMinute.itertuples():
                premarketvol = premarketvol + tuple.volume
                
                
                if tuple.close > preMarketHigh:
                    preMarketHigh = tuple.close
                if tuple.close < support1:
                    support1 = tuple.close
                if counter >= 100:
                    if tuple.close < support2:
                        support2 = tuple.close
                if counter >= 150:
                    if tuple.close < support3:
                        support3 = tuple.close
                counter += 1
            
            if support1 <= support2 and support1 <= support3:
                lowest_support = support1
                if support2 <= support3:
                    mid_support = support2
                    high_support = support3
                else:
                    mid_support = support3
                    high_support = support2   
            if support2 < support1 and support2 <= support3:
                lowest_support = support2
                if support1 <= support3:
                    mid_support = support1
                    high_support = support3
                else:
                    mid_support = support3
                    mid_support = support1
            if support3 < support1 and support3 < support2:
                lowest_support = support3
                if support1 <= support2:
                    mid_support = support1
                    high_support = support3
                else:
                    mid_support= support3
                    high_support = support1
            
            symbolData.support1 = lowest_support
            symbolData.support2 = mid_support
            symbolData.support3 = high_support
            symbolData.firstSupportBroke = False
            symbolData.secondSupportBroke = False
            symbolData.thirdSupportBroke = False
            symbolData.AlreadyBrokeOut = False
            symbolData.preMarketHigh = preMarketHigh
            
            if symbolData.Open >= symbolData.YesterdayClose*1.03:
                symbolData.isGap = True
            else:
                symbolData.isGap = False
                
            if premarketvol <= 1000000:
                remove.append(symbol)
                
            symbolData.isGapPercent = (symbolData.Open - symbolData.YesterdayClose) / symbolData.YesterdayClose


        for symbol in remove:
            self.activeSecurities.pop(symbol, None)
            self.Liquidate(symbol)
            self.RemoveSecurity(symbol)
            
    def LiquidatePositions(self):
        self.Liquidate()
    
            
    def OnData(self, data):
        
        if self.isMarket == True:
            for symbol, symbolData in self.tradingSecurities.items():
                if symbolData.isGap == True:
                    if len([x for x in self.Portfolio if x.Value.Invested]) >= self.maxTraded:
                        break
                    
                    if self.Portfolio[symbol].Invested:
                        if symbolData.AlreadyBrokeOut == False and self.Securities[symbol].Price >= symbolData.preMarketHigh:
                            self.SetHoldings([PortfolioTarget(symbol, self.securityWeight)])
                            self.oneMinuteLow[symbol] = self.Securities[symbol].Low
                            symbolData.AlreadyBrokeOut = True
                    
                    if not self.Portfolio[symbol].Invested and symbol not in self.tradedToday:
                        if self.Securities[symbol].Price <= symbolData.support1:
                            symbolData.firstSupportBroke = True
                        if self.Securities[symbol].Price <= symbolData.preMarketHigh:
                            symbolData.secondSupportBroke = True
                            
                        if symbolData.firstSupportBroke == True and self.Securities[symbol].Price >= symbolData.support1:
                            self.SetHoldings([PortfolioTarget(symbol, self.securityWeight/2)])
                            self.oneMinuteLow[symbol] = self.Securities[symbol].Low
                            self.tradedToday.append(symbol)
                            self.Log(str(symbol) + "support1 = " + str(symbolData.support1))
                            self.Log(str(symbol) + "PreMarketHigh = " + str(symbolData.preMarketHigh))
                            
                        if symbolData.secondSupportBroke == True and self.Securities[symbol].Price >= symbolData.preMarketHigh:
                            self.SetHoldings([PortfolioTarget(symbol, self.securityWeight/2)])
                            self.tradedToday.append(symbol)
                            self.oneMinuteLow[symbol] = self.Securities[symbol].Low
                            symbolData.AlreadyBrokeOut = True
#                            if symbol in self.quarterPositions:
#                                self.quarterPositions.pop(symbol, None)

   
                        continue
                        
                       
 #                           if symbol not in self.quarterPositions:
 #                               self.quarterPositions[symbol] = self.securityWeight/4
 #                           else:
 #                               self.quarterPositions[symbol] += self.securityWeight/4
 #                               
 #                           if self.quarterPositions[symbol] >=1:
 #                               continue
                            
                    self.oneMinuteHigh[symbol] = self.Securities[symbol].High
                    
            self.manageProfit()
            self.oneMinuteLow[symbol] = self.Securities[symbol].Low
            
    def manageProfit(self):
        investedSecurities = [x.Key for x in self.Portfolio if x.Value.Invested]
        for symbol, symbolData in self.activeSecurities.items():
            if self.Portfolio[symbol].Invested and (self.Securities[symbol].Price <= symbolData.preMarketHigh) and (self.Securities[symbol].Price <= self.oneMinuteLow[symbol]) and (self.Securities[symbol].Price > symbolData.support1):
                self.Liquidate(symbol, "PROFIT for Support 1")
                self.Log("Support success count = " + str(self.success_count))
                self.success_count = self.success_count + 1
            elif self.Portfolio[symbol].Invested and self.Securities[symbol].Price <= symbolData.support1:
                self.Liquidate(symbol, "Hit Support 1")
                self.Log("Support loss count = " + str(self.loss_count))
                self.loss_count = self.loss_count + 1
            
            continue
            
            if self.Portfolio[symbol].Invested and self.Securities[symbol].Price >= symbolData.preMarketHigh and (self.Securities[symbol].Price <= self.oneMinuteLow[symbol]):
                self.Liquidate(symbol, "PROFIT High")
                self.Log("PMH success count = " + str(self.success_countt))
                self.success_countt = self.success_countt + 1
                
            elif self.Portfolio[symbol].Invested and self.Securities[symbol].Price >= symbolData.preMarketHigh and (self.Securities[symbol].Price <= self.oneMinuteLow[symbol]):
                self.Liquidate(symbol, "Hit High Support")
                self.Log("PMH loss count = " + str(self.loss_countt))
                self.loss_countt = self.loss_countt + 1
                
#            if self.Portfolio[symbol].Invested and (self.Securities[symbol].Holdings.UnrealizedProfitPercent > 0.02):
#                self.Liquidate(symbol, "PROFIT")
            
            
            
                    
    def OnSecuritiesChanged(self, changes):
        addedSecurities = [x.Symbol for x in changes.AddedSecurities]
        removedSecurities = [x.Symbol for x in changes.RemovedSecurities]
        
        for symbol in addedSecurities:
            if symbol == self.spy.Symbol:
                continue
            
            symbolData = SymbolData(symbol)
            self.activeSecurities[symbol] = symbolData
            
        for symbol in removedSecurities:
            if symbol in self.activeSecurities:
                self.activeSecurities.pop(symbol, None)
            if self.Portfolio[symbol].Invested:
                self.Liquidate(symbol)
                
 #       self.securityWeight = 1/self.maxTraded
    
    def Coarse(self, coarse):
        if self.lastMonth == self.Time.month:
            return Universe.Unchanged
        self.lastMonth = self.Time.month
        
        selectedCoarse = [x for x in coarse if x.HasFundamentalData and x.Price > 40 and x.Volume > 1000000]
        
        self.dollarVolumeBySymbol = {x.Symbol:x.Volume for x in selectedCoarse}

        # If no security has met the QC500 criteria, the universe is unchanged.
        # A new selection will be attempted on the next trading day as self.lastMonth is not updated
        if len(self.dollarVolumeBySymbol) == 0:
            return Universe.Unchanged
        
        return [x.Symbol for x in selectedCoarse]
        
    def Fine(self, fine):
        
        sortedByVolume = sorted([x.Symbol for x in fine if x.CompanyReference.CountryId == "USA"
                                        and x.CompanyReference.PrimaryExchangeID in ["NYS","NAS"]],
                               key = lambda x: self.dollarVolumeBySymbol[x], reverse=True)
                               
        count = len(sortedByVolume)
        if count == 0:
            return Universe.Unchanged
        
        return sortedByVolume[:500]
        
class SymbolData:
    def __init__(self, symbol):
        
        self.Open = -1
        self.YesterdayClose = -1
        self.preMarketHigh = -1
        self.isGap = False
        self.Symbol = symbol
        self.isGapPercent = 0.0
        self.support1 = 0
        self.support2 = 0
        self.support3 = 0
        self.firstSupportBroke = False
        self.secondSupportBroke = False
        self.thirdSupportBroke = False
        self.AlreadyBrokeOut = False