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