The idea is to call the universe selection once per week and filter the stocks using MFI
The criteria to add a stock to the universe is:

  1. Price > 20
  2. 2 < DividendYield < 15
  3. MFI > 60

As you know, MFI is a tradebar indicator, so I cannot use coarse.
The implementation reasoning is:

  • Add Universe is called every day, but if the week day is not Monday, it’ll return the same universe we have now
  • If the week day is Monday, I let the filter run, return 200 stock as maximum and I set a flag _universeSelectionCalled = true
  • Then in the OnData method if the flag _universeSelectionCalled is true I call the method RemoveStocksDontMeetWeeklyCriteria the applies the MFI filter.

But there is something plain wrong:

  • The RemoveStocksDontMeetWeeklyCriteria is never called.
  • The overridden OnSecuritiesChanged methos isn’t called neither.
  • The algorithm takes too long to run and ends ups throwing
Runtime Error: System.Exception: Execution Security Error: Memory Usage Maxed Out - 11264MB max, with last sample of 12998MB.

Any help will be much appreciated.
As I don’t have any working backtest, there is the code:

namespace QuantConnect { public class WeeklyCriteriaUniverse : QCAlgorithm { // holds our coarse fundamental indicators by symbol private SecurityChanges _changes = SecurityChanges.None; private IEnumerable<Symbol> _actualUniverse = Enumerable.Empty<Symbol>(); private bool _firstTime = true; private bool _universeSelectionCalled = false; public override void Initialize() { SetStartDate(year: 2013, month: 10, day: 08); //Set Start Date SetEndDate(year: 2014, month: 10, day: 11); //Set End Date SetCash(startingCash: 100000); //Set Strategy Cash UniverseSettings.Resolution = Resolution.Daily; AddUniverse(coarse => { if (Time.DayOfWeek != DayOfWeek.Monday && !_firstTime) return _actualUniverse; return coarse.Where(c => c.HasFundamentalData) .OrderByDescending(c => c.DollarVolume) .Select(c => c.Symbol) .Take(200); }, fine => { if (Time.DayOfWeek != DayOfWeek.Monday && !_firstTime) return _actualUniverse; Log(Time.ToString("F") + " - AddUniverse Called!"); _universeSelectionCalled = true; return fine.Where(f => f.Price > 20 && f.ValuationRatios.TrailingDividendYield > 2 && f.ValuationRatios.TrailingDividendYield < 15) .Select(f => f.Symbol); } ); } public override void OnData(Slice slice) { if (_universeSelectionCalled) { // ToDO: Call remove from schelude Log(Time.ToString("F") + " - RemoveStocksDontMeetWeeklyCriteria called."); RemoveStocksDontMeetWeeklyCriteria(); } } private void RemoveStocksDontMeetWeeklyCriteria() { var stocksToRemove = new List<Symbol>(); foreach (var stock in Securities.Values) { var mfi = new MoneyFlowIndex(14); foreach (var bar in History(stock.Symbol, TimeSpan.FromDays(16), Resolution.Daily)) { mfi.Update(bar); } if (mfi < 60) stocksToRemove.Add(stock.Symbol); } Log(Time.ToString("F") + " - Stocks in universe: " + Securities.Count); Log(Time.ToString("F") + " - Stocks to remove: " + stocksToRemove.Count); Log(Time.ToString("F") + " - Stocks after removing : " + Securities.Count); foreach (var symbol in stocksToRemove) { UniverseManager.Remove(symbol); } _firstTime = false; _universeSelectionCalled = false; _actualUniverse = Securities.Keys; } public override void OnSecuritiesChanged(SecurityChanges changes) { _changes = changes; //TODO: check if changes is none. Log(Time.ToString("F") + " - Stocks added to universe: " + changes.AddedSecurities.Count.ToString()); Log(Time.ToString("F") + " - Stocks removed from universe: " + changes.RemovedSecurities.Count.ToString()); } } }

Author