Lean  $LEAN_TAG$
BacktestingChainProvider.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 QuantConnect.Util;
20 using System.Collections.Generic;
21 using System.Linq;
23 using QuantConnect.Data;
24 
26 {
27  /// <summary>
28  /// Base backtesting cache provider which will source symbols from local zip files
29  /// </summary>
30  public abstract class BacktestingChainProvider
31  {
32  /// <summary>
33  /// The map file provider instance to use
34  /// </summary>
35  protected IMapFileProvider MapFileProvider { get; private set; }
36 
37  /// <summary>
38  /// The history provider instance to use
39  /// </summary>
40  protected IHistoryProvider HistoryProvider { get; private set; }
41 
42  /// <summary>
43  /// Initializes a new instance of the <see cref="BacktestingChainProvider"/> class
44  /// </summary>
46  {
47  }
48 
49  /// <summary>
50  /// Initializes a new instance of the <see cref="BacktestingChainProvider"/> class
51  /// </summary>
52  /// <param name="parameters">The initialization parameters</param>
53  // TODO: This should be in the chain provider interfaces.
54  // They might be even be unified in a single interface (futures and options chains providers)
56  {
57  HistoryProvider = parameters.HistoryProvider;
58  MapFileProvider = parameters.MapFileProvider;
59  }
60 
61  /// <summary>
62  /// Get the contract symbols associated with the given canonical symbol and date
63  /// </summary>
64  /// <param name="canonicalSymbol">The canonical symbol</param>
65  /// <param name="date">The date to search for</param>
66  protected IEnumerable<Symbol> GetSymbols(Symbol canonicalSymbol, DateTime date)
67  {
68  var marketHoursDataBase = MarketHoursDatabase.FromDataFolder();
69  var universeType = canonicalSymbol.SecurityType.IsOption() ? typeof(OptionUniverse) : typeof(FutureUniverse);
70  // Use this GetEntry extension method since it's data type dependent, so we get the correct entry for the option universe
71  var marketHoursEntry = marketHoursDataBase.GetEntry(canonicalSymbol, new[] { universeType });
72 
73  // We will add a safety measure in case the universe file for the current time is not available:
74  // we will use the latest available universe file within the last 3 trading dates.
75  // This is useful in cases like live trading when the algorithm is deployed at a time of day when
76  // the universe file is not available yet.
77  var history = (List<Slice>)null;
78  var periods = 1;
79  while ((history == null || history.Count == 0) && periods <= 3)
80  {
81  var startDate = Time.GetStartTimeForTradeBars(marketHoursEntry.ExchangeHours, date, Time.OneDay, periods++,
82  extendedMarketHours: false, marketHoursEntry.DataTimeZone);
83  var request = new HistoryRequest(
84  startDate.ConvertToUtc(marketHoursEntry.ExchangeHours.TimeZone),
85  date.ConvertToUtc(marketHoursEntry.ExchangeHours.TimeZone),
86  universeType,
87  canonicalSymbol,
88  Resolution.Daily,
89  marketHoursEntry.ExchangeHours,
90  marketHoursEntry.DataTimeZone,
91  null,
92  false,
93  false,
95  TickType.Quote);
96  history = HistoryProvider.GetHistory([request], marketHoursEntry.DataTimeZone)?.ToList();
97  }
98 
99  var symbols = history == null || history.Count == 0
100  ? Enumerable.Empty<Symbol>()
101  : history.Take(1).GetUniverseData().SelectMany(x => x.Values.Single()).Select(x => x.Symbol);
102 
103  if (canonicalSymbol.SecurityType.IsOption())
104  {
105  symbols = symbols.Where(symbol => symbol.SecurityType.IsOption());
106  }
107 
108  return symbols.Where(symbol => symbol.ID.Date >= date.Date);
109  }
110 
111  /// <summary>
112  /// Helper method to determine if a contract is expired for the requested date
113  /// </summary>
114  protected static bool IsContractExpired(Symbol symbol, DateTime date)
115  {
116  return symbol.ID.Date.Date < date.Date;
117  }
118  }
119 }