Hi all, I am new to QuantConnect and I am currently coding up a momentum strategy (Andreas Clenow).
1) Base screen of the top 500 companies based on trading volume
2) Secondary screen to calculate the screened securities' their regression coefficient multiplied by R squared values. I then store these values in a dictionary for sorting to obtain the top 10 securities with the highest scores
3) Equal weighting portfolio with monthly rebalancement - Liquidate positions if stock is no longer in the long list.
Based on all of this, I still am unable to get my backtest to run as I run into the following error
Runtime Error: Value cannot be null.
Parameter name: source
I am not sure where I went wrong so any help is appreciated! Thank you.
John Fogel
import pandas as pd import numpy as np from datetime import datetime, timedelta from QuantConnect.Data.UniverseSelection import * from scipy.stats import linregress class SystematicMomentum(QCAlgorithm): def Initialize(self): self.num_coarse = 500 self.num_fine = 10 self.SetStartDate(2018, 1, 1) # Set Start Date self.SetCash(10000) # Set Strategy Cash # set the flag for rebalance self.reb = 1 self.AddUniverse(self.CoarseSelectionFunction,self.FineSelectionFunction) self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol self.Schedule.On(self.DateRules.MonthStart(self.spy), self.TimeRules.AfterMarketOpen(self.spy,5), Action(self.rebalance)) def CoarseSelectionFunction(self, coarse): # if the rebalance flag is not 1, return null list to save time. if self.reb != 1: return self.long # make universe selection once a month sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True) filtered = [x.Symbol for x in sortedByDollarVolume if x.HasFundamentalData] # filtered down to the 500 most liquid stocks return filtered[:self.num_coarse] def FineSelectionFunction(self, fine): # return null list if it's not time to rebalance if self.reb != 1: return self.long # drop counter (will update back to 1 after rebalancement has occurred) self.reb = 0 # create dictionaries to store the indicator values stock_filter1 = {} # sort the fine list by their momentum for security in fine: hist = self.History(security.Symbol, timedelta(days=365), Resolution.Daily) hist["log"] = np.log(hist["close"]) x1 = np.arange(hist["close"].count()) slope, _, rvalue, _, _ = linregress(x1, hist["log"]) coeff = slope*252*(rvalue**2) # we now have a dictionary storing the values stock_filter1[security.Symbol] = coeff # we only want the highest values for the coeff self.sorted1 = sorted(stock_filter1.items(), key=lambda d:d[1],reverse=True) sorted1_symbol = [x[0] for x in self.sorted1] # long the top 10 self.long = sorted1_symbol[:self.num_fine] def OnData(self, data): pass def rebalance(self): # at the start of rebalancement, if the stock is no longer in the long list, liquidate long_list = self.long for i in self.Portfolio.Values: if (i.Invested) and (i not in long_list): self.Liquidate(i.Symbol) # Assign each stock equally. Alternatively you can design your own portfolio construction method for i in self.long: self.SetHoldings(i, 0.9/self.num_fine) self.reb = 1
John Fogel
I have fixed the above error and managed to get the backtest to run. However, 2 months into the backtest, I ran into an error - Can someone please explain to me the meaning of this error and a way to rectify it. Thank you!
Shile Wen
Hi Ethan,
This usually means that the hist is empty. This likely occurred because there was no data for the given security, and to prevent this from happening, try adding if len(hist) > 0: as a conditional before any calculations.
Furthermore, please try to move all the logic for calculations and buying/selling of securities to the OnSecuritiesChanged method.
Best Regards,
Shile Wen
John Fogel
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!