This is my first attempt at monthly rebalancing, so I'm missing something simple to get it to work. The concept is to coars filter by dollar volume and fundamental data, then fine filter for ROE, and invest monthly in top 20 results.
The error seems to be from SPY with the rebalance action at the end, but i'm stuck. Any help would be appreciated.
My backtest wasn't showing up in the dropdown so here is the code:
from clr import AddReference
AddReference("System.Core")
AddReference("System.Collections")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm")
from System import *
from System.Collections.Generic import List
from QuantConnect import *
from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect.Data.UniverseSelection import *
class MonthlyROERebalanceAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2000,1,1) #Set Start Date
self.SetEndDate(2020,8,1) #Set End Date
self.SetCash(100000) #Set Strategy Cash
self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
# what resolution should the data *added* to the universe be?
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.numberOfSymbols = 500
self.numberOfSymbolsFine = 20
self._changes = None
# Create the monthly rebalance logic. Check SPY 1 minute after market open to determine the first trading day of the month.
self.Schedule.On(self.DateRules.MonthStart(self.spy),
self.TimeRules.AfterMarketOpen(self.spy,1),
self.rebalance)
def OnData(self, data):
#make sure SPY has data to prevent missing data errors
if data.ContainsKey("SPY") == False: return
pass
# Coarse selection by sorting the symbols by daily dollar volume and define this list as "numbersOfSymbol"
def CoarseSelectionFunction(self, coarse):
# sort descending by daily dollar volume and only those that have fundamental data
sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume and x.HasFundamentalData, reverse=True)
# return the symbol objects of the top entries from our sorted collection
return [ x.Symbol for x in sortedByDollarVolume[:self.numberOfSymbols] ]
# sort the data by Return on Equity and take the top ranked symbols as 'NumberOfSymbolsFine'
def FineSelectionFunction(self, fine):
# sort descending by Return On Equity
sortedByROE = sorted(fine, key=lambda x: x.OperationRatios.ROE.Value, reverse=True)
# take the top entries from our sorted collection
return [ x.Symbol for x in sortedByROE[:self.numberOfSymbolsFine] ]
def rebalance(self):
# invest equally in the fine filtered list of stocks
for symbol in self.numberOfSymbolsFine:
self.SetHoldings(symbol, 1)