/// <summary>
        /// Event fired each time the we add/remove securities from the data feed
        /// </summary>
        /// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
        /// <param name="changes">The security additions and removals from the algorithm</param>
        public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
        {
            // Get removed symbol and invalidate them in the insight collection
            _removedSymbols = changes.RemovedSecurities.Select(x => x.Symbol).ToList();
            _insightCollection.Clear(_removedSymbols.ToArray());

            foreach (var symbol in _removedSymbols)
            {
                if (_symbolDataDict.ContainsKey(symbol))
                {
                    _symbolDataDict[symbol].Reset();
                    _symbolDataDict.Remove(symbol);
                }
            }

            // initialize data for added securities
            var addedSymbols = changes.AddedSecurities.Select(x => x.Symbol).ToList();

            algorithm.History(addedSymbols, _lookback * _period, _resolution)
            .PushThrough(bar =>
            {
                ReturnsSymbolData symbolData;
                if (!_symbolDataDict.TryGetValue(bar.Symbol, out symbolData))
                {
                    symbolData = new ReturnsSymbolData(bar.Symbol, _lookback, _period);
                    _symbolDataDict.Add(bar.Symbol, symbolData);
                }
                symbolData.Update(bar.EndTime, bar.Value);
            });
        }
        /// <summary>
        /// Event fired each time the we add/remove securities from the data feed
        /// </summary>
        /// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
        /// <param name="changes">The security additions and removals from the algorithm</param>
        public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
        {
            base.OnSecuritiesChanged(algorithm, changes);

            foreach (var symbol in changes.RemovedSecurities.Select(x => x.Symbol))
            {
                if (_symbolDataDict.ContainsKey(symbol))
                {
                    _symbolDataDict[symbol].Reset();
                    _symbolDataDict.Remove(symbol);
                }
            }

            // initialize data for added securities
            var addedSymbols = changes.AddedSecurities.ToDictionary(x => x.Symbol, x => x.Exchange.TimeZone);

            algorithm.History(addedSymbols.Keys, _lookback * _period, _resolution)
            .PushThrough(bar =>
            {
                ReturnsSymbolData symbolData;
                if (!_symbolDataDict.TryGetValue(bar.Symbol, out symbolData))
                {
                    symbolData = new ReturnsSymbolData(bar.Symbol, _lookback, _period);
                    _symbolDataDict.Add(bar.Symbol, symbolData);
                }
                // Convert the data timestamp to UTC
                var utcTime = bar.EndTime.ConvertToUtc(addedSymbols[bar.Symbol]);
                symbolData.Update(utcTime, bar.Value);
            });
        }
        /// <summary>
        /// Event fired each time the we add/remove securities from the data feed
        /// </summary>
        /// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
        /// <param name="changes">The security additions and removals from the algorithm</param>
        public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
        {
            base.OnSecuritiesChanged(algorithm, changes);
            // clean up data for removed securities
            foreach (var removed in changes.RemovedSecurities)
            {
                _pendingRemoval.Add(removed.Symbol);
                ReturnsSymbolData data;
                if (_symbolDataDict.TryGetValue(removed.Symbol, out data))
                {
                    _symbolDataDict.Remove(removed.Symbol);
                    data.Reset();
                }
            }

            // initialize data for added securities
            var addedSymbols = new List <Symbol>();

            foreach (var added in changes.AddedSecurities)
            {
                if (!_symbolDataDict.ContainsKey(added.Symbol))
                {
                    var symbolData = new ReturnsSymbolData(added.Symbol, _lookback, _period);
                    _symbolDataDict[added.Symbol] = symbolData;
                    addedSymbols.Add(added.Symbol);
                }
            }
            if (addedSymbols.Count == 0)
            {
                return;
            }

            // warmup our indicators by pushing history through the consolidators
            algorithm.History(addedSymbols, _lookback * _period, _resolution)
            .PushThrough(bar =>
            {
                ReturnsSymbolData symbolData;
                if (_symbolDataDict.TryGetValue(bar.Symbol, out symbolData))
                {
                    symbolData.Update(bar.EndTime, bar.Value);
                }
            });
        }