Lean  $LEAN_TAG$
CompositeDataProvider.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 System.IO;
18 using Newtonsoft.Json;
19 using QuantConnect.Util;
22 using System.Collections.Generic;
23 
25 {
26  /// <summary>
27  /// This data provider will wrap and use multiple data providers internally in the provided order
28  /// </summary>
30  {
31  /// <summary>
32  /// Event raised each time data fetch is finished (successfully or not)
33  /// </summary>
34  public event EventHandler<DataProviderNewDataRequestEventArgs> NewDataRequest;
35 
36  private readonly List<IDataProvider> _dataProviders;
37 
38  /// <summary>
39  /// Creates a new instance and initialize data providers used
40  /// </summary>
42  {
43  _dataProviders = new List<IDataProvider>();
44 
45  var dataProvidersConfig = Config.Get("composite-data-providers");
46  if (!string.IsNullOrEmpty(dataProvidersConfig))
47  {
48  var dataProviders = JsonConvert.DeserializeObject<List<string>>(dataProvidersConfig);
49  foreach (var dataProvider in dataProviders)
50  {
51  _dataProviders.Add(Composer.Instance.GetExportedValueByTypeName<IDataProvider>(dataProvider));
52  }
53 
54  if (_dataProviders.Count == 0)
55  {
56  throw new ArgumentException("CompositeDataProvider(): requires at least 1 valid data provider in 'composite-data-providers'");
57  }
58  }
59  else
60  {
61  throw new ArgumentException("CompositeDataProvider(): requires 'composite-data-providers' to be set with a valid type name");
62  }
63 
64  _dataProviders.ForEach(x => x.NewDataRequest += OnNewDataRequest);
65  }
66 
67  /// <summary>
68  /// Retrieves data to be used in an algorithm
69  /// </summary>
70  /// <param name="key">A string representing where the data is stored</param>
71  /// <returns>A <see cref="Stream"/> of the data requested</returns>
72  public Stream Fetch(string key)
73  {
74  for (var i = 0; i < _dataProviders.Count; i++)
75  {
76  var result = _dataProviders[i].Fetch(key);
77 
78  if (result != null)
79  {
80  return result;
81  }
82  }
83 
84  return null;
85  }
86 
87  /// <summary>
88  /// Event invocator for the <see cref="NewDataRequest"/> event
89  /// </summary>
90  private void OnNewDataRequest(object sender, DataProviderNewDataRequestEventArgs e)
91  {
92  NewDataRequest?.Invoke(this, e);
93  }
94  }
95 }