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