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);
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, 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  return CreateDateRangeHistoryRequests(symbols, typeof(BaseData), startAlgoTz, endAlgoTz, resolution, fillForward, extendedMarketHours,
952  dataMappingMode, dataNormalizationMode, contractDepthOffset);
953  }
954 
955  /// <summary>
956  /// Helper method to create history requests from a date range with custom data type
957  /// </summary>
958  protected IEnumerable<HistoryRequest> CreateDateRangeHistoryRequests(IEnumerable<Symbol> symbols, Type requestedType, DateTime startAlgoTz, DateTime endAlgoTz,
959  Resolution? resolution = null, bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
960  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
961  {
962  return symbols.Where(HistoryRequestValid).SelectMany(x =>
963  {
964  var requests = new List<HistoryRequest>();
965 
966  foreach (var config in GetMatchingSubscriptions(x, requestedType, resolution))
967  {
968  var request = _historyRequestFactory.CreateHistoryRequest(config, startAlgoTz, endAlgoTz, GetExchangeHours(x, requestedType), resolution,
969  fillForward, extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset);
970  requests.Add(request);
971  }
972 
973  return requests;
974  });
975  }
976 
977  /// <summary>
978  /// Helper methods to create a history request for the specified symbols and bar count
979  /// </summary>
980  private IEnumerable<HistoryRequest> CreateBarCountHistoryRequests(IEnumerable<Symbol> symbols, int periods, Resolution? resolution = null,
981  bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
982  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
983  {
984  return CreateBarCountHistoryRequests(symbols, typeof(BaseData), periods, resolution, fillForward, extendedMarketHours, dataMappingMode,
985  dataNormalizationMode, contractDepthOffset);
986  }
987 
988  /// <summary>
989  /// Helper methods to create a history request for the specified symbols and bar count with custom data type
990  /// </summary>
991  private IEnumerable<HistoryRequest> CreateBarCountHistoryRequests(IEnumerable<Symbol> symbols, Type requestedType, int periods,
992  Resolution? resolution = null, bool? fillForward = null, bool? extendedMarketHours = null, DataMappingMode? dataMappingMode = null,
993  DataNormalizationMode? dataNormalizationMode = null, int? contractDepthOffset = null)
994  {
995  return symbols.Where(HistoryRequestValid).SelectMany(symbol =>
996  {
997  var res = GetResolution(symbol, resolution, requestedType);
998  var exchange = GetExchangeHours(symbol, requestedType);
999  var configs = GetMatchingSubscriptions(symbol, requestedType, resolution).ToList();
1000  if (configs.Count == 0)
1001  {
1002  return Enumerable.Empty<HistoryRequest>();
1003  }
1004 
1005  var start = _historyRequestFactory.GetStartTimeAlgoTz(symbol, periods, res, exchange, configs.First().DataTimeZone, extendedMarketHours);
1006  var end = Time;
1007 
1008  return configs.Select(config => _historyRequestFactory.CreateHistoryRequest(config, start, end, exchange, res, fillForward,
1009  extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset));
1010  });
1011  }
1012 
1013  private int GetTickTypeOrder(SecurityType securityType, TickType tickType)
1014  {
1015  return SubscriptionManager.AvailableDataTypes[securityType].IndexOf(tickType);
1016  }
1017 
1018  private IEnumerable<SubscriptionDataConfig> GetMatchingSubscriptions(Symbol symbol, Type type, Resolution? resolution = null)
1019  {
1021  // we add internal subscription so that history requests are covered, this allows us to warm them up too
1022  .GetSubscriptionDataConfigs(symbol, includeInternalConfigs: true)
1023  // find all subscriptions matching the requested type with a higher resolution than requested
1024  .OrderByDescending(s => s.Resolution)
1025  // lets make sure to respect the order of the data types
1026  .ThenByDescending(config => GetTickTypeOrder(config.SecurityType, config.TickType));
1027 
1028  var matchingSubscriptions = subscriptions.Where(s => SubscriptionDataConfigTypeFilter(type, s.Type));
1029 
1030  var internalConfig = new List<SubscriptionDataConfig>();
1031  var userConfig = new List<SubscriptionDataConfig>();
1032  foreach (var config in matchingSubscriptions)
1033  {
1034  if (config.IsInternalFeed)
1035  {
1036  internalConfig.Add(config);
1037  }
1038  else
1039  {
1040  userConfig.Add(config);
1041  }
1042  }
1043 
1044  // if we have any user defined subscription configuration we use it, else we use internal ones if any
1045  List<SubscriptionDataConfig> configs = null;
1046  if(userConfig.Count != 0)
1047  {
1048  configs = userConfig;
1049  }
1050  else if (internalConfig.Count != 0)
1051  {
1052  configs = internalConfig;
1053  }
1054 
1055  // we use the subscription manager registered configurations here, we can not rely on the Securities collection
1056  // since this might be called when creating a security and warming it up
1057  if (configs != null && configs.Count != 0)
1058  {
1059  if (resolution.HasValue
1060  && (resolution == Resolution.Daily || resolution == Resolution.Hour)
1061  && symbol.SecurityType == SecurityType.Equity)
1062  {
1063  // for Daily and Hour resolution, for equities, we have to
1064  // filter out any existing subscriptions that could be of Quote type
1065  // This could happen if they were Resolution.Minute/Second/Tick
1066  return configs.Where(s => s.TickType != TickType.Quote);
1067  }
1068 
1069  if (symbol.IsCanonical() && configs.Count > 1)
1070  {
1071  // option/future (canonicals) might add in a ZipEntryName auxiliary data type used for selection, we filter it out from history requests by default
1072  return configs.Where(s => s.Type != typeof(ZipEntryName));
1073  }
1074 
1075  return configs;
1076  }
1077  else
1078  {
1079  var entry = MarketHoursDatabase.GetEntry(symbol, new []{ type });
1080  resolution = GetResolution(symbol, resolution, type);
1081 
1082  if (!LeanData.IsCommonLeanDataType(type) && !type.IsAbstract)
1083  {
1084  // we were giving a specific type let's fetch it
1085  return new[] { new SubscriptionDataConfig(
1086  type,
1087  symbol,
1088  resolution.Value,
1089  entry.DataTimeZone,
1090  entry.ExchangeHours.TimeZone,
1093  true,
1094  false,
1095  LeanData.GetCommonTickTypeForCommonDataTypes(type, symbol.SecurityType),
1096  true,
1097  UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType))};
1098  }
1099 
1100  return SubscriptionManager
1101  .LookupSubscriptionConfigDataTypes(symbol.SecurityType, resolution.Value, symbol.IsCanonical())
1102  .Where(tuple => SubscriptionDataConfigTypeFilter(type, tuple.Item1))
1103  .Select(x => new SubscriptionDataConfig(
1104  x.Item1,
1105  symbol,
1106  resolution.Value,
1107  entry.DataTimeZone,
1108  entry.ExchangeHours.TimeZone,
1111  true,
1112  false,
1113  x.Item2,
1114  true,
1115  UniverseSettings.GetUniverseNormalizationModeOrDefault(symbol.SecurityType)));
1116  }
1117  }
1118 
1119  /// <summary>
1120  /// Helper method to determine if the provided config type passes the filter of the target type
1121  /// </summary>
1122  /// <remarks>If the target type is <see cref="BaseData"/>, <see cref="OpenInterest"/> config types will return false.
1123  /// This is useful to filter OpenInterest by default from history requests unless it's explicitly requested</remarks>
1124  private bool SubscriptionDataConfigTypeFilter(Type targetType, Type configType)
1125  {
1126  var targetIsGenericType = targetType == typeof(BaseData);
1127 
1128  return targetType.IsAssignableFrom(configType) && (!targetIsGenericType || configType != typeof(OpenInterest));
1129  }
1130 
1131  private SecurityExchangeHours GetExchangeHours(Symbol symbol, Type type = null)
1132  {
1133  return GetMarketHours(symbol, type).ExchangeHours;
1134  }
1135 
1136  private MarketHoursDatabase.Entry GetMarketHours(Symbol symbol, Type type = null)
1137  {
1138  var hoursEntry = type != null
1139  ? MarketHoursDatabase.GetEntry(symbol, new[] { type })
1140  : MarketHoursDatabase.GetEntry(symbol.ID.Market, symbol, symbol.ID.SecurityType);
1141 
1142 
1143  // user can override the exchange hours in algorithm, i.e. HistoryAlgorithm
1144  Security security;
1145  if (Securities.TryGetValue(symbol, out security))
1146  {
1147  return new MarketHoursDatabase.Entry(hoursEntry.DataTimeZone, security.Exchange.Hours);
1148  }
1149 
1150  return hoursEntry;
1151  }
1152 
1153  private Resolution GetResolution(Symbol symbol, Resolution? resolution, Type type)
1154  {
1155  if (resolution != null)
1156  {
1157  return resolution.Value;
1158  }
1159 
1160  Resolution? result = null;
1161  var hasNonInternal = false;
1162  foreach (var config in SubscriptionManager.SubscriptionDataConfigService
1163  .GetSubscriptionDataConfigs(symbol, includeInternalConfigs: true)
1164  // we process non internal configs first
1165  .OrderBy(config => config.IsInternalFeed ? 1 : 0))
1166  {
1167  if (!config.IsInternalFeed || !hasNonInternal)
1168  {
1169  // once we find a non internal config we ignore internals
1170  hasNonInternal |= !config.IsInternalFeed;
1171  if (!result.HasValue || config.Resolution < result)
1172  {
1173  result = config.Resolution;
1174  }
1175  }
1176  }
1177 
1178  if (result != null)
1179  {
1180  return (Resolution)result;
1181  }
1182  else
1183  {
1184  if(resolution != null)
1185  {
1186  return resolution.Value;
1187  }
1188 
1189  if (type == null || LeanData.IsCommonLeanDataType(type) || type.IsAbstract)
1190  {
1192  }
1193 
1194  try
1195  {
1196  // for custom data types let's try to fetch the default resolution from the type definition
1197  var instance = type.GetBaseDataInstance();
1198  return instance.DefaultResolution();
1199  }
1200  catch
1201  {
1202  // just in case
1204  }
1205  }
1206  }
1207 
1208  /// <summary>
1209  /// Validate a symbol for a history request.
1210  /// Universe and canonical symbols are only valid for future security types
1211  /// </summary>
1212  private bool HistoryRequestValid(Symbol symbol)
1213  {
1214  return symbol.SecurityType == SecurityType.Future || !symbol.IsCanonical();
1215  }
1216 
1217  /// <summary>
1218  /// Will set warmup settings validating the algorithm has not finished initialization yet
1219  /// </summary>
1220  private void SetWarmup(int? barCount, TimeSpan? timeSpan, Resolution? resolution)
1221  {
1222  if (_locked)
1223  {
1224  throw new InvalidOperationException("QCAlgorithm.SetWarmup(): This method cannot be used after algorithm initialized");
1225  }
1226 
1227  _warmupTimeSpan = timeSpan;
1228  _warmupBarCount = barCount;
1229  Settings.WarmupResolution = resolution;
1230  }
1231 
1232  /// <summary>
1233  /// Throws if a period bases history request is made for tick resolution, which is not allowed.
1234  /// </summary>
1235  private void CheckPeriodBasedHistoryRequestResolution(IEnumerable<Symbol> symbols, Resolution? resolution, Type requestedType)
1236  {
1237  if (symbols.Any(symbol => GetResolution(symbol, resolution, requestedType) == Resolution.Tick))
1238  {
1239  throw new InvalidOperationException("History functions that accept a 'periods' parameter can not be used with Resolution.Tick");
1240  }
1241  }
1242 
1243  /// <summary>
1244  /// Centralized logic to get data typed history given a list of requests for the specified symbol.
1245  /// This method is used to keep backwards compatibility for those History methods that expect an ArgumentException to be thrown
1246  /// when the security and the requested data type do not match
1247  /// </summary>
1248  /// <remarks>
1249  /// This method is only used for Python algorithms, specially for those requesting custom data type history.
1250  /// The reason for using this method is that custom data type Python history calls to
1251  /// <see cref="History{T}(QuantConnect.Symbol, int, Resolution?)"/> will always use <see cref="PythonData"/> (the custom data base class)
1252  /// 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
1253  /// to the actual requested type, resulting in an empty list of slices.
1254  /// </remarks>
1255  private static IEnumerable<dynamic> GetPythonCustomDataTypeHistory(IEnumerable<Slice> slices, List<HistoryRequest> requests,
1256  Symbol symbol = null)
1257  {
1258  if (requests.Count == 0 || requests.Any(x => x.DataType != requests[0].DataType))
1259  {
1260  throw new ArgumentException("QCAlgorithm.GetPythonCustomDataTypeHistory(): All history requests must be for the same data type");
1261  }
1262 
1263  var pythonType = requests[0].DataType;
1264 
1265  if (symbol == null)
1266  {
1267  return slices.Get(pythonType);
1268  }
1269 
1270  return slices.Get(pythonType, symbol);
1271  }
1272 
1273  /// <summary>
1274  /// Wraps the resulting history enumerable in case of a Python custom data history request.
1275  /// We need to get and release the Python GIL when parallel history requests are enabled to avoid deadlocks
1276  /// in the custom data readers.
1277  /// </summary>
1278  private static IEnumerable<Slice> WrapPythonDataHistory(IEnumerable<Slice> history)
1279  {
1280  using var enumerator = history.GetEnumerator();
1281 
1282  var hasData = true;
1283  while (hasData)
1284  {
1285  // When yielding in tasks there's no guarantee it will continue in the same thread, but we need that guarantee
1286  using (Py.GIL())
1287  {
1288  var state = PythonEngine.BeginAllowThreads();
1289  try
1290  {
1291  hasData = enumerator.MoveNext();
1292  }
1293  finally
1294  {
1295  // we always need to reset the state so that we can dispose of the GIL
1296  PythonEngine.EndAllowThreads(state);
1297  }
1298  }
1299  if (hasData)
1300  {
1301  yield return enumerator.Current;
1302  }
1303  }
1304  }
1305  }
1306 }