Lean  $LEAN_TAG$
FactorFile.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 
17 using System;
18 using System.IO;
19 using System.Linq;
20 using QuantConnect.Util;
21 using System.Collections;
22 using System.Collections.Generic;
23 
25 {
26  /// <summary>
27  /// Represents an entire factor file for a specified symbol
28  /// </summary>
29  public abstract class FactorFile<T> : IFactorProvider
30  where T : IFactorRow
31  {
32  /// <summary>
33  /// Keeping a reversed version is more performant that reversing it each time we need it
34  /// </summary>
35  protected List<DateTime> ReversedFactorFileDates { get; }
36 
37  /// <summary>
38  /// The factor file data rows sorted by date
39  /// </summary>
40  public SortedList<DateTime, List<T>> SortedFactorFileData { get; set; }
41 
42  /// <summary>
43  /// The minimum tradeable date for the symbol
44  /// </summary>
45  /// <remarks>
46  /// Some factor files have INF split values, indicating that the stock has so many splits
47  /// that prices can't be calculated with correct numerical precision.
48  /// To allow backtesting these symbols, we need to move the starting date
49  /// forward when reading the data.
50  /// Known symbols: GBSN, JUNI, NEWL
51  /// </remarks>
52  public DateTime? FactorFileMinimumDate { get; set; }
53 
54  /// <summary>
55  /// Gets the most recent factor change in the factor file
56  /// </summary>
58  .FirstOrDefault(time => time != Time.EndOfTime);
59 
60  /// <summary>
61  /// Gets the symbol this factor file represents
62  /// </summary>
63  public string Permtick { get; }
64 
65  /// <summary>
66  /// Initializes a new instance of the <see cref="FactorFile{T}"/> class.
67  /// </summary>
68  protected FactorFile(string permtick, IEnumerable<T> data, DateTime? factorFileMinimumDate = null)
69  {
70  Permtick = permtick.LazyToUpper();
71 
72  SortedFactorFileData = new SortedList<DateTime, List<T>>();
73  foreach (var row in data)
74  {
75  if (!SortedFactorFileData.TryGetValue(row.Date, out var factorFileRows))
76  {
77  SortedFactorFileData[row.Date] = factorFileRows = new List<T>();
78  }
79 
80  factorFileRows.Add(row);
81  }
82 
83  ReversedFactorFileDates = new List<DateTime>(SortedFactorFileData.Count);
84  foreach (var time in SortedFactorFileData.Keys.Reverse())
85  {
86  ReversedFactorFileDates.Add(time);
87  }
88 
89  FactorFileMinimumDate = factorFileMinimumDate;
90  }
91 
92  /// <summary>
93  /// Gets the price scale factor for the specified search date
94  /// </summary>
95  public abstract decimal GetPriceFactor(
96  DateTime searchDate,
97  DataNormalizationMode dataNormalizationMode,
98  DataMappingMode? dataMappingMode = null,
99  uint contractOffset = 0
100  );
101 
102  /// <summary>
103  /// Writes this factor file data to an enumerable of csv lines
104  /// </summary>
105  /// <returns>An enumerable of lines representing this factor file</returns>
106  public IEnumerable<string> GetFileFormat()
107  {
108  return SortedFactorFileData.SelectMany(kvp => kvp.Value.Select(row => row.GetFileFormat()));
109  }
110 
111  /// <summary>
112  /// Write the factor file to the correct place in the default Data folder
113  /// </summary>
114  /// <param name="symbol">The symbol this factor file represents</param>
115  public void WriteToFile(Symbol symbol)
116  {
117  var filePath = LeanData.GenerateRelativeFactorFilePath(symbol);
118  File.WriteAllLines(filePath, GetFileFormat());
119  }
120 
121  /// <summary>Returns an enumerator that iterates through the collection.</summary>
122  /// <returns>A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.</returns>
123  /// <filterpriority>1</filterpriority>
124  public IEnumerator<IFactorRow> GetEnumerator()
125  {
126  foreach (var kvp in SortedFactorFileData)
127  {
128  foreach (var factorRow in kvp.Value)
129  {
130  yield return factorRow;
131  }
132  }
133  }
134 
135  /// <summary>Returns an enumerator that iterates through a collection.</summary>
136  /// <returns>An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.</returns>
137  /// <filterpriority>2</filterpriority>
138  IEnumerator IEnumerable.GetEnumerator()
139  {
140  return GetEnumerator();
141  }
142  }
143 }