Example #1
0
        /********************************************************
         * CLASS METHODS
         *********************************************************/
        /// <summary>
        /// Try and create a new instance of the object and return it using the MoveNext enumeration pattern ("Current" public variable).
        /// </summary>
        /// <remarks>This is a highly called method and should be kept lean as possible.</remarks>
        /// <returns>Boolean true on successful move next. Set Current public property.</returns>
        public bool MoveNext()
        {
            BaseData instance           = null;
            var      instanceMarketOpen = false;

            //Log.Debug("SubscriptionDataReader.MoveNext(): Starting MoveNext...");

            //Calls this when no file, first "moveNext()" in refresh source.
            if (_endOfStream || _reader == null || _reader.EndOfStream)
            {
                if (_reader == null)
                {
                    //Handle the 1% of time:: getReader failed (e.g. missing day on S3) so skip day:
                    Current = null;
                }
                else
                {
                    //This is a MoveNext() after reading the last line of file:
                    _lastBarOfStream = Current;
                }
                _endOfStream = true;
                return(false);
            }

            //Log.Debug("SubscriptionDataReader.MoveNext(): Launching While-InstanceNotNull && not EOS: " + reader.EndOfStream);
            //Keep looking until output's an instance:
            while (instance == null && !_reader.EndOfStream)
            {
                //Get the next string line from file, create instance of BaseData:
                var line = _reader.ReadLine();
                try
                {
                    //Using Fasterflex method invokers.
                    instance = _readerMethodInvoker(_dataFactory, _config, line, _date, _feedEndpoint) as BaseData;
                }
                catch (Exception err)
                {
                    //Log.Debug("SubscriptionDataReader.MoveNext(): Error invoking instance: " + err.Message);
                    Engine.ResultHandler.RuntimeError("Error invoking " + _config.Symbol + " data reader. Line: " + line + " Error: " + err.Message, err.StackTrace);
                    _endOfStream = true;
                }

                if (instance != null)
                {
                    instanceMarketOpen = _security.Exchange.DateTimeIsOpen(instance.Time);

                    //Apply custom user data filters:
                    try
                    {
                        if (!_security.DataFilter.Filter(_security, instance))
                        {
                            instance = null;
                            continue;
                        }
                    }
                    catch (Exception err)
                    {
                        Log.Error("SubscriptionDataReader.MoveNext(): Error applying filter: " + err.Message);
                        Engine.ResultHandler.RuntimeError("Runtime error applying data filter. Assuming filter pass: "******"SubscriptionDataReader.MoveNext(): Instance null, continuing...");
                        continue;
                    }


                    //Check if we're in date range of the data request
                    if (!_isQCData)
                    {
                        if (instance.Time < _periodStart)
                        {
                            _lastBarOutsideMarketHours = instance;
                            instance = null;
                            continue;
                        }
                        if (instance.Time > _periodFinish)
                        {
                            instance = null;
                            continue;
                        }
                    }

                    //Save bar for extended market hours (fill forward).
                    if (!instanceMarketOpen)
                    {
                        _lastBarOutsideMarketHours = instance;
                    }

                    //However, if we only want market hours data, don't return yet: Discard and continue looping.
                    if (!_config.ExtendedMarketHours && !instanceMarketOpen)
                    {
                        instance = null;
                    }
                }
            }

            //Handle edge conditions: First Bar Read:
            // -> Use previous bar from yesterday if available
            if (Current == null)
            {
                //Handle first loop where not set yet:
                if (_lastBarOfStream == null)
                {
                    //For first bar, fill forward from premarket data where possible
                    _lastBarOfStream = _lastBarOutsideMarketHours ?? instance;
                }
                //If current not set yet, set Previous to yesterday/last bar read.
                Previous = _lastBarOfStream;
            }
            else
            {
                Previous = Current;
            }

            Current = instance;

            //End of Stream: rewind reader to last
            if (_reader.EndOfStream && instance == null)
            {
                //Log.Debug("SubscriptionDataReader.MoveNext(): Reader EOS.");
                _endOfStream = true;

                if (_isFillForward && Previous != null)
                {
                    //If instance == null, current is null, so clone previous to record the final sample:
                    Current = Previous.Clone();
                    //When market closes fastforward current bar to the last bar fill forwarded to close time.
                    Current.Time = _security.Exchange.TimeOfDayClosed(Previous.Time);
                    // Save the previous bar as last bar before next stream (for fill forwrd).
                    _lastBarOfStream = Previous;
                }
                return(false);
            }
            return(true);
        }