/*
* 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.Linq;
using QuantConnect.Util;
using System.Collections;
using System.Collections.Generic;
namespace QuantConnect.Data.Auxiliary
{
///
/// Represents an entire factor file for a specified symbol
///
public abstract class FactorFile : IFactorProvider
where T : IFactorRow
{
///
/// Keeping a reversed version is more performant that reversing it each time we need it
///
protected List ReversedFactorFileDates { get; }
///
/// The factor file data rows sorted by date
///
public SortedList> SortedFactorFileData { get; set; }
///
/// The minimum tradeable date for the symbol
///
///
/// Some factor files have INF split values, indicating that the stock has so many splits
/// that prices can't be calculated with correct numerical precision.
/// To allow backtesting these symbols, we need to move the starting date
/// forward when reading the data.
/// Known symbols: GBSN, JUNI, NEWL
///
public DateTime? FactorFileMinimumDate { get; set; }
///
/// Gets the most recent factor change in the factor file
///
public DateTime MostRecentFactorChange => ReversedFactorFileDates
.FirstOrDefault(time => time != Time.EndOfTime);
///
/// Gets the symbol this factor file represents
///
public string Permtick { get; }
///
/// Initializes a new instance of the class.
///
protected FactorFile(string permtick, IEnumerable data, DateTime? factorFileMinimumDate = null)
{
Permtick = permtick.LazyToUpper();
SortedFactorFileData = new SortedList>();
foreach (var row in data)
{
if (!SortedFactorFileData.TryGetValue(row.Date, out var factorFileRows))
{
SortedFactorFileData[row.Date] = factorFileRows = new List();
}
factorFileRows.Add(row);
}
ReversedFactorFileDates = new List(SortedFactorFileData.Count);
foreach (var time in SortedFactorFileData.Keys.Reverse())
{
ReversedFactorFileDates.Add(time);
}
FactorFileMinimumDate = factorFileMinimumDate;
}
///
/// Gets the price scale factor for the specified search date
///
public abstract decimal GetPriceFactor(
DateTime searchDate,
DataNormalizationMode dataNormalizationMode,
DataMappingMode? dataMappingMode = null,
uint contractOffset = 0
);
///
/// Writes this factor file data to an enumerable of csv lines
///
/// An enumerable of lines representing this factor file
public IEnumerable GetFileFormat()
{
return SortedFactorFileData.SelectMany(kvp => kvp.Value.Select(row => row.GetFileFormat()));
}
///
/// Write the factor file to the correct place in the default Data folder
///
/// The symbol this factor file represents
public void WriteToFile(Symbol symbol)
{
var filePath = LeanData.GenerateRelativeFactorFilePath(symbol);
File.WriteAllLines(filePath, GetFileFormat());
}
/// Returns an enumerator that iterates through the collection.
/// A that can be used to iterate through the collection.
/// 1
public IEnumerator GetEnumerator()
{
foreach (var kvp in SortedFactorFileData)
{
foreach (var factorRow in kvp.Value)
{
yield return factorRow;
}
}
}
/// Returns an enumerator that iterates through a collection.
/// An object that can be used to iterate through the collection.
/// 2
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}