Lean  $LEAN_TAG$
QCAlgorithm.History.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 NodaTime;
18 using System.Linq;
19 using QuantConnect.Data;
20 using QuantConnect.Util;
24 using System.Collections.Generic;
25 using QuantConnect.Python;
26 using Python.Runtime;
29 
30 namespace QuantConnect.Algorithm
31 {
32  public partial class QCAlgorithm
33  {
34  private bool _dataDictionaryTickWarningSent;
35 
36  /// <summary>
37  /// Gets or sets the history provider for the algorithm
38  /// </summary>
40  {
41  get;
42  set;
43  }
44 
45  /// <summary>
46  /// Gets whether or not this algorithm is still warming up
47  /// </summary>
48  [DocumentationAttribute(HistoricalData)]
49  public bool IsWarmingUp
50  {
51  get;
52  private set;
53  }
54 
55  /// <summary>
56  /// Sets the warm up period to the specified value
57  /// </summary>
58  /// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
59  [DocumentationAttribute(HistoricalData)]
60  public void SetWarmup(TimeSpan timeSpan)
61  {
62  SetWarmUp(timeSpan, null);
63  }
64 
65  /// <summary>
66  /// Sets the warm up period to the specified value
67  /// </summary>
68  /// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
69  [DocumentationAttribute(HistoricalData)]
70  public void SetWarmUp(TimeSpan timeSpan)
71  {
72  SetWarmup(timeSpan);
73  }
74 
75  /// <summary>
76  /// Sets the warm up period to the specified value
77  /// </summary>
78  /// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
79  /// <param name="resolution">The resolution to request</param>
80  [DocumentationAttribute(HistoricalData)]
81  public void SetWarmup(TimeSpan timeSpan, Resolution? resolution)
82  {
83  SetWarmup(null, timeSpan, resolution);
84  }
85 
86  /// <summary>
87  /// Sets the warm up period to the specified value
88  /// </summary>
89  /// <param name="timeSpan">The amount of time to warm up, this does not take into account market hours/weekends</param>
90  /// <param name="resolution">The resolution to request</param>
91  [DocumentationAttribute(HistoricalData)]
92  public void SetWarmUp(TimeSpan timeSpan, Resolution? resolution)
93  {
94  SetWarmup(timeSpan, resolution);
95  }
96 
97  /// <summary>
98  /// Sets the warm up period by resolving a start date that would send that amount of data into
99  /// the algorithm. The highest (smallest) resolution in the securities collection will be used.
100  /// For example, if an algorithm has minute and daily data and 200 bars are requested, that would
101  /// use 200 minute bars.
102  /// </summary>
103  /// <param name="barCount">The number of data points requested for warm up</param>
104  [DocumentationAttribute(HistoricalData)]
105  public void SetWarmup(int barCount)
106  {
107  SetWarmUp(barCount, null);
108  }
109 
110  /// <summary>
111  /// Sets the warm up period by resolving a start date that would send that amount of data into
112  /// the algorithm. The highest (smallest) resolution in the securities collection will be used.
113  /// For example, if an algorithm has minute and daily data and 200 bars are requested, that would
114  /// use 200 minute bars.
115  /// </summary>
116  /// <param name="barCount">The number of data points requested for warm up</param>
117  [DocumentationAttribute(HistoricalData)]
118  public void SetWarmUp(int barCount)
119  {
120  SetWarmup(barCount);
121  }
122 
123  /// <summary>
124  /// Sets the warm up period by resolving a start date that would send that amount of data into
125  /// the algorithm.
126  /// </summary>
127  /// <param name="barCount">The number of data points requested for warm up</param>
128  /// <param name="resolution">The resolution to request</param>
129  [DocumentationAttribute(HistoricalData)]
130  public void SetWarmup(int barCount, Resolution? resolution)
131  {
132  SetWarmup(barCount, null, resolution);
133  }
134 
135  /// <summary>
136  /// Sets the warm up period by resolving a start date that would send that amount of data into
137  /// the algorithm.
138  /// </summary>
139  /// <param name="barCount">The number of data points requested for warm up</param>
140  /// <param name="resolution">The resolution to request</param>
141  [DocumentationAttribute(HistoricalData)]
142  public void SetWarmUp(int barCount, Resolution? resolution)
143  {
144  SetWarmup(barCount, resolution);
145  }
146 
147  /// <summary>
148  /// Sets <see cref="IAlgorithm.IsWarmingUp"/> to false to indicate this algorithm has finished its warm up
149  /// </summary>
150  [DocumentationAttribute(HistoricalData)]
151  public void SetFinishedWarmingUp()
152  {
153  IsWarmingUp = false;
154  }
155 
156  /// <summary>
157  /// Message for exception that is thrown when the implicit conversion between symbol and string fails
158  /// </summary>
159  private readonly string _symbolEmptyErrorMessage = "Cannot create history for the given ticker. " +
160  "Either explicitly use a symbol object to make the history request " +
161  "or ensure the symbol has been added using the AddSecurity() method before making the history request.";
162 
163  /// <summary>
164  /// Gets the history requests required for provide warm up data for the algorithm
165  /// </summary>
166  /// <returns></returns>
167  [DocumentationAttribute(HistoricalData)]
168  private bool TryGetWarmupHistoryStartTime(out DateTime result)
169  {
170  result = Time;
171 
172  if (_warmupBarCount.HasValue)
173  {
174  var symbols = Securities.Keys;
175  if (symbols.Count != 0)
176  {
177  var startTimeUtc = CreateBarCountHistoryRequests(symbols, _warmupBarCount.Value, Settings.WarmupResolution)
178  .DefaultIfEmpty()
179  .Min(request => request == null ? default : request.StartTimeUtc);
180  if (startTimeUtc != default)
181  {
182  result = startTimeUtc.ConvertFromUtc(TimeZone);
183  return true;
184  }
185  }
186 
187  var defaultResolutionToUse = UniverseSettings.Resolution;
188  if (Settings.WarmupResolution.HasValue)
189  {
190  defaultResolutionToUse = Settings.WarmupResolution.Value;
191  }
192 
193  // if the algorithm has no added security, let's take a look at the universes to determine
194  // what the start date should be used. Defaulting to always open
195  result = Time - _warmupBarCount.Value * defaultResolutionToUse.ToTimeSpan();
196 
197  foreach (var universe in UniverseManager.Values)
198  {
199  var config = universe.Configuration;
200  var resolution = universe.Configuration.Resolution;
201  if (Settings.WarmupResolution.HasValue)
202  {
203  resolution = Settings.WarmupResolution.Value;
204  }
205  var exchange = MarketHoursDatabase.GetExchangeHours(config);
206  var start = _historyRequestFactory.GetStartTimeAlgoTz(config.Symbol, _warmupBarCount.Value, resolution, exchange, config.DataTimeZone, config.Type);
207  // we choose the min start
208  result = result < start ? result : start;
209  }
210  return true;
211  }
212  if (_warmupTimeSpan.HasValue)
213  {
214  result = Time - _warmupTimeSpan.Value;
215  return true;
216  }
217 
218  return false;
219  }
220 
221  /// <summary>
222  /// Get the history for all configured securities over the requested span.
223  /// This will use the resolution and other subscription settings for each security.
224  /// The symbols must exist in the Securities collection.
225  /// </summary>
226  /// <param name="span">The span over which to request data. This is a calendar span, so take into consideration weekends and such</param>
227  /// <param name="resolution">The resolution to request</param>
228  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
229  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
230  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
231  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
232  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
233  /// For example, 0 will use the front month, 1 will use the back month contract</param>
234  /// <returns>An enumerable of slice containing data over the most recent span for all configured securities</returns>
235  [DocumentationAttribute(HistoricalData)]
236  public IEnumerable<Slice> History(TimeSpan span, Resolution? resolution = null, bool? fillForward = null, bool? extendedMarketHours = null,
237  DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
238  {
239  return History(Securities.Keys, Time - span, Time, resolution, fillForward, extendedMarketHours, dataMappingMode,
240  dataNormalizationMode, contractDepthOffset).Memoize();
241  }
242 
243  /// <summary>
244  /// Get the history for all configured securities over the requested span.
245  /// This will use the resolution and other subscription settings for each security.
246  /// The symbols must exist in the Securities collection.
247  /// </summary>
248  /// <param name="periods">The number of bars to request</param>
249  /// <param name="resolution">The resolution to request</param>
250  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
251  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
252  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
253  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
254  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
255  /// For example, 0 will use the front month, 1 will use the back month contract</param>
256  /// <returns>An enumerable of slice containing data over the most recent span for all configured securities</returns>
257  [DocumentationAttribute(HistoricalData)]
258  public IEnumerable<Slice> History(int periods, Resolution? resolution = null, bool? fillForward = null, bool? extendedMarketHours = null,
259  DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
260  {
261  return History(Securities.Keys, periods, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
262  contractDepthOffset).Memoize();
263  }
264 
265  /// <summary>
266  /// Get the history for all configured securities over the requested span.
267  /// This will use the resolution and other subscription settings for each security.
268  /// The symbols must exist in the Securities collection.
269  /// </summary>
270  /// <param name="universe">The universe to fetch the data for</param>
271  /// <param name="periods">The number of bars to request</param>
272  /// <param name="resolution">The resolution to request</param>
273  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
274  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
275  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
276  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
277  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
278  /// For example, 0 will use the front month, 1 will use the back month contract</param>
279  /// <returns>An enumerable of slice containing data over the most recent span for all configured securities</returns>
280  [DocumentationAttribute(HistoricalData)]
281  public IEnumerable<BaseDataCollection> History(Universe universe, int periods, Resolution? resolution = null, bool? fillForward = null, bool? extendedMarketHours = null,
282  DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
283  {
284  var symbols = new[] { universe.Configuration.Symbol };
285  resolution ??= universe.Configuration.Resolution;
286  CheckPeriodBasedHistoryRequestResolution(symbols, resolution, universe.Configuration.Type);
287  var requests = CreateBarCountHistoryRequests(symbols, universe.Configuration.Type, periods, resolution, fillForward, extendedMarketHours, dataMappingMode,
288  dataNormalizationMode, contractDepthOffset);
289  return GetDataTypedHistory<BaseDataCollection>(requests).Select(x => x.Values.Single());
290  }
291 
292  /// <summary>
293  /// Gets the historical data for all symbols of the requested type over the requested span.
294  /// The symbol's configured values for resolution and fill forward behavior will be used
295  /// The symbols must exist in the Securities collection.
296  /// </summary>
297  /// <param name="universe">The universe to fetch the data for</param>
298  /// <param name="span">The span over which to request data. This is a calendar span, so take into consideration weekends and such</param>
299  /// <param name="resolution">The resolution to request</param>
300  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
301  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
302  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
303  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
304  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
305  /// For example, 0 will use the front month, 1 will use the back month contract</param>
306  /// <returns>An enumerable of slice containing the requested historical data</returns>
307  [DocumentationAttribute(HistoricalData)]
308  public IEnumerable<BaseDataCollection> History(Universe universe, TimeSpan span, Resolution? resolution = null, bool? fillForward = null,
309  bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null,
310  int? contractDepthOffset = null)
311  {
312  return History(universe, Time - span, Time, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset);
313  }
314 
315  /// <summary>
316  /// Gets the historical data for the specified symbols between the specified dates. The symbols must exist in the Securities collection.
317  /// </summary>
318  /// <param name="universe">The universe to fetch the data for</param>
319  /// <param name="start">The start time in the algorithm's time zone</param>
320  /// <param name="end">The end time in the algorithm's time zone</param>
321  /// <param name="resolution">The resolution to request</param>
322  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
323  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
324  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
325  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
326  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
327  /// For example, 0 will use the front month, 1 will use the back month contract</param>
328  /// <returns>An enumerable of slice containing the requested historical data</returns>
329  [DocumentationAttribute(HistoricalData)]
330  public IEnumerable<BaseDataCollection> History(Universe universe, DateTime start, DateTime end, Resolution? resolution = null,
331  bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
332  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
333  {
334  resolution ??= universe.Configuration.Resolution;
335  var requests = CreateDateRangeHistoryRequests(new[] { universe.Symbol }, universe.DataType, start, end, resolution, fillForward, extendedMarketHours,
336  dataMappingMode, dataNormalizationMode, contractDepthOffset);
337  return GetDataTypedHistory<BaseDataCollection>(requests).Select(x => x.Values.Single());
338  }
339 
340  /// <summary>
341  /// Gets the historical data for all symbols of the requested type over the requested span.
342  /// The symbol's configured values for resolution and fill forward behavior will be used
343  /// The symbols must exist in the Securities collection.
344  /// </summary>
345  /// <param name="span">The span over which to retrieve recent historical data</param>
346  /// <param name="resolution">The resolution to request</param>
347  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
348  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
349  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
350  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
351  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
352  /// For example, 0 will use the front month, 1 will use the back month contract</param>
353  /// <returns>An enumerable of slice containing the requested historical data</returns>
354  [DocumentationAttribute(HistoricalData)]
355  public IEnumerable<DataDictionary<T>> History<T>(TimeSpan span, Resolution? resolution = null, bool? fillForward = null,
356  bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null,
357  int? contractDepthOffset = null)
358  where T : IBaseData
359  {
360  return History<T>(Securities.Keys, span, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
361  contractDepthOffset).Memoize();
362  }
363 
364  /// <summary>
365  /// Gets the historical data for the specified symbols over the requested span.
366  /// The symbols must exist in the Securities collection.
367  /// </summary>
368  /// <typeparam name="T">The data type of the symbols</typeparam>
369  /// <param name="symbols">The symbols to retrieve historical data for</param>
370  /// <param name="span">The span over which to retrieve recent historical data</param>
371  /// <param name="resolution">The resolution to request</param>
372  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
373  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
374  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
375  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
376  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
377  /// For example, 0 will use the front month, 1 will use the back month contract</param>
378  /// <returns>An enumerable of slice containing the requested historical data</returns>
379  [DocumentationAttribute(HistoricalData)]
380  public IEnumerable<DataDictionary<T>> History<T>(IEnumerable<Symbol> symbols, TimeSpan span, Resolution? resolution = null,
381  bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
382  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
383  where T : IBaseData
384  {
385  return History<T>(symbols, Time - span, Time, resolution, fillForward, extendedMarketHours, dataMappingMode,
386  dataNormalizationMode, contractDepthOffset).Memoize();
387  }
388 
389  /// <summary>
390  /// Gets the historical data for the specified symbols. The exact number of bars will be returned for
391  /// each symbol. This may result in some data start earlier/later than others due to when various
392  /// exchanges are open. The symbols must exist in the Securities collection.
393  /// </summary>
394  /// <typeparam name="T">The data type of the symbols</typeparam>
395  /// <param name="symbols">The symbols to retrieve historical data for</param>
396  /// <param name="periods">The number of bars to request</param>
397  /// <param name="resolution">The resolution to request</param>
398  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
399  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
400  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
401  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
402  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
403  /// For example, 0 will use the front month, 1 will use the back month contract</param>
404  /// <returns>An enumerable of slice containing the requested historical data</returns>
405  [DocumentationAttribute(HistoricalData)]
406  public IEnumerable<DataDictionary<T>> History<T>(IEnumerable<Symbol> symbols, int periods, Resolution? resolution = null,
407  bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
408  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
409  where T : IBaseData
410  {
411  CheckPeriodBasedHistoryRequestResolution(symbols, resolution, typeof(T));
412  var requests = CreateBarCountHistoryRequests(symbols, typeof(T), periods, resolution, fillForward, extendedMarketHours, dataMappingMode,
413  dataNormalizationMode, contractDepthOffset);
414  return GetDataTypedHistory<T>(requests);
415  }
416 
417  /// <summary>
418  /// Gets the historical data for the specified symbols between the specified dates. The symbols must exist in the Securities collection.
419  /// </summary>
420  /// <typeparam name="T">The data type of the symbols</typeparam>
421  /// <param name="symbols">The symbols to retrieve historical data for</param>
422  /// <param name="start">The start time in the algorithm's time zone</param>
423  /// <param name="end">The end time in the algorithm's time zone</param>
424  /// <param name="resolution">The resolution to request</param>
425  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
426  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
427  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
428  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
429  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
430  /// For example, 0 will use the front month, 1 will use the back month contract</param>
431  /// <returns>An enumerable of slice containing the requested historical data</returns>
432  [DocumentationAttribute(HistoricalData)]
433  public IEnumerable<DataDictionary<T>> History<T>(IEnumerable<Symbol> symbols, DateTime start, DateTime end, Resolution? resolution = null,
434  bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
435  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
436  where T : IBaseData
437  {
438  var requests = CreateDateRangeHistoryRequests(symbols, typeof(T), start, end, resolution, fillForward, extendedMarketHours,
439  dataMappingMode, dataNormalizationMode, contractDepthOffset);
440  return GetDataTypedHistory<T>(requests);
441  }
442 
443  /// <summary>
444  /// Gets the historical data for the specified symbol over the request span. The symbol must exist in the Securities collection.
445  /// </summary>
446  /// <typeparam name="T">The data type of the symbol</typeparam>
447  /// <param name="symbol">The symbol to retrieve historical data for</param>
448  /// <param name="span">The span over which to retrieve recent historical data</param>
449  /// <param name="resolution">The resolution to request</param>
450  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
451  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
452  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
453  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
454  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
455  /// For example, 0 will use the front month, 1 will use the back month contract</param>
456  /// <returns>An enumerable of slice containing the requested historical data</returns>
457  [DocumentationAttribute(HistoricalData)]
458  public IEnumerable<T> History<T>(Symbol symbol, TimeSpan span, Resolution? resolution = null, bool? fillForward = null,
459  bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null,
460  int? contractDepthOffset = null)
461  where T : IBaseData
462  {
463  return History<T>(symbol, Time - span, Time, resolution, fillForward, extendedMarketHours, dataMappingMode,
464  dataNormalizationMode, contractDepthOffset).Memoize();
465  }
466 
467  /// <summary>
468  /// Gets the historical data for the specified symbol. The exact number of bars will be returned.
469  /// The symbol must exist in the Securities collection.
470  /// </summary>
471  /// <param name="symbol">The symbol to retrieve historical data for</param>
472  /// <param name="periods">The number of bars to request</param>
473  /// <param name="resolution">The resolution to request</param>
474  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
475  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
476  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
477  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
478  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
479  /// For example, 0 will use the front month, 1 will use the back month contract</param>
480  /// <returns>An enumerable of slice containing the requested historical data</returns>
481  [DocumentationAttribute(HistoricalData)]
482  public IEnumerable<TradeBar> History(Symbol symbol, int periods, Resolution? resolution = null, bool? fillForward = null,
483  bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null,
484  int? contractDepthOffset = null)
485  {
486  if (symbol == null) throw new ArgumentException(_symbolEmptyErrorMessage);
487 
488  resolution = GetResolution(symbol, resolution, typeof(TradeBar));
489  CheckPeriodBasedHistoryRequestResolution(new[] { symbol }, resolution, typeof(TradeBar));
490  var marketHours = GetMarketHours(symbol);
491  var start = _historyRequestFactory.GetStartTimeAlgoTz(symbol, periods, resolution.Value, marketHours.ExchangeHours,
492  marketHours.DataTimeZone, typeof(TradeBar), extendedMarketHours);
493 
494  return History(symbol, start, Time, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
495  contractDepthOffset);
496  }
497 
498  /// <summary>
499  /// Gets the historical data for the specified symbol. The exact number of bars will be returned.
500  /// The symbol must exist in the Securities collection.
501  /// </summary>
502  /// <typeparam name="T">The data type of the symbol</typeparam>
503  /// <param name="symbol">The symbol to retrieve historical data for</param>
504  /// <param name="periods">The number of bars to request</param>
505  /// <param name="resolution">The resolution to request</param>
506  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
507  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
508  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
509  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
510  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
511  /// For example, 0 will use the front month, 1 will use the back month contract</param>
512  /// <returns>An enumerable of slice containing the requested historical data</returns>
513  [DocumentationAttribute(HistoricalData)]
514  public IEnumerable<T> History<T>(Symbol symbol, int periods, Resolution? resolution = null, bool? fillForward = null,
515  bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null,
516  int? contractDepthOffset = null)
517  where T : IBaseData
518  {
519  resolution = GetResolution(symbol, resolution, typeof(T));
520  CheckPeriodBasedHistoryRequestResolution(new[] { symbol }, resolution, typeof(T));
521  var requests = CreateBarCountHistoryRequests(new[] { symbol }, typeof(T), periods, resolution, fillForward, extendedMarketHours,
522  dataMappingMode, dataNormalizationMode, contractDepthOffset);
523  return GetDataTypedHistory<T>(requests, symbol);
524  }
525 
526  /// <summary>
527  /// Gets the historical data for the specified symbol between the specified dates. The symbol must exist in the Securities collection.
528  /// </summary>
529  /// <param name="symbol">The symbol to retrieve historical data for</param>
530  /// <param name="start">The start time in the algorithm's time zone</param>
531  /// <param name="end">The end time in the algorithm's time zone</param>
532  /// <param name="resolution">The resolution to request</param>
533  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
534  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
535  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
536  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
537  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
538  /// For example, 0 will use the front month, 1 will use the back month contract</param>
539  /// <returns>An enumerable of slice containing the requested historical data</returns>
540  [DocumentationAttribute(HistoricalData)]
541  public IEnumerable<T> History<T>(Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null, bool? fillForward = null,
542  bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null,
543  int? contractDepthOffset = null)
544  where T : IBaseData
545  {
546  var requests = CreateDateRangeHistoryRequests(new[] { symbol }, typeof(T), start, end, resolution, fillForward, extendedMarketHours,
547  dataMappingMode, dataNormalizationMode, contractDepthOffset);
548  return GetDataTypedHistory<T>(requests, symbol);
549  }
550 
551  /// <summary>
552  /// Gets the historical data for the specified symbol over the request span. The symbol must exist in the Securities collection.
553  /// </summary>
554  /// <param name="symbol">The symbol to retrieve historical data for</param>
555  /// <param name="span">The span over which to retrieve recent historical data</param>
556  /// <param name="resolution">The resolution to request</param>
557  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
558  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
559  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
560  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
561  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
562  /// For example, 0 will use the front month, 1 will use the back month contract</param>
563  /// <returns>An enumerable of slice containing the requested historical data</returns>
564  [DocumentationAttribute(HistoricalData)]
565  public IEnumerable<TradeBar> History(Symbol symbol, TimeSpan span, Resolution? resolution = null, bool? fillForward = null,
566  bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null,
567  int? contractDepthOffset = null)
568  {
569  return History(symbol, Time - span, Time, resolution, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
570  contractDepthOffset);
571  }
572 
573  /// <summary>
574  /// Gets the historical data for the specified symbol over the request span. The symbol must exist in the Securities collection.
575  /// </summary>
576  /// <param name="symbol">The symbol to retrieve historical data for</param>
577  /// <param name="start">The start time in the algorithm's time zone</param>
578  /// <param name="end">The end time in the algorithm's time zone</param>
579  /// <param name="resolution">The resolution to request</param>
580  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
581  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
582  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
583  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
584  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
585  /// For example, 0 will use the front month, 1 will use the back month contract</param>
586  /// <returns>An enumerable of slice containing the requested historical data</returns>
587  [DocumentationAttribute(HistoricalData)]
588  public IEnumerable<TradeBar> History(Symbol symbol, DateTime start, DateTime end, Resolution? resolution = null, bool? fillForward = null,
589  bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null,
590  int? contractDepthOffset = null)
591  {
592  var securityType = symbol.ID.SecurityType;
593  if (securityType == SecurityType.Forex || securityType == SecurityType.Cfd)
594  {
595  Error("Calling History<TradeBar> method on a Forex or CFD security will return an empty result. Please use the generic version with QuoteBar type parameter.");
596  }
597 
598  var resolutionToUse = resolution ?? GetResolution(symbol, resolution, typeof(TradeBar));
599  if (resolutionToUse == Resolution.Tick)
600  {
601  throw new InvalidOperationException("Calling History<TradeBar> method with Resolution.Tick will return an empty result." +
602  " Please use the generic version with Tick type parameter or provide a list of Symbols to use the Slice history request API.");
603  }
604 
605  return History(new[] { symbol }, start, end, resolutionToUse, fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode,
606  contractDepthOffset).Get(symbol).Memoize();
607  }
608 
609  /// <summary>
610  /// Gets the historical data for the specified symbols over the requested span.
611  /// The symbol's configured values for resolution and fill forward behavior will be used
612  /// The symbols must exist in the Securities collection.
613  /// </summary>
614  /// <param name="symbols">The symbols to retrieve historical data for</param>
615  /// <param name="span">The span over which to retrieve recent historical data</param>
616  /// <param name="resolution">The resolution to request</param>
617  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
618  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
619  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
620  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
621  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
622  /// For example, 0 will use the front month, 1 will use the back month contract</param>
623  /// <returns>An enumerable of slice containing the requested historical data</returns>
624  [DocumentationAttribute(HistoricalData)]
625  public IEnumerable<Slice> History(IEnumerable<Symbol> symbols, TimeSpan span, Resolution? resolution = null, bool? fillForward = null,
626  bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null,
627  int? contractDepthOffset = null)
628  {
629  return History(symbols, Time - span, Time, resolution, fillForward, extendedMarketHours, dataMappingMode,
630  dataNormalizationMode, contractDepthOffset).Memoize();
631  }
632 
633  /// <summary>
634  /// Gets the historical data for the specified symbols. The exact number of bars will be returned for
635  /// each symbol. This may result in some data start earlier/later than others due to when various
636  /// exchanges are open. The symbols must exist in the Securities collection.
637  /// </summary>
638  /// <param name="symbols">The symbols to retrieve historical data for</param>
639  /// <param name="periods">The number of bars to request</param>
640  /// <param name="resolution">The resolution to request</param>
641  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
642  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
643  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
644  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
645  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
646  /// For example, 0 will use the front month, 1 will use the back month contract</param>
647  /// <returns>An enumerable of slice containing the requested historical data</returns>
648  [DocumentationAttribute(HistoricalData)]
649  public IEnumerable<Slice> History(IEnumerable<Symbol> symbols, int periods, Resolution? resolution = null, bool? fillForward = null,
650  bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null, DataNormalizationMode? dataNormalizationMode = null,
651  int? contractDepthOffset = null)
652  {
653  CheckPeriodBasedHistoryRequestResolution(symbols, resolution, null);
654  return History(CreateBarCountHistoryRequests(symbols, periods, resolution, fillForward, extendedMarketHours, dataMappingMode,
655  dataNormalizationMode, contractDepthOffset)).Memoize();
656  }
657 
658  /// <summary>
659  /// Gets the historical data for the specified symbols between the specified dates. The symbols must exist in the Securities collection.
660  /// </summary>
661  /// <param name="symbols">The symbols to retrieve historical data for</param>
662  /// <param name="start">The start time in the algorithm's time zone</param>
663  /// <param name="end">The end time in the algorithm's time zone</param>
664  /// <param name="resolution">The resolution to request</param>
665  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
666  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
667  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
668  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
669  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
670  /// For example, 0 will use the front month, 1 will use the back month contract</param>
671  /// <returns>An enumerable of slice containing the requested historical data</returns>
672  [DocumentationAttribute(HistoricalData)]
673  public IEnumerable<Slice> History(IEnumerable<Symbol> symbols, DateTime start, DateTime end, Resolution? resolution = null,
674  bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
675  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
676  {
677  return History(CreateDateRangeHistoryRequests(symbols, start, end, resolution, fillForward, extendedMarketHours, dataMappingMode,
678  dataNormalizationMode, contractDepthOffset)).Memoize();
679  }
680 
681  /// <summary>
682  /// Executes the specified history request
683  /// </summary>
684  /// <param name="request">the history request to execute</param>
685  /// <returns>An enumerable of slice satisfying the specified history request</returns>
686  [DocumentationAttribute(HistoricalData)]
687  public IEnumerable<Slice> History(HistoryRequest request)
688  {
689  return History(new[] { request }).Memoize();
690  }
691 
692  /// <summary>
693  /// Executes the specified history requests
694  /// </summary>
695  /// <param name="requests">the history requests to execute</param>
696  /// <returns>An enumerable of slice satisfying the specified history request</returns>
697  [DocumentationAttribute(HistoricalData)]
698  public IEnumerable<Slice> History(IEnumerable<HistoryRequest> requests)
699  {
700  return History(requests, TimeZone).Memoize();
701  }
702 
703  /// <summary>
704  /// Yields data to warmup a security for all it's subscribed data types
705  /// </summary>
706  /// <param name="security"><see cref="Security"/> object for which to retrieve historical data</param>
707  /// <returns>Securities historical data</returns>
708  [DocumentationAttribute(AddingData)]
709  [DocumentationAttribute(HistoricalData)]
710  public IEnumerable<BaseData> GetLastKnownPrices(Security security)
711  {
712  return GetLastKnownPrices(security.Symbol);
713  }
714 
715  /// <summary>
716  /// Yields data to warmup a security for all it's subscribed data types
717  /// </summary>
718  /// <param name="symbol">The symbol we want to get seed data for</param>
719  /// <returns>Securities historical data</returns>
720  [DocumentationAttribute(AddingData)]
721  [DocumentationAttribute(HistoricalData)]
722  public IEnumerable<BaseData> GetLastKnownPrices(Symbol symbol)
723  {
724  if (!HistoryRequestValid(symbol) || HistoryProvider == null)
725  {
726  return Enumerable.Empty<BaseData>();
727  }
728 
729  var result = new Dictionary<TickType, BaseData>();
730  Resolution? resolution = null;
731  Func<int, bool> requestData = period =>
732  {
733  var historyRequests = CreateBarCountHistoryRequests(new[] { symbol }, period)
734  .Select(request =>
735  {
736  // For speed and memory usage, use Resolution.Minute as the minimum resolution
737  request.Resolution = (Resolution)Math.Max((int)Resolution.Minute, (int)request.Resolution);
738  // force no fill forward behavior
739  request.FillForwardResolution = null;
740 
741  resolution = request.Resolution;
742  return request;
743  })
744  // request only those tick types we didn't get the data we wanted
745  .Where(request => !result.ContainsKey(request.TickType))
746  .ToList();
747  foreach (var slice in History(historyRequests))
748  {
749  for (var i = 0; i < historyRequests.Count; i++)
750  {
751  var historyRequest = historyRequests[i];
752  var data = slice.Get(historyRequest.DataType);
753  if (data.ContainsKey(symbol))
754  {
755  // keep the last data point per tick type
756  result[historyRequest.TickType] = (BaseData)data[symbol];
757  }
758  }
759  }
760  // true when all history requests tick types have a data point
761  return historyRequests.All(request => result.ContainsKey(request.TickType));
762  };
763 
764  if (!requestData(5))
765  {
766  if (resolution.HasValue)
767  {
768  // If the first attempt to get the last know price returns null, it maybe the case of an illiquid security.
769  // We increase the look-back period for this case accordingly to the resolution to cover 3 trading days
770  var periods =
771  resolution.Value == Resolution.Daily ? 3 :
772  resolution.Value == Resolution.Hour ? 24 : 1440;
773  requestData(periods);
774  }
775  else
776  {
777  // this shouldn't happen but just in case
779  $"QCAlgorithm.GetLastKnownPrices(): no history request was created for symbol {symbol} at {Time}");
780  }
781  }
782  // return the data ordered by time ascending
783  return result.Values.OrderBy(data => data.Time);
784  }
785 
786  /// <summary>
787  /// Get the last known price using the history provider.
788  /// Useful for seeding securities with the correct price
789  /// </summary>
790  /// <param name="security"><see cref="Security"/> object for which to retrieve historical data</param>
791  /// <returns>A single <see cref="BaseData"/> object with the last known price</returns>
792  [Obsolete("This method is obsolete please use 'GetLastKnownPrices' which will return the last data point" +
793  " for each type associated with the requested security")]
794  [DocumentationAttribute(AddingData)]
795  [DocumentationAttribute(HistoricalData)]
797  {
798  return GetLastKnownPrices(security.Symbol)
799  // since we are returning a single data point let's respect order
800  .OrderByDescending(data => GetTickTypeOrder(data.Symbol.SecurityType, LeanData.GetCommonTickTypeForCommonDataTypes(data.GetType(), data.Symbol.SecurityType)))
801  .LastOrDefault();
802  }
803 
804  /// <summary>
805  /// Centralized logic to get data typed history given a list of requests for the specified symbol.
806  /// This method is used to keep backwards compatibility for those History methods that expect an ArgumentException to be thrown
807  /// when the security and the requested data type do not match
808  /// </summary>
809  /// <remarks>
810  /// This method will check for Python custom data types in order to call the right Slice.Get dynamic method
811  /// </remarks>
812  private IEnumerable<T> GetDataTypedHistory<T>(IEnumerable<HistoryRequest> requests, Symbol symbol)
813  where T : IBaseData
814  {
815  var type = typeof(T);
816 
817  var historyRequests = requests.Where(x => x != null).ToList();
818  if (historyRequests.Count == 0)
819  {
820  throw new ArgumentException($"No history data could be fetched. " +
821  $"This could be due to the specified security not being of the requested type. Symbol: {symbol} Requested Type: {type.Name}");
822  }
823 
824  var slices = History(historyRequests, TimeZone);
825 
826  IEnumerable<T> result = null;
827 
828  // If T is a custom data coming from Python (a class derived from PythonData), T will get here as PythonData
829  // and not the actual custom type. We take care of this especial case by using a dynamic version of GetDataTypedHistory that
830  // receives the Python type, and we get it from the history requests.
831  if (type == typeof(PythonData))
832  {
833  result = GetPythonCustomDataTypeHistory(slices, historyRequests, symbol).OfType<T>();
834  }
835  // TODO: This is a patch to fix the issue with the Slice.GetImpl method returning only the last tick
836  // for each symbol instead of the whole list of ticks.
837  // The actual issue is Slice.GetImpl, so patch this can be removed right after it is properly addressed.
838  // A proposed solution making the Tick class a BaseDataCollection and make the Ticks class a dictionary Symbol->Tick instead of
839  // Symbol->List<Tick> so we can use the Slice.Get methods to collect all ticks in every slice instead of only the last one.
840  else if (type == typeof(Tick))
841  {
842  result = (IEnumerable<T>)slices.Select(x => x.Ticks).Where(x => x.ContainsKey(symbol)).SelectMany(x => x[symbol]);
843  }
844  else
845  {
846  result = slices.Get<T>(symbol);
847  }
848 
849  return result.Memoize();
850  }
851 
852  /// <summary>
853  /// Centralized logic to get data typed history for a given list of requests.
854  /// </summary>
855  /// <remarks>
856  /// This method will check for Python custom data types in order to call the right Slice.Get dynamic method
857  /// </remarks>
858  protected IEnumerable<DataDictionary<T>> GetDataTypedHistory<T>(IEnumerable<HistoryRequest> requests)
859  where T : IBaseData
860  {
861  var historyRequests = requests.Where(x => x != null).ToList();
862  var slices = History(historyRequests, TimeZone);
863 
864  IEnumerable<DataDictionary<T>> result = null;
865 
866  if (typeof(T) == typeof(PythonData))
867  {
868  result = GetPythonCustomDataTypeHistory(slices, historyRequests).OfType<DataDictionary<T>>();
869  }
870  else
871  {
872  if (typeof(T) == typeof(Tick) && !_dataDictionaryTickWarningSent)
873  {
874  _dataDictionaryTickWarningSent = true;
875  Debug("Warning: Multiple symbols Tick history will return the last tick per timestep. To access all ticks remove the 'Tick' type to use the History() returning Slice, all ticks can be accessed with Slice.Ticks.");
876  }
877 
878  if (typeof(T) == typeof(BaseDataCollection) && historyRequests[0].DataType != typeof(BaseDataCollection))
879  {
880  result = (IEnumerable<DataDictionary<T>>)slices.GetUniverseData();
881  }
882  else
883  {
884  result = slices.Get<T>();
885  }
886  }
887 
888  return result.Memoize();
889  }
890 
891  private IEnumerable<Slice> History(IEnumerable<HistoryRequest> requests, DateTimeZone timeZone)
892  {
893  // filter out any universe securities that may have made it this far
894  var filteredRequests = GetFilterestRequests(requests);
895 
896  // filter out future data to prevent look ahead bias
897  var history = HistoryProvider.GetHistory(filteredRequests, timeZone);
898 
899  if (PythonEngine.IsInitialized)
900  {
901  // add protection against potential python deadlocks
902  // with parallel history requests we reuse the data stack threads to serve the history calls because of this we need to make sure to release
903  // the GIL before waiting on the history request because there could be a work/job in the data stack queues which needs the GIL
904  return WrapPythonDataHistory(history);
905  }
906 
907  return history;
908  }
909 
910  private IEnumerable<HistoryRequest> GetFilterestRequests(IEnumerable<HistoryRequest> requests)
911  {
912  var sentMessage = false;
913  foreach (var request in requests.Where(hr => HistoryRequestValid(hr.Symbol)))
914  {
915  // prevent future requests
916  if (request.EndTimeUtc > UtcTime)
917  {
918  var endTimeUtc = UtcTime;
919  var startTimeUtc = request.StartTimeUtc;
920  if (request.StartTimeUtc > request.EndTimeUtc)
921  {
922  startTimeUtc = request.EndTimeUtc;
923  }
924 
925  yield return new HistoryRequest(startTimeUtc, endTimeUtc,
926  request.DataType, request.Symbol, request.Resolution, request.ExchangeHours,
927  request.DataTimeZone, request.FillForwardResolution, request.IncludeExtendedMarketHours,
928  request.IsCustomData, request.DataNormalizationMode, request.TickType, request.DataMappingMode,
929  request.ContractDepthOffset);
930 
931  if (!sentMessage)
932  {
933  sentMessage = true;
934  Debug("Request for future history modified to end now.");
935  }
936  }
937  else
938  {
939  yield return request;
940  }
941  }
942  }
943 
944  /// <summary>
945  /// Helper method to create history requests from a date range
946  /// </summary>
947  protected IEnumerable<HistoryRequest> CreateDateRangeHistoryRequests(IEnumerable<Symbol> symbols, DateTime startAlgoTz, DateTime endAlgoTz,
948  Resolution? resolution = null, bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
949  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
950  {
951  // Materialize the symbols to avoid multiple enumeration
952  var symbolsArray = symbols.ToArray();
954  symbolsArray,
955  Extensions.GetCustomDataTypeFromSymbols(symbolsArray),
956  startAlgoTz,
957  endAlgoTz,
958  resolution,
959  fillForward,
960  extendedMarketHours,
961  dataMappingMode,
962  dataNormalizationMode,
963  contractDepthOffset);
964  }
965 
966  /// <summary>
967  /// Helper method to create history requests from a date range with custom data type
968  /// </summary>
969  protected IEnumerable<HistoryRequest> CreateDateRangeHistoryRequests(IEnumerable<Symbol> symbols, Type requestedType, DateTime startAlgoTz, DateTime endAlgoTz,
970  Resolution? resolution = null, bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
971  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
972  {
973  return symbols.Where(HistoryRequestValid).SelectMany(x =>
974  {
975  var requests = new List<HistoryRequest>();
976 
977  foreach (var config in GetMatchingSubscriptions(x, requestedType, resolution))
978  {
979  var request = _historyRequestFactory.CreateHistoryRequest(config, startAlgoTz, endAlgoTz, GetExchangeHours(x, requestedType), resolution,
980  fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset);
981  requests.Add(request);
982  }
983 
984  return requests;
985  });
986  }
987 
988  /// <summary>
989  /// Helper methods to create a history request for the specified symbols and bar count
990  /// </summary>
991  private IEnumerable<HistoryRequest> CreateBarCountHistoryRequests(IEnumerable<Symbol> symbols, int periods, Resolution? resolution = null,
992  bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
993  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
994  {
995  // Materialize the symbols to avoid multiple enumeration
996  var symbolsArray = symbols.ToArray();
997  return CreateBarCountHistoryRequests(
998  symbolsArray,
999  Extensions.GetCustomDataTypeFromSymbols(symbolsArray),
1000  periods,
1001  resolution,
1002  fillForward,
1003  extendedMarketHours,
1004  dataMappingMode,
1005  dataNormalizationMode,
1006  contractDepthOffset);
1007  }
1008 
1009  /// <summary>
1010  /// Helper methods to create a history request for the specified symbols and bar count with custom data type
1011  /// </summary>
1012  private IEnumerable<HistoryRequest> CreateBarCountHistoryRequests(IEnumerable<Symbol> symbols, Type requestedType, int periods,
1013  Resolution? resolution = null, bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
1014  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
1015  {
1016  return symbols.Where(HistoryRequestValid).SelectMany(symbol =>
1017  {
1018  // Match or create configs for the symbol
1019  var configs = GetMatchingSubscriptions(symbol, requestedType, resolution).ToList();
1020  if (configs.Count == 0)
1021  {
1022  return Enumerable.Empty<HistoryRequest>();
1023  }
1024 
1025  return configs.Select(config =>
1026  {
1027  // If no requested type was passed, use the config type to get the resolution (if not provided) and the exchange hours
1028  var type = requestedType ?? config.Type;
1029  var res = GetResolution(symbol, resolution, type);
1030  var exchange = GetExchangeHours(symbol, type);
1031  var start = _historyRequestFactory.GetStartTimeAlgoTz(symbol, periods, res, exchange, config.DataTimeZone,
1032  config.Type, extendedMarketHours);
1033  var end = Time;
1034 
1035  return _historyRequestFactory.CreateHistoryRequest(config, start, end, exchange, res, fillForward,
1036  extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset);
1037  });
1038  });
1039  }
1040 
1041  private int GetTickTypeOrder(SecurityType securityType, TickType tickType)
1042  {
1043  return SubscriptionManager.AvailableDataTypes[securityType].IndexOf(tickType);
1044  }
1045 
1046  private IEnumerable<SubscriptionDataConfig> GetMatchingSubscriptions(Symbol symbol, Type type, Resolution? resolution = null)
1047  {
1049  // we add internal subscription so that history requests are covered, this allows us to warm them up too
1050  .GetSubscriptionDataConfigs(symbol, includeInternalConfigs: true)
1051  // find all subscriptions matching the requested type with a higher resolution than requested
1052  .OrderByDescending(s => s.Resolution)
1053  // lets make sure to respect the order of the data types
1054  .ThenByDescending(config => GetTickTypeOrder(config.SecurityType, config.TickType));
1055 
1056  var matchingSubscriptions = subscriptions.Where(s => SubscriptionDataConfigTypeFilter(type, s.Type));
1057 
1058  var internalConfig = new List<SubscriptionDataConfig>();
1059  var userConfig = new List<SubscriptionDataConfig>();
1060  foreach (var config in matchingSubscriptions)
1061  {
1062  if (config.IsInternalFeed)
1063  {
1064  internalConfig.Add(config);
1065  }
1066  else
1067  {
1068  userConfig.Add(config);
1069  }
1070  }
1071 
1072  // if we have any user defined subscription configuration we use it, else we use internal ones if any
1073  List<SubscriptionDataConfig> configs = null;
1074  if (userConfig.Count != 0)
1075  {
1076  configs = userConfig;
1077  }
1078  else if (internalConfig.Count != 0)
1079  {
1080  configs = internalConfig;
1081  }
1082 
1083  // we use the subscription manager registered configurations here, we can not rely on the Securities collection
1084  // since this might be called when creating a security and warming it up
1085  if (configs != null && configs.Count != 0)
1086  {
1087  if (resolution.HasValue
1088  && (resolution == Resolution.Daily || resolution == Resolution.Hour)
1089  && symbol.SecurityType == SecurityType.Equity)
1090  {
1091  // for Daily and Hour resolution, for equities, we have to
1092  // filter out any existing subscriptions that could be of Quote type
1093  // This could happen if they were Resolution.Minute/Second/Tick
1094  return configs.Where(s => s.TickType != TickType.Quote);
1095  }
1096 
1097  if (symbol.IsCanonical() && configs.Count > 1)
1098  {
1099  // option/future (canonicals) might add in a ZipEntryName auxiliary data type used for selection, we filter it out from history requests by default
1100  return configs.Where(s => s.Type != typeof(ZipEntryName));
1101  }
1102 
1103  return configs;
1104  }
1105  else
1106  {
1107  resolution = GetResolution(symbol, resolution, type);
1108 
1109  // If type was specified and not a lean data type and also not abstract, we create a new subscription
1110  if (type != null && !LeanData.IsCommonLeanDataType(type) && !type.IsAbstract)
1111  {
1112  // we already know it's not a common lean data type
1113  var isCustom = Extensions.IsCustomDataType(symbol, type);
1114  var entry = MarketHoursDatabase.GetEntry(symbol, new[] { type });
1115 
1116  // we were giving a specific type let's fetch it
1117  return new[] { new SubscriptionDataConfig(
1118  type,
1119  symbol,
1120  resolution.Value,
1121  entry.DataTimeZone,
1122  entry.ExchangeHours.TimeZone,
1125  true,
1126  isCustom,
1127  LeanData.GetCommonTickTypeForCommonDataTypes(type, symbol.SecurityType),
1128  true,
1129  UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType))};
1130  }
1131 
1132  return SubscriptionManager
1133  .LookupSubscriptionConfigDataTypes(symbol.SecurityType, resolution.Value, symbol.IsCanonical())
1134  .Where(tuple => SubscriptionDataConfigTypeFilter(type, tuple.Item1))
1135  .Select(x =>
1136  {
1137  var configType = x.Item1;
1138  // Use the config type to get an accurate mhdb entry
1139  var entry = MarketHoursDatabase.GetEntry(symbol, new[] { configType });
1140 
1141  return new SubscriptionDataConfig(
1142  configType,
1143  symbol,
1144  resolution.Value,
1145  entry.DataTimeZone,
1146  entry.ExchangeHours.TimeZone,
1149  true,
1150  false,
1151  x.Item2,
1152  true,
1153  UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType));
1154  })
1155  // lets make sure to respect the order of the data types, if used on a history request will affect outcome when using pushthrough for example
1156  .OrderByDescending(config => GetTickTypeOrder(config.SecurityType, config.TickType));
1157  }
1158  }
1159 
1160  /// <summary>
1161  /// Helper method to determine if the provided config type passes the filter of the target type
1162  /// </summary>
1163  /// <remarks>If the target type is <see cref="BaseData"/>, <see cref="OpenInterest"/> config types will return false.
1164  /// This is useful to filter OpenInterest by default from history requests unless it's explicitly requested</remarks>
1165  private bool SubscriptionDataConfigTypeFilter(Type targetType, Type configType)
1166  {
1167  if (targetType == null)
1168  {
1169  return configType != typeof(OpenInterest);
1170  }
1171 
1172  var targetIsGenericType = targetType == typeof(BaseData);
1173 
1174  return targetType.IsAssignableFrom(configType) && (!targetIsGenericType || configType != typeof(OpenInterest));
1175  }
1176 
1177  private SecurityExchangeHours GetExchangeHours(Symbol symbol, Type type = null)
1178  {
1179  return GetMarketHours(symbol, type).ExchangeHours;
1180  }
1181 
1182  private MarketHoursDatabase.Entry GetMarketHours(Symbol symbol, Type type = null)
1183  {
1184  var hoursEntry = type != null
1185  ? MarketHoursDatabase.GetEntry(symbol, new[] { type })
1186  : MarketHoursDatabase.GetEntry(symbol.ID.Market, symbol, symbol.ID.SecurityType);
1187 
1188 
1189  // user can override the exchange hours in algorithm, i.e. HistoryAlgorithm
1190  Security security;
1191  if (Securities.TryGetValue(symbol, out security))
1192  {
1193  return new MarketHoursDatabase.Entry(hoursEntry.DataTimeZone, security.Exchange.Hours);
1194  }
1195 
1196  return hoursEntry;
1197  }
1198 
1199  private Resolution GetResolution(Symbol symbol, Resolution? resolution, Type type)
1200  {
1201  if (resolution != null)
1202  {
1203  return resolution.Value;
1204  }
1205 
1206  Resolution? result = null;
1207  var hasNonInternal = false;
1208  foreach (var config in SubscriptionManager.SubscriptionDataConfigService
1209  .GetSubscriptionDataConfigs(symbol, includeInternalConfigs: true)
1210  // we process non internal configs first
1211  .OrderBy(config => config.IsInternalFeed ? 1 : 0))
1212  {
1213  if (!config.IsInternalFeed || !hasNonInternal)
1214  {
1215  // once we find a non internal config we ignore internals
1216  hasNonInternal |= !config.IsInternalFeed;
1217  if (!result.HasValue || config.Resolution < result)
1218  {
1219  result = config.Resolution;
1220  }
1221  }
1222  }
1223 
1224  if (result != null)
1225  {
1226  return (Resolution)result;
1227  }
1228  else
1229  {
1230  if (resolution != null)
1231  {
1232  return resolution.Value;
1233  }
1234 
1235  if (type == null || LeanData.IsCommonLeanDataType(type) || type.IsAbstract)
1236  {
1238  }
1239 
1240  try
1241  {
1242  // for custom data types let's try to fetch the default resolution from the type definition
1243  var instance = type.GetBaseDataInstance();
1244  return instance.DefaultResolution();
1245  }
1246  catch
1247  {
1248  // just in case
1250  }
1251  }
1252  }
1253 
1254  /// <summary>
1255  /// Validate a symbol for a history request.
1256  /// Universe and canonical symbols are only valid for future security types
1257  /// </summary>
1258  private bool HistoryRequestValid(Symbol symbol)
1259  {
1260  return symbol.SecurityType == SecurityType.Future ||
1261  symbol.SecurityType == SecurityType.Option ||
1262  symbol.SecurityType == SecurityType.IndexOption ||
1263  !symbol.IsCanonical();
1264  }
1265 
1266  /// <summary>
1267  /// Will set warmup settings validating the algorithm has not finished initialization yet
1268  /// </summary>
1269  private void SetWarmup(int? barCount, TimeSpan? timeSpan, Resolution? resolution)
1270  {
1271  if (_locked)
1272  {
1273  throw new InvalidOperationException("QCAlgorithm.SetWarmup(): This method cannot be used after algorithm initialized");
1274  }
1275 
1276  _warmupTimeSpan = timeSpan;
1277  _warmupBarCount = barCount;
1278  Settings.WarmupResolution = resolution;
1279  }
1280 
1281  /// <summary>
1282  /// Throws if a period bases history request is made for tick resolution, which is not allowed.
1283  /// </summary>
1284  private void CheckPeriodBasedHistoryRequestResolution(IEnumerable<Symbol> symbols, Resolution? resolution, Type requestedType)
1285  {
1286  if (symbols.Any(symbol => GetResolution(symbol, resolution, requestedType) == Resolution.Tick))
1287  {
1288  throw new InvalidOperationException("History functions that accept a 'periods' parameter can not be used with Resolution.Tick");
1289  }
1290  }
1291 
1292  /// <summary>
1293  /// Centralized logic to get data typed history given a list of requests for the specified symbol.
1294  /// This method is used to keep backwards compatibility for those History methods that expect an ArgumentException to be thrown
1295  /// when the security and the requested data type do not match
1296  /// </summary>
1297  /// <remarks>
1298  /// This method is only used for Python algorithms, specially for those requesting custom data type history.
1299  /// The reason for using this method is that custom data type Python history calls to
1300  /// <see cref="History{T}(QuantConnect.Symbol, int, Resolution?, bool?, bool?, DataMappingMode?, DataNormalizationMode?, int?)"/> will always use <see cref="PythonData"/> (the custom data base class)
1301  /// as the T argument, because the custom data class is a Python type, which will cause the history data in the slices to not be matched
1302  /// to the actual requested type, resulting in an empty list of slices.
1303  /// </remarks>
1304  private static IEnumerable<dynamic> GetPythonCustomDataTypeHistory(IEnumerable<Slice> slices, List<HistoryRequest> requests,
1305  Symbol symbol = null)
1306  {
1307  if (requests.Count == 0 || requests.Any(x => x.DataType != requests[0].DataType))
1308  {
1309  throw new ArgumentException("QCAlgorithm.GetPythonCustomDataTypeHistory(): All history requests must be for the same data type");
1310  }
1311 
1312  var pythonType = requests[0].DataType;
1313 
1314  if (symbol == null)
1315  {
1316  return slices.Get(pythonType);
1317  }
1318 
1319  return slices.Get(pythonType, symbol);
1320  }
1321 
1322  /// <summary>
1323  /// Wraps the resulting history enumerable in case of a Python custom data history request.
1324  /// We need to get and release the Python GIL when parallel history requests are enabled to avoid deadlocks
1325  /// in the custom data readers.
1326  /// </summary>
1327  private static IEnumerable<Slice> WrapPythonDataHistory(IEnumerable<Slice> history)
1328  {
1329  using var enumerator = history.GetEnumerator();
1330 
1331  var hasData = true;
1332  while (hasData)
1333  {
1334  // When yielding in tasks there's no guarantee it will continue in the same thread, but we need that guarantee
1335  using (Py.GIL())
1336  {
1337  var state = PythonEngine.BeginAllowThreads();
1338  try
1339  {
1340  hasData = enumerator.MoveNext();
1341  }
1342  finally
1343  {
1344  // we always need to reset the state so that we can dispose of the GIL
1345  PythonEngine.EndAllowThreads(state);
1346  }
1347  }
1348  if (hasData)
1349  {
1350  yield return enumerator.Current;
1351  }
1352  }
1353  }
1354  }
1355 }