/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.IO; using System.Collections.Generic; using QuantConnect.Data.Fundamental; namespace QuantConnect.Data.UniverseSelection { /// /// Coarse base fundamental data provider /// public class CoarseFundamentalDataProvider : BaseFundamentalDataProvider { private DateTime _date; private readonly Dictionary _coarseFundamental = new(); /// /// Will fetch the requested fundamental information for the requested time and symbol /// /// The expected data type /// The time to request this data for /// The security identifier /// The name of the fundamental property /// The fundamental information public override T Get(DateTime time, SecurityIdentifier securityIdentifier, FundamentalProperty name) { var enumName = Enum.GetName(name); lock (_coarseFundamental) { if (time == _date) { return GetProperty(securityIdentifier, enumName); } _date = time; var path = Path.Combine(Globals.DataFolder, "equity", "usa", "fundamental", "coarse", $"{time:yyyyMMdd}.csv"); var fileStream = DataProvider.Fetch(path); if (fileStream == null) { return GetDefault(); } _coarseFundamental.Clear(); using (var reader = new StreamReader(fileStream)) { while (!reader.EndOfStream) { var line = reader.ReadLine(); var coarse = Read(line, time); if (coarse != null) { _coarseFundamental[coarse.Symbol.ID] = coarse; } } } return GetProperty(securityIdentifier, enumName); } } /// /// Reads the given line and returns a CoarseFundamentalSource with the information within it /// public static CoarseFundamentalSource Read(string line, DateTime date) { try { var csv = line.Split(','); var coarse = new CoarseFundamentalSource { Symbol = new Symbol(SecurityIdentifier.Parse(csv[0]), csv[1]), Time = date, Value = csv[2].ToDecimal(), VolumeSetter = csv[3].ToInt64(), DollarVolumeSetter = (double)csv[4].ToDecimal() }; if (csv.Length > 5) { coarse.HasFundamentalDataSetter = csv[5].ConvertInvariant(); } if (csv.Length > 7) { coarse.PriceFactorSetter = csv[6].ToDecimal(); coarse.SplitFactorSetter = csv[7].ToDecimal(); } return coarse; } catch (Exception) { return null; } } private dynamic GetProperty(SecurityIdentifier securityIdentifier, string property) { if (!_coarseFundamental.TryGetValue(securityIdentifier, out var coarse)) { return GetDefault(); } switch (property) { case nameof(CoarseFundamental.Price): return coarse.Price; case nameof(CoarseFundamental.Value): return coarse.Value; case nameof(CoarseFundamental.Market): return coarse.Market; case nameof(CoarseFundamental.Volume): return coarse.Volume; case nameof(CoarseFundamental.PriceFactor): return coarse.PriceFactor; case nameof(CoarseFundamental.SplitFactor): return coarse.SplitFactor; case nameof(CoarseFundamental.DollarVolume): return coarse.DollarVolume; case nameof(CoarseFundamental.HasFundamentalData): return false; } return GetDefault(); } /// /// Coarse fundamental with setters /// public class CoarseFundamentalSource : CoarseFundamental { /// /// Property to set the volume of the Coarse Fundamental /// public long VolumeSetter { get; init; } /// /// Property to set the dollar volume of the Coarse Fundamental /// public double DollarVolumeSetter { get; init; } /// /// Property to set the price factor of the Coarse Fundamental /// public decimal PriceFactorSetter { get; set; } = 1; /// /// Property to set the split factor of the Coarse Fundamental /// public decimal SplitFactorSetter { get; set; } = 1; /// /// Property to indicate if the Coarse Fundamental has fundamental data /// public bool HasFundamentalDataSetter { get; set; } /// /// Gets the day's dollar volume for this symbol /// public override double DollarVolume => DollarVolumeSetter; /// /// Gets the day's total volume /// public override long Volume => VolumeSetter; /// /// Returns whether the symbol has fundamental data for the given date /// public override bool HasFundamentalData => HasFundamentalDataSetter; /// /// Gets the price factor for the given date /// public override decimal PriceFactor => PriceFactorSetter; /// /// Gets the split factor for the given date /// public override decimal SplitFactor => SplitFactorSetter; } } }