import numpy as np
import pandas as pd
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Data import *
from datetime import timedelta
from System.Collections.Generic import List
from QuantConnect.Data.UniverseSelection import *
class QualityMomentumModel(QCAlgorithm):
def __init__(self):
# Set target number of securities to hold
self.TARGET_SECURITIES = 5
#trend following filter
self.TF_LOOKBACK = 200
self.TF_CURRENT_LOOKBACK = 20
self.TF_up = 0
#determining momentum
self.MOMENTUM_LOOKBACK_DAYS = 126 #how many days to lookback
self.MOMENTUM_SKIP_DAYS = 10 #how many days to skip
overall_lookback = (self.MOMENTUM_LOOKBACK_DAYS + self.MOMENTUM_SKIP_DAYS)
def Initialize(self):
self.SetStartDate(2010, 1, 1) # Set Start Date
self.SetEndDate(2012, 1, 1)
self.SetCash(1000) # Set Strategy Cash
self.spy = self.AddEquity("SPY", Resolution.Minute) #add SPY to use for trends
self.UniverseSettings.Resolution = Resolution.Minute #update the universe every minute
#adding a universe of stocks
#schedule function for selecting stocks and weights
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 30), Action(self.select_stocks_set_weights))
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 30), Action(self.select_stocks_set_weights))
#schedule function for making trades
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 30), Action(self.trade))
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 30), Action(self.trade))
#50 Day moving average of SPY
self.spy_ma_fast = self.SMA("SPY", 50)
#200 Day moving average of SPY
self.spy_ma_slow = self.SMA("SPY", 200)
self.trend_up = self.spy_ma_fast >= self.spy_ma_slow
if self.spy_ma_fast >= self.spy_ma_slow:
self.TF_up = 1
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
def CoarseSelectionFunction(self, coarse):
'''Drop securities which have no fundamental data or have too low prices.
Select those with highest by dollar volume'''
selected = [x for x in coarse if (x.HasFundamentalData)
and (float(x.Price) > 20)]
filtered = sorted(selected, key=lambda x: x.DollarVolume, reverse=True)
return [x.Symbol for x in filtered[:2000]]
def FineSelectionFunction(self, fine):
if self.TF_up == 1:
filtered_fine = [x for x in fine if x.ValuationRatios.FCFYield
and x.ValuationRatios.CashReturn
and x.OperationRatios.ROIC
and x.OperationRatios.LongTermDebtEquityRatio.NineMonths]
value = [x for x in filtered_fine if x.ValuationRatios.CashReturn
and x.ValuationRatios.FCFYield]
quality = [x for x in value if x.OperationRatios.ROIC
and x.OperationRatios.LongTermDebtEquityRatio]
self.returns_overall = sorted(quality,
key = lambda f: f.OperationRatios.RevenueGrowth.overall_lookback)
self.returns_recent = sorted(quality,
key = lambda f: f.OperationRatios.RevenueGrowth.MOMENTUM_SKIP_DAYS)
self.momentum = sorted(quality,
key = lambda f: self.returns_overall -
self.returns_recent)
self.top_quality = sorted(quality,
key = lambda f: f.OperationRatios.ROE.OneMonth)
TQ2 = [x[0] for x in self.top_quality]
self.stocks_to_hold = [x.symbol for x in TQ2[:self.TARGET_SECURITIES]]
return self.stocks_to_hold
print(self.stocks_to_hold)
def OnData(self, data):
pass
def select_stocks_set_weights(self):
# Set desired stock weights
# Equally weight
self.stock_weight = 1.0 / self.TARGET_SECURITIES
self.stock_weights = pd.Series(index=self.stocks_to_hold, data=self.stock_weight)
def trade(self):
for i in self.Portfolio.Values:
if (i.Invested) and (i not in self.stocks_to_hold):
self.Liquidate(i.Symbol)
for i in self.stocks_to_hold:
self.SetHoldings(i, self.stock_weight)
Here I've tried to create a filter for ROE ROIC FCF and whatnot for when SPY is bullish, However, when I try to backtest it, nothing gets traded the list of stocks don't get printed. I don't know where my error is but any help would be appreciated, thanks.