Overall Statistics
class CalibratedUncoupledCoreWave(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019,1, 1)  # Set Start Date
        #self.SetEndDate(2016, 12, 12) # Set End Date
        self.SetCash(100000)  # Set Strategy Cash
        # Set the resolution of your data
        self.UniverseSettings.Resolution = Resolution.Minute
        # Add the universes
        self.AddUniverse(self.SelectCoarse,self.SelectFine)
        # Liquidate all positions before the market close each day
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Tuesday,DayOfWeek.Wednesday, DayOfWeek.Thursday,DayOfWeek.Friday), self.TimeRules.At(15, 30), self.ClosePositions)
        # Store yesterday's close in a dictionary for reference in the SelectFine Function
        self.coarseclose={}
        # Store yesterday's close on fine filtered stocks to reference them in the OnData function
        self.fineclose={}
        # Ensure only 1 trade per day per stock
        self.traded={}
        # Ensure each level of profit taking is only executed once per stock per day
        self.pt1={}
        self.pt2={}
        self.pt3={}
        self.pt4={}
        # Only enter a trade if today's price is above yesterday's close * self.targetentry
        self.targetentry=2.00


    def SelectCoarse(self, coarse):
        # Penny Stock filter
        myuniverse = [x for x in coarse if x.HasFundamentalData and x.DollarVolume > 1000000 \
        and x.DollarVolume < 5000000 and x.Price > 0 and x.Price <= 5.0]
        stocks = {x.Symbol: x for x in myuniverse} 
        # Clear the dictionary each day before re-populating it
        self.coarseclose.clear()
        # Load the dictionary with yesterday's close for each filtered stock
        for c in myuniverse:
            self.coarseclose[c.Symbol] = c.AdjustedPrice
        # Return filtered stocks for further filtering by the SelecFine function
        return list(stocks.keys())
        
    def SelectFine(self,fine):
        ''' 
        This function takes the stock of the CoarceFundamental function and narrow the list adding specific fundamental filters
        Largely to ensure that only common stock is traded and not EG Preference Shares or ETFs
            '''
        fine_filter = [x.Symbol for x in fine if x.SecurityReference.IsPrimaryShare == 1 and x.SecurityReference.SecurityType == 'ST00000001' and x.CompanyReference.IsLimitedPartnership == 0 and 
        x.SecurityReference.IsDepositaryReceipt == 0 ]
        self.fineclose.clear()
        self.traded.clear()
        self.pt1.clear()
        self.pt2.clear()
        self.pt3.clear()
        self.pt4.clear()
        self.pt1={k: 0 for k in fine_filter}
        self.pt2={k: 0 for k in fine_filter}
        self.pt3={k: 0 for k in fine_filter}
        self.pt4={k: 0 for k in fine_filter}
        self.fineclose = {k: self.coarseclose[k] for k in fine_filter}
        self.traded = {k: 0 for k in fine_filter}
        return fine_filter
        
    def OnData(self, data):
        '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        Arguments:
            data: Slice object keyed by symbol containing the stock data
        '''

        for kvp in data.Bars:
            symbol = kvp.Key
            close = kvp.Value.Close
            dollarvolume=kvp.Value.Close*kvp.Value.Volume
            if kvp.Key in self.fineclose.keys():
                target =self.fineclose[kvp.Key]*self.targetentry
            if self.Portfolio[symbol].Quantity == 0.0:
                if kvp.Key in self.traded.keys():
                    if self.traded[symbol] == 0:
                        if close>=target:
                            if self.Time.hour <= 10 and self.Time.minute <=29:
                                if dollarvolume >= 50000:
                                   self.traded[symbol]=1
                               #self.SetHoldings(symbol, (min(1/len(self.traded),0.01)))
                                   self.SetHoldings(symbol,0.01 )
            if self.Portfolio[symbol].Invested:
                cost = round(self.Portfolio[symbol].AveragePrice,3)
                profittarget1 = cost * 1.05
                profittarget2 = cost * 1.10
                profittarget3 = cost * 1.15
                profittarget4 = cost * 1.20
                stoploss = cost * 0.95
                quantity=self.Portfolio[symbol].Quantity
                if self.Time.hour <= 15 and self.Time.minute <=29:
                    if close>= profittarget1 and self.pt1[symbol] == 0:
                        self.MarketOrder(symbol, -(quantity*0.25))
                        self.pt1[symbol] = 1
                    if close>= profittarget2 and self.pt2[symbol] == 0:
                        self.MarketOrder(symbol, -(quantity*0.33))
                        self.pt2[symbol] = 1
                    if close>= profittarget3 and self.pt3[symbol] == 0:
                        self.MarketOrder(symbol, -(quantity*0.50))
                        self.pt3[symbol] = 1
                    if close>= profittarget4 and self.pt4[symbol] == 0:
                        self.Liquidate()
                        self.pt4[symbol] = 1
                if self.Time.hour <= 15 and self.Time.minute <=29:
                    if (close <= stoploss):self.Liquidate()

    def ClosePositions(self):        
            if self.Portfolio.Invested:
                self.Liquidate()