/// <summary>
 /// Initializes a new instance of the <see cref="CollectionSubscriptionDataSourceReader"/> class
 /// </summary>
 /// <param name="dataCacheProvider">Used to cache data for requested from the IDataProvider</param>
 /// <param name="config">The subscription's configuration</param>
 /// <param name="date">The date this factory was produced to read data for</param>
 /// <param name="isLiveMode">True if we're in live mode, false for backtesting</param>
 public CollectionSubscriptionDataSourceReader(IDataCacheProvider dataCacheProvider, SubscriptionDataConfig config, DateTime date, bool isLiveMode)
     : base(dataCacheProvider, isLiveMode)
 {
     _date    = date;
     _config  = config;
     _factory = _config.GetBaseDataInstance();
 }
Esempio n. 2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ZipEntryNameSubscriptionDataSourceReader"/> class
 /// </summary>
 /// <param name="config">The subscription's configuration</param>
 /// <param name="date">The date this factory was produced to read data for</param>
 /// <param name="isLiveMode">True if we're in live mode, false for backtesting</param>
 public ZipEntryNameSubscriptionDataSourceReader(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
 {
     _config     = config;
     _date       = date;
     _isLiveMode = isLiveMode;
     _factory    = _factory = config.GetBaseDataInstance();
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="TextSubscriptionDataSourceReader"/> class
 /// </summary>
 /// <param name="dataCacheProvider">This provider caches files if needed</param>
 /// <param name="config">The subscription's configuration</param>
 /// <param name="date">The date this factory was produced to read data for</param>
 /// <param name="isLiveMode">True if we're in live mode, false for backtesting</param>
 public TextSubscriptionDataSourceReader(IDataCacheProvider dataCacheProvider, SubscriptionDataConfig config, DateTime date, bool isLiveMode)
     : base(dataCacheProvider, isLiveMode)
 {
     _date    = date;
     _config  = config;
     _factory = config.GetBaseDataInstance();
     _shouldCacheDataPoints = !_config.IsCustomData && _config.Resolution >= Resolution.Hour &&
                              _config.Type != typeof(FineFundamental) && _config.Type != typeof(CoarseFundamental) &&
                              !DataCacheProvider.IsDataEphemeral;
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="TextSubscriptionDataSourceReader"/> class
        /// </summary>
        /// <param name="dataCacheProvider">This provider caches files if needed</param>
        /// <param name="config">The subscription's configuration</param>
        /// <param name="date">The date this factory was produced to read data for</param>
        /// <param name="isLiveMode">True if we're in live mode, false for backtesting</param>
        public TextSubscriptionDataSourceReader(IDataCacheProvider dataCacheProvider, SubscriptionDataConfig config, DateTime date, bool isLiveMode)
            : base(dataCacheProvider, isLiveMode)
        {
            _date    = date;
            _config  = config;
            _factory = config.GetBaseDataInstance();
            _shouldCacheDataPoints = !_config.IsCustomData && _config.Resolution >= Resolution.Hour &&
                                     _config.Type != typeof(FineFundamental) && _config.Type != typeof(CoarseFundamental) &&
                                     !DataCacheProvider.IsDataEphemeral;

            var method = _config.Type.GetMethod("Reader",
                                                new[] { typeof(SubscriptionDataConfig), typeof(StreamReader), typeof(DateTime), typeof(bool) });

            if (method != null && method.DeclaringType == _config.Type)
            {
                _implementsStreamReader = true;
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Creates a new <see cref="ISubscriptionDataSourceReader"/> capable of handling the specified <paramref name="source"/>
        /// </summary>
        /// <param name="source">The subscription data source to create a factory for</param>
        /// <param name="dataCacheProvider">Used to cache data</param>
        /// <param name="config">The configuration of the subscription</param>
        /// <param name="date">The date to be processed</param>
        /// <param name="isLiveMode">True for live mode, false otherwise</param>
        /// <returns>A new <see cref="ISubscriptionDataSourceReader"/> that can read the specified <paramref name="source"/></returns>
        public static ISubscriptionDataSourceReader ForSource(SubscriptionDataSource source, IDataCacheProvider dataCacheProvider, SubscriptionDataConfig config, DateTime date, bool isLiveMode)
        {
            ISubscriptionDataSourceReader    reader;
            TextSubscriptionDataSourceReader textReader = null;

            switch (source.Format)
            {
            case FileFormat.Csv:
                reader = textReader = new TextSubscriptionDataSourceReader(dataCacheProvider, config, date, isLiveMode);
                break;

            case FileFormat.Collection:
                reader = new CollectionSubscriptionDataSourceReader(dataCacheProvider, config, date, isLiveMode);
                break;

            case FileFormat.ZipEntryName:
                reader = new ZipEntryNameSubscriptionDataSourceReader(config, date, isLiveMode);
                break;

            case FileFormat.Index:
                return(new IndexSubscriptionDataSourceReader(dataCacheProvider, config, date, isLiveMode));

            default:
                throw new NotImplementedException("SubscriptionFactory.ForSource(" + source + ") has not been implemented yet.");
            }

            // wire up event handlers for logging missing files
            if (source.TransportMedium == SubscriptionTransportMedium.LocalFile)
            {
                var factory = config.GetBaseDataInstance();
                if (!factory.IsSparseData())
                {
                    reader.InvalidSource += (sender, args) => Log.Error($"SubscriptionDataSourceReader.InvalidSource(): File not found: {args.Source.Source}");
                    if (textReader != null)
                    {
                        textReader.CreateStreamReaderError += (sender, args) => Log.Error($"SubscriptionDataSourceReader.CreateStreamReaderError(): File not found: {args.Source.Source}");
                    }
                }
            }

            return(reader);
        }
        /// <summary>
        /// Initializes the <see cref="SubscriptionDataReader"/> instance
        /// </summary>
        /// <remarks>Should be called after all consumers of <see cref="NewTradableDate"/> event are set,
        /// since it will produce events.</remarks>
        public void Initialize()
        {
            if (_initialized)
            {
                return;
            }

            //Save the type of data we'll be getting from the source.
            try
            {
                _dataFactory = _config.GetBaseDataInstance();
            }
            catch (ArgumentException exception)
            {
                OnInvalidConfigurationDetected(new InvalidConfigurationDetectedEventArgs(_config.Symbol, exception.Message));
                _endOfStream = true;
                return;
            }

            //If its quandl set the access token in data factory:
            var quandl = _dataFactory as Quandl;

            if (quandl != null)
            {
                if (!Quandl.IsAuthCodeSet)
                {
                    Quandl.SetAuthCode(Config.Get("quandl-auth-token"));
                }
            }

            // If Tiingo data, set the access token in data factory
            var tiingo = _dataFactory as TiingoPrice;

            if (tiingo != null)
            {
                if (!Tiingo.IsAuthCodeSet)
                {
                    Tiingo.SetAuthCode(Config.Get("tiingo-auth-token"));
                }
            }

            // If USEnergyAPI data, set the access token in data factory
            var energyInformation = _dataFactory as USEnergyAPI;

            if (energyInformation != null)
            {
                if (!USEnergyAPI.IsAuthCodeSet)
                {
                    USEnergyAPI.SetAuthCode(Config.Get("us-energy-information-auth-token"));
                }
            }

            // If Fred data, set the access token in data factory
            var fred = _dataFactory as FredApi;

            if (fred != null)
            {
                if (!FredApi.IsAuthCodeSet)
                {
                    FredApi.SetAuthCode(Config.Get("fred-auth-token"));
                }
            }

            _factorFile = new FactorFile(_config.Symbol.Value, new List <FactorFileRow>());
            _mapFile    = new MapFile(_config.Symbol.Value, new List <MapFileRow>());

            // load up the map files for equities, options, and custom data if it supports it.
            // Only load up factor files for equities
            if (_dataFactory.RequiresMapping())
            {
                try
                {
                    var mapFile = _mapFileResolver.ResolveMapFile(_config.Symbol, _config.Type);

                    // only take the resolved map file if it has data, otherwise we'll use the empty one we defined above
                    if (mapFile.Any())
                    {
                        _mapFile = mapFile;
                    }

                    if (!_config.IsCustomData && !_config.SecurityType.IsOption())
                    {
                        var factorFile = _factorFileProvider.Get(_config.Symbol);
                        _hasScaleFactors = factorFile != null;
                        if (_hasScaleFactors)
                        {
                            _factorFile = factorFile;

                            // if factor file has minimum date, update start period if before minimum date
                            if (!_isLiveMode && _factorFile != null && _factorFile.FactorFileMinimumDate.HasValue)
                            {
                                if (_periodStart < _factorFile.FactorFileMinimumDate.Value)
                                {
                                    _periodStart = _factorFile.FactorFileMinimumDate.Value;

                                    OnNumericalPrecisionLimited(
                                        new NumericalPrecisionLimitedEventArgs(_config.Symbol,
                                                                               $"[{_config.Symbol.Value}, {_factorFile.FactorFileMinimumDate.Value.ToShortDateString()}]"));
                                }
                            }
                        }

                        if (_periodStart < mapFile.FirstDate)
                        {
                            _periodStart = mapFile.FirstDate;

                            OnStartDateLimited(
                                new StartDateLimitedEventArgs(_config.Symbol,
                                                              $"[{_config.Symbol.Value}," +
                                                              $" {mapFile.FirstDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}]"));
                        }
                    }
                }
                catch (Exception err)
                {
                    Log.Error(err, "Fetching Price/Map Factors: " + _config.Symbol.ID + ": ");
                }
            }

            _delistingDate = _config.Symbol.GetDelistingDate(_mapFile);

            // adding a day so we stop at EOD
            _delistingDate = _delistingDate.AddDays(1);

            UpdateDataEnumerator(true);

            _initialized = true;
        }
        /// <summary>
        /// Reads the specified <paramref name="source"/>
        /// </summary>
        /// <param name="source">The source to be read</param>
        /// <returns>An <see cref="IEnumerable{BaseData}"/> that contains the data in the source</returns>
        public override IEnumerable <BaseData> Read(SubscriptionDataSource source)
        {
            List <BaseData> cache;

            _shouldCacheDataPoints = _shouldCacheDataPoints &&
                                     // only cache local files
                                     source.TransportMedium == SubscriptionTransportMedium.LocalFile;
            var cacheItem = _shouldCacheDataPoints
                ? BaseDataSourceCache.GetCacheItem(source.Source + _config.Type) : null;

            if (cacheItem == null)
            {
                cache = new List <BaseData>();
                using (var reader = CreateStreamReader(source))
                {
                    // if the reader doesn't have data then we're done with this subscription
                    if (reader == null || reader.EndOfStream)
                    {
                        OnCreateStreamReaderError(_date, source);
                        yield break;
                    }

                    if (_factory == null)
                    {
                        // only create a factory if the stream isn't null
                        _factory = _config.GetBaseDataInstance();
                    }
                    // while the reader has data
                    while (!reader.EndOfStream)
                    {
                        BaseData instance = null;
                        string   line     = null;
                        try
                        {
                            if (reader.StreamReader != null && _implementsStreamReader)
                            {
                                instance = _factory.Reader(_config, reader.StreamReader, _date, IsLiveMode);
                            }
                            else
                            {
                                // read a line and pass it to the base data factory
                                line     = reader.ReadLine();
                                instance = _factory.Reader(_config, line, _date, IsLiveMode);
                            }
                        }
                        catch (Exception err)
                        {
                            OnReaderError(line ?? "StreamReader", err);
                        }

                        if (instance != null && instance.EndTime != default(DateTime))
                        {
                            if (_shouldCacheDataPoints)
                            {
                                cache.Add(instance);
                            }
                            else
                            {
                                yield return(instance);
                            }
                        }
                        else if (reader.ShouldBeRateLimited)
                        {
                            yield return(instance);
                        }
                    }
                }

                if (!_shouldCacheDataPoints)
                {
                    yield break;
                }

                cacheItem = new CacheItem(source.Source + _config.Type, cache);
                BaseDataSourceCache.Add(cacheItem, CachePolicy);
            }
            cache = cacheItem.Value as List <BaseData>;
            if (cache == null)
            {
                throw new InvalidOperationException("CacheItem can not be cast into expected type. " +
                                                    $"Type is: {cacheItem.Value.GetType()}");
            }
            // Find the first data point 10 days (just in case) before the desired date
            // and subtract one item (just in case there was a time gap and data.Time is after _date)
            var frontier = _date.AddDays(-10);
            var index    = cache.FindIndex(data => data.Time > frontier);

            index = index > 0 ? (index - 1) : 0;
            foreach (var data in cache.Skip(index))
            {
                var clone = data.Clone();
                clone.Symbol = _config.Symbol;
                yield return(clone);
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Initializes the <see cref="SubscriptionDataReader"/> instance
        /// </summary>
        /// <remarks>Should be called after all consumers of <see cref="NewTradableDate"/> event are set,
        /// since it will produce events.</remarks>
        public void Initialize()
        {
            if (_initialized)
            {
                return;
            }

            //Save the type of data we'll be getting from the source.
            try
            {
                _dataFactory = _config.GetBaseDataInstance();
            }
            catch (ArgumentException exception)
            {
                OnInvalidConfigurationDetected(new InvalidConfigurationDetectedEventArgs(exception.Message));
                _endOfStream = true;
                return;
            }

            //If its quandl set the access token in data factory:
            var quandl = _dataFactory as Quandl;

            if (quandl != null)
            {
                if (!Quandl.IsAuthCodeSet)
                {
                    Quandl.SetAuthCode(Config.Get("quandl-auth-token"));
                }
            }

            // If Tiingo data, set the access token in data factory
            var tiingo = _dataFactory as TiingoPrice;

            if (tiingo != null)
            {
                if (!Tiingo.IsAuthCodeSet)
                {
                    Tiingo.SetAuthCode(Config.Get("tiingo-auth-token"));
                }
            }

            // If USEnergyAPI data, set the access token in data factory
            var energyInformation = _dataFactory as USEnergyAPI;

            if (energyInformation != null)
            {
                if (!USEnergyAPI.IsAuthCodeSet)
                {
                    USEnergyAPI.SetAuthCode(Config.Get("us-energy-information-auth-token"));
                }
            }

            _factorFile = new FactorFile(_config.Symbol.Value, new List <FactorFileRow>());
            _mapFile    = new MapFile(_config.Symbol.Value, new List <MapFileRow>());

            // load up the map files for equities, options, and custom data if it supports it.
            // Only load up factor files for equities
            if (_dataFactory.RequiresMapping())
            {
                try
                {
                    var mapFile = _mapFileResolver.ResolveMapFile(_config.Symbol, _config.Type);

                    // only take the resolved map file if it has data, otherwise we'll use the empty one we defined above
                    if (mapFile.Any())
                    {
                        _mapFile = mapFile;
                    }

                    if (!_config.IsCustomData && _config.SecurityType != SecurityType.Option)
                    {
                        var factorFile = _factorFileProvider.Get(_config.Symbol);
                        _hasScaleFactors = factorFile != null;
                        if (_hasScaleFactors)
                        {
                            _factorFile = factorFile;

                            // if factor file has minimum date, update start period if before minimum date
                            if (!_isLiveMode && _factorFile != null && _factorFile.FactorFileMinimumDate.HasValue)
                            {
                                if (_periodStart < _factorFile.FactorFileMinimumDate.Value)
                                {
                                    _periodStart = _factorFile.FactorFileMinimumDate.Value;

                                    OnNumericalPrecisionLimited(
                                        new NumericalPrecisionLimitedEventArgs(
                                            $"Data for symbol {_config.Symbol.Value} has been limited due to numerical precision issues in the factor file. " +
                                            $"The starting date has been set to {_factorFile.FactorFileMinimumDate.Value.ToShortDateString()}."));
                                }
                            }
                        }
                    }
                }
                catch (Exception err)
                {
                    Log.Error(err, "Fetching Price/Map Factors: " + _config.Symbol.ID + ": ");
                }
            }

            // Estimate delisting date.
            switch (_config.Symbol.ID.SecurityType)
            {
            case SecurityType.Future:
                _delistingDate = _config.Symbol.ID.Date;
                break;

            case SecurityType.Option:
                _delistingDate = OptionSymbol.GetLastDayOfTrading(_config.Symbol);
                break;

            default:
                _delistingDate = _mapFile.DelistingDate;
                break;
            }
            // adding a day so we stop at EOD
            _delistingDate = _delistingDate.AddDays(1);

            _subscriptionFactoryEnumerator = ResolveDataEnumerator(true);

            _initialized = true;
        }
        /// <summary>
        /// Reads the specified <paramref name="source"/>
        /// </summary>
        /// <param name="source">The source to be read</param>
        /// <returns>An <see cref="IEnumerable{BaseData}"/> that contains the data in the source</returns>
        public override IEnumerable <BaseData> Read(SubscriptionDataSource source)
        {
            List <BaseData> cache = null;

            _shouldCacheDataPoints = _shouldCacheDataPoints &&
                                     // only cache local files
                                     source.TransportMedium == SubscriptionTransportMedium.LocalFile;

            string cacheKey = null;

            if (_shouldCacheDataPoints)
            {
                cacheKey = source.Source + _config.Type;
                BaseDataSourceCache.TryGetValue(cacheKey, out cache);
            }
            if (cache == null)
            {
                cache = _shouldCacheDataPoints ? new List <BaseData>(30000) : null;
                using (var reader = CreateStreamReader(source))
                {
                    if (reader == null)
                    {
                        // if the reader doesn't have data then we're done with this subscription
                        yield break;
                    }

                    if (_factory == null)
                    {
                        // only create a factory if the stream isn't null
                        _factory = _config.GetBaseDataInstance();
                    }
                    // while the reader has data
                    while (!reader.EndOfStream)
                    {
                        BaseData instance = null;
                        string   line     = null;
                        try
                        {
                            if (reader.StreamReader != null && _implementsStreamReader)
                            {
                                instance = _factory.Reader(_config, reader.StreamReader, _date, IsLiveMode);
                            }
                            else
                            {
                                // read a line and pass it to the base data factory
                                line     = reader.ReadLine();
                                instance = _factory.Reader(_config, line, _date, IsLiveMode);
                            }
                        }
                        catch (Exception err)
                        {
                            OnReaderError(line ?? "StreamReader", err);
                        }

                        if (instance != null && instance.EndTime != default(DateTime))
                        {
                            if (_shouldCacheDataPoints)
                            {
                                cache.Add(instance);
                            }
                            else
                            {
                                yield return(instance);
                            }
                        }
                        else if (reader.ShouldBeRateLimited)
                        {
                            yield return(instance);
                        }
                    }
                }

                if (!_shouldCacheDataPoints)
                {
                    yield break;
                }

                lock (CacheKeys)
                {
                    CacheKeys.Enqueue(cacheKey);
                    // we create a new dictionary, so we don't have to take locks when reading, and add our new item
                    var newCache = new Dictionary <string, List <BaseData> >(BaseDataSourceCache)
                    {
                        [cacheKey] = cache
                    };

                    if (BaseDataSourceCache.Count > CacheSize)
                    {
                        var removeCount = 0;
                        // we remove a portion of the first in entries
                        while (++removeCount < (CacheSize / 4))
                        {
                            newCache.Remove(CacheKeys.Dequeue());
                        }
                        // update the cache instance
                        BaseDataSourceCache = newCache;
                    }
                    else
                    {
                        // update the cache instance
                        BaseDataSourceCache = newCache;
                    }
                }
            }

            if (cache == null)
            {
                throw new InvalidOperationException($"Cache should not be null. Key: {cacheKey}");
            }
            // Find the first data point 10 days (just in case) before the desired date
            // and subtract one item (just in case there was a time gap and data.Time is after _date)
            var frontier = _date.AddDays(-10);
            var index    = cache.FindIndex(data => data.Time > frontier);

            index = index > 0 ? (index - 1) : 0;
            foreach (var data in cache.Skip(index))
            {
                var clone = data.Clone();
                clone.Symbol = _config.Symbol;
                yield return(clone);
            }
        }