Lean  $LEAN_TAG$
OptionChainUniverseSubscriptionEnumeratorFactory.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 
17 using System;
18 using System.Collections.Generic;
19 using System.Linq;
20 using QuantConnect.Data;
24 
26 {
27  /// <summary>
28  /// Provides an implementation of <see cref="ISubscriptionEnumeratorFactory"/> for the <see cref="OptionChainUniverse"/>
29  /// </summary>
31  {
32  private readonly Func<SubscriptionRequest, IEnumerator<BaseData>> _enumeratorConfigurator;
33  private readonly bool _isLiveMode;
34 
35  private readonly IDataQueueUniverseProvider _symbolUniverse;
36  private readonly ITimeProvider _timeProvider;
37 
38  /// <summary>
39  /// Initializes a new instance of the <see cref="OptionChainUniverseSubscriptionEnumeratorFactory"/> class
40  /// </summary>
41  /// <param name="enumeratorConfigurator">Function used to configure the sub-enumerators before sync (fill-forward/filter/ect...)</param>
42  /// <param name="symbolUniverse">Symbol universe provider of the data queue</param>
43  /// <param name="timeProvider">The time provider instance used to determine when bars are completed and can be emitted</param>
44  public OptionChainUniverseSubscriptionEnumeratorFactory(Func<SubscriptionRequest, IEnumerator<BaseData>> enumeratorConfigurator,
45  IDataQueueUniverseProvider symbolUniverse, ITimeProvider timeProvider)
46  {
47  _isLiveMode = true;
48  _symbolUniverse = symbolUniverse;
49  _timeProvider = timeProvider;
50  _enumeratorConfigurator = enumeratorConfigurator;
51  }
52 
53  /// <summary>
54  /// Creates an enumerator to read the specified request
55  /// </summary>
56  /// <param name="request">The subscription request to be read</param>
57  /// <param name="dataProvider">Provider used to get data when it is not present on disk</param>
58  /// <returns>An enumerator reading the subscription request</returns>
59  public IEnumerator<BaseData> CreateEnumerator(SubscriptionRequest request, IDataProvider dataProvider)
60  {
61  if (_isLiveMode)
62  {
63  // configuring the enumerator
64  var subscriptionConfiguration = GetSubscriptionConfigurations(request).First();
65  var subscriptionRequest = new SubscriptionRequest(request, configuration: subscriptionConfiguration);
66  var configuredEnumerator = _enumeratorConfigurator(subscriptionRequest);
67 
68  return new DataQueueOptionChainUniverseDataCollectionEnumerator(subscriptionRequest, configuredEnumerator, _symbolUniverse, _timeProvider);
69  }
70  else
71  {
72  throw new InvalidOperationException($"Backtesting is expected to be using {nameof(BaseDataSubscriptionEnumeratorFactory)}");
73  }
74  }
75 
76  private IEnumerable<SubscriptionDataConfig> GetSubscriptionConfigurations(SubscriptionRequest request)
77  {
78  // canonical also needs underlying price data
79  var config = request.Configuration;
80  var underlying = config.Symbol.Underlying;
81 
82  // Making sure data is non-tick
83  var resolution = config.Resolution == Resolution.Tick ? Resolution.Second : config.Resolution;
84 
85  var configurations = new List<SubscriptionDataConfig>
86  {
87  // add underlying trade data
88  new SubscriptionDataConfig(config, resolution: resolution, fillForward: true, symbol: underlying, objectType: typeof (TradeBar), tickType: TickType.Trade),
89  };
90 
91  if (!_isLiveMode)
92  {
93  // rewrite the primary to be fill forward
94  configurations.Add(new SubscriptionDataConfig(config, resolution: resolution, fillForward: true));
95  }
96 
97  return configurations;
98  }
99  }
100 }