Overall Statistics |
Total Trades 894 Average Win 0.39% Average Loss -0.33% Compounding Annual Return 32.137% Drawdown 16.400% Expectancy 0.359 Net Profit 82.647% Sharpe Ratio 1.623 Loss Rate 38% Win Rate 62% Profit-Loss Ratio 1.18 Alpha 0.238 Beta -0.001 Annual Standard Deviation 0.147 Annual Variance 0.022 Information Ratio 0.371 Tracking Error 0.182 Treynor Ratio -159.855 Total Fees $936.27 |
from System.Collections.Generic import List from QuantConnect.Data.UniverseSelection import * import operator from math import ceil,floor class CoarseFineFundamentalComboAlgorithm(QCAlgorithm): '''In this algorithm we demonstrate how to define a universe as a combination of use the coarse fundamental data and fine fundamental data''' def Initialize(self): self.SetStartDate(2012,01,02) #Set Start Date self.SetEndDate(2014,03,02) #Set End Date self.SetCash(50000) #Set Strategy Cash self.flag1 = 1 self.flag2 = 0 self.flag3 = 0 self.UniverseSettings.Resolution = Resolution.Daily # this add universe method accepts two parameters: # - coarse selection function: accepts an IEnumerable<CoarseFundamental> and returns an IEnumerable<Symbol> # - fine selection function: accepts an IEnumerable<FineFundamental> and returns an IEnumerable<Symbol> self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction) self.AddEquity("SPY") self.__numberOfSymbols = 200 self.__numberOfSymbolsFine = 20 self.num_portfolios = 5 self._changes = SecurityChanges.None self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY"), Action(self.Rebalancing)) # sort the data by daily dollar volume and take the top 'NumberOfSymbols' def CoarseSelectionFunction(self, coarse): if self.flag1: CoarseWithFundamental = [x for x in coarse if x.HasFundamentalData] sortedByDollarVolume = sorted(CoarseWithFundamental, key=lambda x: x.DollarVolume, reverse=True) # return the symbol objects of the top entries from our sorted collection top = sortedByDollarVolume[:self.__numberOfSymbols] # we need to return only the symbol objects list = List[Symbol]() for x in top: list.Add(x.Symbol) return list else: return(List[Symbol]()) def FineSelectionFunction(self, fine): if self.flag1: self.flag1 = 0 self.flag2 = 1 filtered_fine = [x for x in fine if x.ValuationRatios.PERatio and x.ValuationRatios.PriceChange1M and x.ValuationRatios.BookValuePerShare] sortedByfactor1 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.PERatio, reverse=False) sortedByfactor2 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.PriceChange1M, reverse=False) sortedByfactor3 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.BookValuePerShare, reverse=True) num_stocks = floor(len(filtered_fine)/self.num_portfolios)*self.num_portfolios stock_dict = {} for i,ele in enumerate(sortedByfactor1): rank1 = i rank2 = sortedByfactor2.index(ele) rank3 = sortedByfactor3.index(ele) score = [ceil(rank1/num_stocks),ceil(rank2/num_stocks),ceil(rank3/num_stocks)] score = sum(score) stock_dict[ele] = 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 xrange(len(self.sorted_stock))] # take the top entries from our sorted collection topFine = sorted_symbol[:self.__numberOfSymbolsFine] list = List[Symbol]() for x in topFine: list.Add(x.Symbol) self.flag3 = self.flag3 + 1 return list else: return (List[Symbol]()) def OnData(self, data): if self.flag3 > 0: if self.flag2 == 1: self.flag2 = 0 # if we have no changes, do nothing if self._changes == SecurityChanges.None: return # liquidate removed securities for security in self._changes.RemovedSecurities: if security.Invested: self.Liquidate(security.Symbol) for security in self._changes.AddedSecurities: self.SetHoldings(security.Symbol, 1/float(len(self._changes.AddedSecurities))) self._changes = SecurityChanges.None; # this event fires whenever we have changes to our universe def OnSecuritiesChanged(self, changes): self._changes = changes def Rebalancing(self): self.flag1 = 1