Overall Statistics |
Total Trades 473 Average Win 0.21% Average Loss -0.20% Compounding Annual Return 1.833% Drawdown 18.100% Expectancy 0.018 Net Profit 2.132% Sharpe Ratio 0.158 Probabilistic Sharpe Ratio 15.866% Loss Rate 50% Win Rate 50% Profit-Loss Ratio 1.05 Alpha -0.03 Beta 0.996 Annual Standard Deviation 0.162 Annual Variance 0.026 Information Ratio -0.51 Tracking Error 0.06 Treynor Ratio 0.026 Total Fees $477.83 |
from math import ceil,floor class CoarseFineFundamentalComboAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2018,1,2) # Set Start Date self.SetEndDate(2019,3,2) # Set End Date self.SetCash(50000) # Set Strategy Cash self.AddUniverseSelection( FineFundamentalUniverseSelectionModel(self.CoarseSelectionFunction, self.FineSelectionFunction) ) self.AddAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(30))) self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel(lambda time:None)) self.AddEquity("SPY") self.numberOfSymbols = 100 self.numberOfSymbolsFine = 10 self.num_portfolios = 6 self.rmvd_symbols = [] self.readded_symbols = [] self.rermvd_symbols = [] self.curr_month = self.Time.month def OnSecuritiesChanged(self, changes): for security in changes.AddedSecurities: if security.Symbol in self.rmvd_symbols: self.readded_symbols.append(security.Symbol) for security in changes.RemovedSecurities: self.rmvd_symbols.append(security.Symbol) if security.Symbol in self.readded_symbols: self.rermvd_symbols.append(security.Symbol) self.Debug(f"{self.Time.date()} | readded symbols: {[str(x.Value) for x in self.readded_symbols][:5]}. ") self.Debug(f"{self.Time.date()} | reremoved symbols: {[str(x.Value) for x in self.rermvd_symbols][:5]}. ") def CoarseSelectionFunction(self, coarse): if self.curr_month == self.Time.month: return Universe.Unchanged self.curr_month = self.Time.month CoarseWithFundamental = [x for x in coarse if x.HasFundamentalData] sortedByDollarVolume = sorted(CoarseWithFundamental, key=lambda x: x.DollarVolume, reverse=True) top = sortedByDollarVolume[:self.numberOfSymbols] return [i.Symbol for i in top] def FineSelectionFunction(self, fine): filtered_fine = [x for x in fine if x.EarningReports.TotalDividendPerShare.ThreeMonths and x.ValuationRatios.PriceChange1M and x.ValuationRatios.BookValuePerShare and x.ValuationRatios.FCFYield] sortedByfactor1 = sorted(filtered_fine, key=lambda x: x.EarningReports.TotalDividendPerShare.ThreeMonths, reverse=True) sortedByfactor2 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.PriceChange1M, reverse=False) sortedByfactor3 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.BookValuePerShare, reverse=True) sortedByfactor4 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.FCFYield, reverse=True) num_stocks = floor(len(filtered_fine)/self.num_portfolios) stock_dict = {} for i,ele in enumerate(sortedByfactor1): rank1 = i rank2 = sortedByfactor2.index(ele) rank3 = sortedByfactor3.index(ele) rank4 = sortedByfactor4.index(ele) score = [ceil(rank1/num_stocks), ceil(rank2/num_stocks), ceil(rank3/num_stocks), ceil(rank4/num_stocks)] score = sum(score) stock_dict[ele] = score #self.Log("score" + str(score)) self.sorted_stock = sorted(stock_dict.items(), key=lambda d:d[1],reverse=True) sorted_symbol = [self.sorted_stock[i][0] for i in range(len(self.sorted_stock))] topFine = sorted_symbol[:self.numberOfSymbolsFine] return [i.Symbol for i in topFine]