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