Overall Statistics |
Total Trades 39440 Average Win 0.01% Average Loss -0.01% Compounding Annual Return -3.207% Drawdown 24.300% Expectancy -0.064 Net Profit -16.645% Sharpe Ratio -0.302 Probabilistic Sharpe Ratio 0.007% Loss Rate 45% Win Rate 55% Profit-Loss Ratio 0.69 Alpha -0.018 Beta -0.022 Annual Standard Deviation 0.066 Annual Variance 0.004 Information Ratio -0.624 Tracking Error 0.17 Treynor Ratio 0.897 Total Fees $125321.13 Estimated Strategy Capacity $5000.00 Lowest Capacity Asset HHS R735QTJ8XC9X |
#region imports from AlgorithmImports import * #endregion # https://quantpedia.com/Screener/Details/199 class ROAEffectWithinStocks(QCAlgorithm): def Initialize(self): self.SetStartDate(2015, 1, 1) self.SetEndDate(2020, 8, 1) self.SetCash(10000000) self.UniverseSettings.Resolution = Resolution.Daily self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction) self.AddEquity("SPY", Resolution.Daily) self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY"), self.Rebalance) self.monthly_rebalance = False self.coarse = False def CoarseSelectionFunction(self, coarse): if self.monthly_rebalance: self.coarse = True filteredCoarse = [x.Symbol for x in coarse if x.HasFundamentalData] return filteredCoarse else: return Universe.Unchanged def FineSelectionFunction(self, fine): if self.monthly_rebalance: fine =[i for i in fine if i.EarningReports.BasicAverageShares.ThreeMonths != 0 and i.EarningReports.BasicEPS.TwelveMonths != 0 and i.ValuationRatios.PERatio != 0 # sales is greater than 10 million and i.ValuationRatios.SalesPerShare*i.EarningReports.DilutedAverageShares.Value > 10000000 and i.OperationRatios.ROA.Value != 0] # sort into 2 halfs based on market capitalization sorted_market_cap = sorted(fine, key = lambda x:x.MarketCap, reverse=True) top = sorted_market_cap[:int(len(sorted_market_cap)*0.5)] bottom = sorted_market_cap[-int(len(sorted_market_cap)*0.5):] # each half is then divided into deciles based on Return on Assets (ROA) sortedTopByROA = sorted(top, key = lambda x: x.OperationRatios.ROA.Value, reverse = True) sortedBottomByROA = sorted(bottom, key = lambda x: x.OperationRatios.ROA.Value, reverse = True) # long top decile from each market capitalization group long_ = sortedTopByROA[:int(len(sortedTopByROA)*0.1)] + sortedBottomByROA[:int(len(sortedTopByROA)*0.1)] self.longStocks = [i.Symbol for i in long_] # short bottom decile from each market capitalization group short = sortedTopByROA[-int(len(sortedTopByROA)*0.1):] + sortedBottomByROA[-int(len(sortedTopByROA)*0.1):] self.shortStocks = [i.Symbol for i in short] return self.longStocks + self.shortStocks else: return Universe.Unchanged def Rebalance(self): self.monthly_rebalance = True def OnData(self, data): if not (self.monthly_rebalance and self.coarse): return self.coarse = False self.monthly_rebalance = False stocks_invested = [x.Key for x in self.Portfolio if x.Value.Invested] for i in stocks_invested: if i not in self.longStocks+self.shortStocks: self.Liquidate(i) long_weight = 0.5/len(self.longStocks) for i in self.longStocks: self.SetHoldings(i, long_weight) short_weight = 0.5/len(self.shortStocks) for i in self.shortStocks: self.SetHoldings(i, -short_weight)