Overall Statistics Total Trades1334Average Win1.14%Average Loss-0.83%Compounding Annual Return19.210%Drawdown33.700%Expectancy0.274Net Profit332.724%Sharpe Ratio0.78Probabilistic Sharpe Ratio18.432%Loss Rate46%Win Rate54%Profit-Loss Ratio1.37Alpha0.018Beta1.312Annual Standard Deviation0.242Annual Variance0.058Information Ratio0.417Tracking Error0.141Treynor Ratio0.144Total Fees\$3779.06
import operator
from math import ceil,floor

class CoarseFineFundamentalComboAlgorithm(QCAlgorithm):

def Initialize(self):

self.SetStartDate(2009,1,2)  # Set Start Date
self.SetEndDate(2017,5,2)    # Set End Date
self.SetCash(50000)          # Set Strategy Cash
self.flag1 = 1
self.flag2 = 0
self.flag3 = 0
self.last_rebalance=self.Time
self.UniverseSettings.Resolution = Resolution.Minute
self.numberOfSymbols = 300
self.numberOfSymbolsFine = 10
self.num_portfolios = 6
self._changes = None
self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY"), Action(self.Rebalancing))

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)
top = sortedByDollarVolume[:self.numberOfSymbols]
selection=[i.Symbol for i in top]
return selection
else:
return []

def FineSelectionFunction(self, fine):
if self.flag1:
self.flag1 = 0
self.flag2 = 1

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]

self.flag3 = self.flag3 + 1
selection=[i.Symbol for i in topFine]
tickers=[i.Value for i in selection]

return selection

else:
return []

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 == None: return
# liquidate removed securities
for security in self._changes.RemovedSecurities:
if security.Invested:
self.Liquidate(security.Symbol)

self.flag1 = 1