Lean  $LEAN_TAG$
HistoryRequestFactory.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;
21 using QuantConnect.Util;
22 
23 namespace QuantConnect.Data
24 {
25  /// <summary>
26  /// Helper class used to create new <see cref="HistoryRequest"/>
27  /// </summary>
28  public class HistoryRequestFactory
29  {
30  private readonly IAlgorithm _algorithm;
31 
32  /// <summary>
33  /// Creates a new instance
34  /// </summary>
35  /// <param name="algorithm">The algorithm instance to use</param>
37  {
38  _algorithm = algorithm;
39  }
40 
41  /// <summary>
42  /// Creates a new history request
43  /// </summary>
44  /// <param name="subscription">The config </param>
45  /// <param name="startAlgoTz">History request start time in algorithm time zone</param>
46  /// <param name="endAlgoTz">History request end time in algorithm time zone</param>
47  /// <param name="exchangeHours">Security exchange hours</param>
48  /// <param name="resolution">The resolution to use. If null will use <see cref="SubscriptionDataConfig.Resolution"/></param>
49  /// <param name="fillForward">True to fill forward missing data, false otherwise</param>
50  /// <param name="extendedMarketHours">True to include extended market hours data, false otherwise</param>
51  /// <param name="dataMappingMode">The contract mapping mode to use for the security history request</param>
52  /// <param name="dataNormalizationMode">The price scaling mode to use for the securities history</param>
53  /// <param name="contractDepthOffset">The continuous contract desired offset from the current front month.
54  /// For example, 0 will use the front month, 1 will use the back month contract</param>
55  /// <returns>The new <see cref="HistoryRequest"/></returns>
57  DateTime startAlgoTz,
58  DateTime endAlgoTz,
59  SecurityExchangeHours exchangeHours,
60  Resolution? resolution,
61  bool? fillForward = null,
62  bool? extendedMarketHours = null,
63  DataMappingMode? dataMappingMode = null,
64  DataNormalizationMode? dataNormalizationMode = null,
65  int? contractDepthOffset = null)
66  {
67  resolution ??= subscription.Resolution;
68 
69  var dataType = subscription.Type;
70 
71  // if we change resolution the data type can change, for example subscription being Tick type and resolution daily
72  // data type here won't be Tick anymore, but TradeBar/QuoteBar
73  if (resolution.Value != subscription.Resolution && LeanData.IsCommonLeanDataType(dataType))
74  {
75  dataType = LeanData.GetDataType(resolution.Value, subscription.TickType);
76  }
77 
78  var fillForwardResolution = subscription.FillDataForward ? resolution : null;
79  if (fillForward != null)
80  {
81  fillForwardResolution = fillForward.Value ? resolution : null;
82  }
83 
84  var request = new HistoryRequest(subscription,
85  exchangeHours,
86  startAlgoTz.ConvertToUtc(_algorithm.TimeZone),
87  endAlgoTz.ConvertToUtc(_algorithm.TimeZone))
88  {
89  DataType = dataType,
90  Resolution = resolution.Value,
91  FillForwardResolution = fillForwardResolution,
92  TickType = subscription.TickType
93  };
94 
95  if (extendedMarketHours != null)
96  {
97  request.IncludeExtendedMarketHours = extendedMarketHours.Value;
98  }
99 
100  if (dataMappingMode != null)
101  {
102  request.DataMappingMode = dataMappingMode.Value;
103  }
104 
105  if (dataNormalizationMode != null)
106  {
107  request.DataNormalizationMode = dataNormalizationMode.Value;
108  }
109 
110  if (contractDepthOffset != null)
111  {
112  request.ContractDepthOffset = (uint)Math.Abs(contractDepthOffset.Value);
113  }
114 
115  return request;
116  }
117 
118  /// <summary>
119  /// Gets the start time required for the specified bar count in terms of the algorithm's time zone
120  /// </summary>
121  /// <param name="symbol">The symbol to select proper <see cref="SubscriptionDataConfig"/> config</param>
122  /// <param name="periods">The number of bars requested</param>
123  /// <param name="resolution">The length of each bar</param>
124  /// <param name="exchange">The exchange hours used for market open hours</param>
125  /// <param name="dataTimeZone">The time zone in which data are stored</param>
126  /// <param name="dataType">The data type to request</param>
127  /// <param name="extendedMarketHours">
128  /// True to include extended market hours data, false otherwise.
129  /// If not passed, the config will be used to determined whether to include extended market hours.
130  /// </param>
131  /// <returns>The start time that would provide the specified number of bars ending at the algorithm's current time</returns>
132  public DateTime GetStartTimeAlgoTz(
133  Symbol symbol,
134  int periods,
135  Resolution resolution,
136  SecurityExchangeHours exchange,
137  DateTimeZone dataTimeZone,
138  Type dataType,
139  bool? extendedMarketHours = null)
140  {
141  return GetStartTimeAlgoTz(_algorithm.UtcTime, symbol, periods, resolution, exchange, dataTimeZone, dataType, extendedMarketHours);
142  }
143 
144  /// <summary>
145  /// Gets the start time required for the specified bar count in terms of the algorithm's time zone
146  /// </summary>
147  /// <param name="referenceUtcTime">The end time in utc</param>
148  /// <param name="symbol">The symbol to select proper <see cref="SubscriptionDataConfig"/> config</param>
149  /// <param name="periods">The number of bars requested</param>
150  /// <param name="resolution">The length of each bar</param>
151  /// <param name="exchange">The exchange hours used for market open hours</param>
152  /// <param name="dataTimeZone">The time zone in which data are stored</param>
153  /// <param name="dataType">The data type to request</param>
154  /// <param name="extendedMarketHours">
155  /// True to include extended market hours data, false otherwise.
156  /// If not passed, the config will be used to determined whether to include extended market hours.
157  /// </param>
158  /// <returns>The start time that would provide the specified number of bars ending at the algorithm's current time</returns>
159  public DateTime GetStartTimeAlgoTz(
160  DateTime referenceUtcTime,
161  Symbol symbol,
162  int periods,
163  Resolution resolution,
164  SecurityExchangeHours exchange,
165  DateTimeZone dataTimeZone,
166  Type dataType,
167  bool? extendedMarketHours = null)
168  {
169  var isExtendedMarketHours = false;
170  // hour resolution does no have extended market hours data. Same for chain universes
171  if (resolution != Resolution.Hour && LeanData.SupportsExtendedMarketHours(dataType))
172  {
173  if (extendedMarketHours.HasValue)
174  {
175  isExtendedMarketHours = extendedMarketHours.Value;
176  }
177  else
178  {
179  var configs = _algorithm.SubscriptionManager
180  .SubscriptionDataConfigService
181  .GetSubscriptionDataConfigs(symbol);
182  isExtendedMarketHours = configs.IsExtendedMarketHours();
183  }
184  }
185 
186  var timeSpan = resolution.ToTimeSpan();
187  // make this a minimum of one second
188  timeSpan = timeSpan < Time.OneSecond ? Time.OneSecond : timeSpan;
189 
190  var localStartTime = Time.GetStartTimeForTradeBars(
191  exchange,
192  referenceUtcTime.ConvertFromUtc(exchange.TimeZone),
193  timeSpan,
194  periods,
195  isExtendedMarketHours,
196  dataTimeZone,
197  LeanData.UseDailyStrictEndTimes(_algorithm.Settings, dataType, symbol, timeSpan, exchange));
198  return localStartTime.ConvertTo(exchange.TimeZone, _algorithm.TimeZone);
199  }
200  }
201 }