Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-0.325
Tracking Error
0.196
Treynor Ratio
0
Total Fees
$0.00
#https://www.quantconnect.com/forum/discussion/3377/momentum-strategy-with-market-cap-and-ev-ebitda/p1
#https://www.quantconnect.com/docs/algorithm-reference/universes#Universes-Coarse-Universe-Selection
#https://www.quantconnect.com/forum/discussion/6485/onsecuritieschanged-questions/p1
#https://www.quantconnect.com/lean/documentation/topic23824.html
#https://www.quantconnect.com/lean/documentation/topic19223.html
#https://www.quantconnect.com/docs/data-library/fundamentals#Fundamentals-Asset-Classification
#https://www.quantconnect.com/lean/documentation/topic7404.html
#https://www.quantconnect.com/forum/discussion/2460/operation-ratios-aren-039-t-working-in-backtest/p1
#https://github.com/QuantConnect/Lean/blob/cbd953437f987392f2c2e154adcb7d43d684b7f1/Algorithm.Python/EmaCrossUniverseSelectionAlgorithm.py
#https://www.quantconnect.com/forum/discussion/9809/stock-age-time-in-portfolio/p1
#https://www.quantconnect.com/forum/discussion/9620/morningstar-grades-and-scores/p1
#https://www.quantconnect.com/forum/discussion/3792/how-many-stocks-do-i-hold/p1
#https://www.quantconnect.com/forum/discussion/7825/portfolio-properties/p0
#https://www.quantconnect.com/forum/discussion/2386/quot-runtime-error-039-039-wasn-039-t-found-in-the-tradebars-object-quot-when-dealing-with-universe-of-stocks

import pandas as pd
class GrowthStockswithHighRevenue(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 9, 1) 
        self.SetEndDate(2020, 11, 22) 
        self.SetCash(100000)
        self.SetBenchmark("SPY")
        self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
        self.max_holdings = 5   # Number of holdings we want in portfolio
        
        #selection filter variables
        self.min_price = 5
        self.min_vol_per_day = 50000
        self.max_shares_outstanding = 50000000
        self.min_growth_score = 60
        self.min_revenue_growth = .10
        self.max_revenue_growth = .60
        self.num_coarse = 100   # Number of symbols selected at Coarse Selection
        self.num_fine = 20      # Number of symbols selected at Fine Selection
        
        #indictor variables
        self.mom = {}           # Dict of Momentum indicator keyed by Symbol
        self.lookback = 45      # Momentum indicator lookback period
        self.longs = []
        
        self.fundamentals_df=pd.DataFrame(columns=['symbol','growth_score'])
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverse(self.Coarse, self.Fine)
        
        self.Schedule.On(self.DateRules.EveryDay("SPY"),
            self.TimeRules.AfterMarketOpen(self.spy, 10),
            self.EveryDayAfterMarketOpen)
       
    def Coarse(self, coarse):
        selected = sorted([x for x in coarse if x.HasFundamentalData and x.Price > self.min_price and x.Volume > self.min_vol_per_day],
            key=lambda x: x.DollarVolume, reverse=True)
        return [x.Symbol for x in selected[:self.num_coarse]]    
      
    def Fine(self, fine):
        fine = [f for f in fine if f.ValuationRatios.PERatio > 0
                               and f.EarningReports.BasicEPS.TwelveMonths > 0
                               and f.EarningReports.BasicAverageShares.ThreeMonths > 0
                               and f.AssetClassification.GrowthScore >  self.min_growth_score
                               and f.OperationRatios.RevenueGrowth.Value >  self.min_revenue_growth
                               and f.OperationRatios.RevenueGrowth.Value <  self.max_revenue_growth
                               and f.ValuationRatios.FCFYield > 0
                               and f.EarningReports.BasicAverageShares.ThreeMonths < self.max_shares_outstanding]

        selected = sorted(fine,key=lambda f: f.AssetClassification.GrowthScore,reverse=True)
        return [x.Symbol for x in selected[:self.num_fine]]
    
    #-----------------------------------------------------------------------------------------  
    def OnSecuritiesChanged(self, changes): 
        self.Log('--OnSecuritiesChanged--')
        
        for security in changes.RemovedSecurities:
            symbol = security.Symbol
        self.Log('Removed from universe ' + str(len(changes.RemovedSecurities)))

        for security in changes.AddedSecurities:
            symbol = security.Symbol
            #these symbols we want to buy or do further interrogation on
            #df = df.append({'returns': 25, 'symbol': 'XXX', 'trend': 0} , ignore_index=True)
        self.Log('Add to universe ' + str(len(changes.AddedSecurities)))
            
        for security in self.ActiveSecurities:
            self.Log("Security: " + str(security.Key))
        self.Log("Universe: " + str(len(self.ActiveSecurities)))
        
    def OnData(self, data): 
        #self.Log('--OnData--')
        if self.IsWarmingUp:
            return
        
    def EveryDayAfterMarketOpen(self):
        holdings=0
        holdings = self.portfolio_holdings(False)   #get count of current holdings
        #for symbol in self.ActiveSecurities.Keys:
        #    if (holdings < self.max_holdings):
        #        self.SetHoldings(symbol, 1/ self.max_holdings)
        pass
        #self.Log("EveryDay.SPY 10 min after open: Fired at: {0}".format(self.Time))
        
    def OnEndOfAlgorithm(self):
        self.portfolio_holdings(True)  #print out holdings  
    
    def portfolio_holdings(self, print_it): 
        #return count of holdings and print if print_it is true 
        i1=0
        if (print_it):
            self.Log("-- Portfolio --")
        for kvp in self.Portfolio:
            if kvp.Value.Invested:
                holding = kvp.Value
                symbol = holding.Symbol.Value
                quantity = holding.Quantity
                avgprice = holding.AveragePrice
                price = self.Securities[symbol].Price
                net = ((price - avgprice) / avgprice) * 100
                s1 = '{:3.2f}'.format(avgprice) + ',' + '{:3.2f}'.format(price) + ',' + '{:3.2f}'.format(net)
                i1=i1+1
                if (print_it):
                    self.Log(symbol + "," + str(quantity) + "," + s1)
        return(i1)