/// <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; }