/// <summary>
        /// Creates an enumerator to read the specified request
        /// </summary>
        /// <param name="request">The subscription request to be read</param>
        /// <param name="dataFileProvider">Provider used to get data when it is not present on disk</param>
        /// <returns>An enumerator reading the subscription request</returns>
        public IEnumerator<BaseData> CreateEnumerator(SubscriptionRequest request, IDataFileProvider dataFileProvider)
        {
            var tradableDays = _tradableDaysProvider(request);

            var fineFundamental = new FineFundamental();
            var fineFundamentalConfiguration = new SubscriptionDataConfig(request.Configuration, typeof(FineFundamental), request.Security.Symbol);

            return (
                from date in tradableDays

                let fineFundamentalSource = GetSource(fineFundamental, fineFundamentalConfiguration, date)
                let fineFundamentalFactory = SubscriptionDataSourceReader.ForSource(fineFundamentalSource, dataFileProvider, fineFundamentalConfiguration, date, false)
                let fineFundamentalForDate = (FineFundamental)fineFundamentalFactory.Read(fineFundamentalSource).FirstOrDefault()

                select new FineFundamental
                {
                    DataType = MarketDataType.Auxiliary,
                    Symbol = request.Configuration.Symbol,
                    Time = date,
                    CompanyReference = fineFundamentalForDate != null ? fineFundamentalForDate.CompanyReference : new CompanyReference(),
                    SecurityReference = fineFundamentalForDate != null ? fineFundamentalForDate.SecurityReference : new SecurityReference(),
                    FinancialStatements = fineFundamentalForDate != null ? fineFundamentalForDate.FinancialStatements : new FinancialStatements(),
                    EarningReports = fineFundamentalForDate != null ? fineFundamentalForDate.EarningReports : new EarningReports(),
                    OperationRatios = fineFundamentalForDate != null ? fineFundamentalForDate.OperationRatios : new OperationRatios(),
                    EarningRatios = fineFundamentalForDate != null ? fineFundamentalForDate.EarningRatios : new EarningRatios(),
                    ValuationRatios = fineFundamentalForDate != null ? fineFundamentalForDate.ValuationRatios : new ValuationRatios()
                }
                ).GetEnumerator();
        }
        /// <summary>
        /// Returns a SubscriptionDataSource for the FineFundamental class, 
        /// returning data from a previous date if not available for the requested date
        /// </summary>
        private SubscriptionDataSource GetSource(FineFundamental fine, SubscriptionDataConfig config, DateTime date)
        {
            var source = fine.GetSource(config, date, false);

            var fileName = date.ToString("yyyyMMdd");

            if (!File.Exists(source.Source))
            {
                if (_lastUsedFileName == null)
                {
                    // find first file date
                    var path = Path.GetDirectoryName(source.Source) ?? string.Empty;
                    if (string.IsNullOrEmpty(path) || !Directory.Exists(path))
                        return source;

                    var firstFileName = Path.GetFileNameWithoutExtension(Directory.GetFiles(path, "*.zip").OrderBy(x => x).First());
                    var firstDate = DateTime.ParseExact(firstFileName, "yyyyMMdd", CultureInfo.InvariantCulture);

                    // requested date before first date, return current invalid source anyway
                    if (date < firstDate)
                        return source;

                    // requested date after first date, save date of first existing file
                    _lastUsedFileName = firstFileName;

                    // loop back in time until we find an existing file
                    while (string.CompareOrdinal(fileName, _lastUsedFileName) > 0)
                    {
                        // get previous date
                        date = date.AddDays(-1);

                        // get file name for this date
                        source = fine.GetSource(config, date, false);
                        fileName = Path.GetFileNameWithoutExtension(source.Source);

                        if (!File.Exists(source.Source))
                            continue;

                        // we found the file, save its name and return the source
                        _lastUsedFileName = fileName;

                        break;
                    }
                }
                else
                {
                    // return source for last existing file date
                    date = DateTime.ParseExact(_lastUsedFileName, "yyyyMMdd", CultureInfo.InvariantCulture);
                    source = fine.GetSource(config, date, false);
                }
            }
            else
            {
                _lastUsedFileName = fileName;
            }

            return source;
        }