Lean  $LEAN_TAG$
CoarseFundamentalDataProvider.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using System.IO;
18 using System.Collections.Generic;
20 
22 {
23  /// <summary>
24  /// Coarse base fundamental data provider
25  /// </summary>
27  {
28  private DateTime _date;
29  private readonly Dictionary<SecurityIdentifier, CoarseFundamental> _coarseFundamental = new();
30 
31  /// <summary>
32  /// Will fetch the requested fundamental information for the requested time and symbol
33  /// </summary>
34  /// <typeparam name="T">The expected data type</typeparam>
35  /// <param name="time">The time to request this data for</param>
36  /// <param name="securityIdentifier">The security identifier</param>
37  /// <param name="name">The name of the fundamental property</param>
38  /// <returns>The fundamental information</returns>
39  public override T Get<T>(DateTime time, SecurityIdentifier securityIdentifier, FundamentalProperty name)
40  {
41  var enumName = Enum.GetName(name);
42  lock (_coarseFundamental)
43  {
44  if (time == _date)
45  {
46  return GetProperty<T>(securityIdentifier, enumName);
47  }
48  _date = time;
49 
50  var path = Path.Combine(Globals.DataFolder, "equity", "usa", "fundamental", "coarse", $"{time:yyyyMMdd}.csv");
51  var fileStream = DataProvider.Fetch(path);
52  if (fileStream == null)
53  {
54  return GetDefault<T>();
55  }
56 
57  _coarseFundamental.Clear();
58  using (var reader = new StreamReader(fileStream))
59  {
60  while (!reader.EndOfStream)
61  {
62  var line = reader.ReadLine();
63  var coarse = Read(line, time);
64  if (coarse != null)
65  {
66  _coarseFundamental[coarse.Symbol.ID] = coarse;
67  }
68  }
69  }
70 
71  return GetProperty<T>(securityIdentifier, enumName);
72  }
73  }
74 
75  /// <summary>
76  /// Reads the given line and returns a CoarseFundamentalSource with the information within it
77  /// </summary>
78  public static CoarseFundamentalSource Read(string line, DateTime date)
79  {
80  try
81  {
82  var csv = line.Split(',');
83  var coarse = new CoarseFundamentalSource
84  {
85  Symbol = new Symbol(SecurityIdentifier.Parse(csv[0]), csv[1]),
86  Time = date,
87  Value = csv[2].ToDecimal(),
88  VolumeSetter = csv[3].ToInt64(),
89  DollarVolumeSetter = (double)csv[4].ToDecimal()
90  };
91 
92  if (csv.Length > 5)
93  {
94  coarse.HasFundamentalDataSetter = csv[5].ConvertInvariant<bool>();
95  }
96 
97  if (csv.Length > 7)
98  {
99  coarse.PriceFactorSetter = csv[6].ToDecimal();
100  coarse.SplitFactorSetter = csv[7].ToDecimal();
101  }
102 
103  return coarse;
104  }
105  catch (Exception)
106  {
107  return null;
108  }
109 
110  }
111 
112  private dynamic GetProperty<T>(SecurityIdentifier securityIdentifier, string property)
113  {
114  if (!_coarseFundamental.TryGetValue(securityIdentifier, out var coarse))
115  {
116  return GetDefault<T>();
117  }
118 
119  switch (property)
120  {
121  case nameof(CoarseFundamental.Price):
122  return coarse.Price;
123  case nameof(CoarseFundamental.Value):
124  return coarse.Value;
125  case nameof(CoarseFundamental.Market):
126  return coarse.Market;
127  case nameof(CoarseFundamental.Volume):
128  return coarse.Volume;
129  case nameof(CoarseFundamental.PriceFactor):
130  return coarse.PriceFactor;
131  case nameof(CoarseFundamental.SplitFactor):
132  return coarse.SplitFactor;
133  case nameof(CoarseFundamental.DollarVolume):
134  return coarse.DollarVolume;
135  case nameof(CoarseFundamental.HasFundamentalData):
136  return false;
137  }
138 
139  return GetDefault<T>();
140  }
141 
142  /// <summary>
143  /// Coarse fundamental with setters
144  /// </summary>
146  {
147  /// <summary>
148  /// Property to set the volume of the Coarse Fundamental
149  /// </summary>
150  public long VolumeSetter { get; init; }
151 
152  /// <summary>
153  /// Property to set the dollar volume of the Coarse Fundamental
154  /// </summary>
155  public double DollarVolumeSetter { get; init; }
156 
157  /// <summary>
158  /// Property to set the price factor of the Coarse Fundamental
159  /// </summary>
160  public decimal PriceFactorSetter { get; set; } = 1;
161 
162  /// <summary>
163  /// Property to set the split factor of the Coarse Fundamental
164  /// </summary>
165  public decimal SplitFactorSetter { get; set; } = 1;
166 
167  /// <summary>
168  /// Property to indicate if the Coarse Fundamental has fundamental data
169  /// </summary>
170  public bool HasFundamentalDataSetter { get; set; }
171 
172  /// <summary>
173  /// Gets the day's dollar volume for this symbol
174  /// </summary>
175  public override double DollarVolume => DollarVolumeSetter;
176 
177  /// <summary>
178  /// Gets the day's total volume
179  /// </summary>
180  public override long Volume => VolumeSetter;
181 
182  /// <summary>
183  /// Returns whether the symbol has fundamental data for the given date
184  /// </summary>
186 
187  /// <summary>
188  /// Gets the price factor for the given date
189  /// </summary>
190  public override decimal PriceFactor => PriceFactorSetter;
191 
192  /// <summary>
193  /// Gets the split factor for the given date
194  /// </summary>
195  public override decimal SplitFactor => SplitFactorSetter;
196  }
197  }
198 }