I was testing the fine/coarse demonstration algorithm to see what happened if I switched the P/E ratio to another fundamental metric. When I tested different valuation ratios, the backtests were successful, but the algorithm crashed when I tested it with operation ratios. Not sure if data is missing, maybe adding dropna somewhere would help.
Alexandre Catarino
Could you please attach a backtest that provides an example of the issue?
Eric Novinson
It seems like the problem is on a single line. With sortedByFRatio = sorted(fine, key=lambda x: x.OperationRatios.ROIC, reverse=True) the backtest crashes but if I use sortedByFRatio = sorted(fine, key=lambda x: x.ValuationRatios.PEGRatio, reverse=True) the backtest runs successfully and this seems to be the case with other operation ratios and valuation ratios as well. Maybe I'm getting the syntax wrong, thought that if x.ValuationRatios.Ratio works then x.OperationRatios.Ratio should also work.
from System.Collections.Generic import List from QuantConnect.Data.UniverseSelection import * class CoarseFineFundamentalComboAlgorithm(QCAlgorithm): '''In this algorithm we demonstrate how to define a universe as a combination of use the coarse fundamental data and fine fundamental data''' def Initialize(self): '''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.''' self.SetStartDate(2013,01,01) #Set Start Date self.SetEndDate(2014,01,01) #Set End Date self.SetCash(10000) #Set Strategy Cash 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 = 100 self.__numberOfSymbolsFine = 10 self._changes = SecurityChanges.None # sort the data by daily dollar volume and take the top 'NumberOfSymbols' def CoarseSelectionFunction(self, coarse): # sort descending by daily dollar volume sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True) # return the symbol objects of the top entries from our sorted collection topvol = sortedByDollarVolume[:self.__numberOfSymbols] # we need to return only the symbol objects list = List[Symbol]() for x in topvol: list.Add(x.Symbol) return list # sort the data by fundamental ratio and take the top 'NumberOfSymbolsFine' def FineSelectionFunction(self, fine): # sort descending by fundamental ratio sortedByFRatio = sorted(fine, key=lambda x: x.ValuationRatios.PEGRatio, reverse=True) # take the top entries from our sorted collection topFine = sortedByFRatio[:self.__numberOfSymbolsFine] list = List[Symbol]() for x in topFine: list.Add(x.Symbol) return list def OnData(self, data): # if we have no changes, do nothing if self._changes == SecurityChanges.None: return # liquidate removed securities for security in self._changes.RemovedSecurities: if security.Invested: self.Liquidate(security.Symbol) # we want equal allocation in each security in our universe # 0.95 to avoid using margin # Avoid passing number of symbols here for now for security in self._changes.AddedSecurities: self.SetHoldings(security.Symbol, 0.09) self._changes = SecurityChanges.None; # this event fires whenever we have changes to our universe def OnSecuritiesChanged(self, changes): self._changes = changes
Alexandre Catarino
OperationRatios.ROIC is a MultiPeriodField fundamental data. That means you have:
ROIC.OneYear .SixMonths .ThreeMonths .Value
where Value refers to the OneYear since it is the default.
If you are look for the three-month ROIC, for exemple, please use:
sortedByFRatio = sorted(fine, key=lambda x: x.OperationRatios.ROIC.ThreeMonths, reverse=True)
Eric Novinson
Thank you, I added OneYear and it works now.
Eric Novinson
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!