| Overall Statistics |
|
Total Trades 10001 Average Win 0.04% Average Loss -0.03% Compounding Annual Return 2.659% Drawdown 12.900% Expectancy 0.120 Net Profit 18.544% Sharpe Ratio 0.568 Loss Rate 52% Win Rate 48% Profit-Loss Ratio 1.32 Alpha -0.006 Beta 1.695 Annual Standard Deviation 0.04 Annual Variance 0.002 Information Ratio 0.15 Tracking Error 0.04 Treynor Ratio 0.013 Total Fees $10683.04 |
import operator
from math import ceil,floor
class CoarseFineFundamentalComboAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2000,9,9) # Set Start Date
self.SetEndDate(2018,9,9) # Set End Date
self.SetCash(100000) # Set Strategy Cash
self.flag1 = 1
self.flag2 = 0
self.flag3 = 0
self.UniverseSettings.Resolution = Resolution.Minute
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
self.AddEquity("SPY")
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))
self.window = RollingWindow[TradeBar](2)
self.SetWarmUp(20)
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]
return [i.Symbol for i in top]
else:
return []
def FineSelectionFunction(self, fine):
if self.flag1:
self.flag1 = 0
self.flag2 = 1
filtered_fine = [x for x in fine if x.FinancialStatements.IncomeStatement.EBIT.ThreeMonths
and x.FinancialStatements.BalanceSheet.InvestedCapital.ThreeMonths
and x.FinancialStatements.BalanceSheet.PreferredStock.ThreeMonths]
sortedByROIC = sorted(filtered_fine, key=lambda x: (x.FinancialStatements.IncomeStatement.EBIT.ThreeMonths)/((x.FinancialStatements.BalanceSheet.InvestedCapital.ThreeMonths)+(x.FinancialStatements.BalanceSheet.PreferredStock.ThreeMonths)), reverse=True)
# The FinancialStatements is the property of elements in filtered_fine, so you need to basically say "from the data in filtered_fine, take x, y and z and do this function, and return the answer as sortedbyROIC.
#financial data comes in quaters i.e Three Month periods, therefore make sure it is three months so that there is no 0 on denominator.
return [i.Symbol for i in sortedByROIC]
num_stocks = floor(len(filtered_fine)/self.num_portfolios)
stock_dict = {}
for i,ele in enumerate(ROIC):
rank1 = i
score = [ceil(rank1/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 range(len(self.sorted_stock))]
topFine = sorted_symbol[:self.numberOfSymbolsFine]
self.flag3 = self.flag3 + 1
return [i.Symbol for i in topFine]
else:
return []
def OnData(self, data):
if self.flag3 > 0:
if self.flag2 == 1:
self.flag2 = 0
if self._changes == None: return
for security in self._changes.RemovedSecurities:
if security.Invested:
self.Liquidate(security.Symbol)
for security in self._changes.AddedSecurities:
self.SetHoldings(security.Symbol, 0.8/float(len(self._changes.AddedSecurities)))
self._changes = None
def OnSecuritiesChanged(self, changes):
self._changes = changes
def Rebalancing(self):
self.flag1 = 1