Lean  $LEAN_TAG$
FundamentalUniverseSelectionModel.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.Linq;
18 using Python.Runtime;
20 using System.Collections.Generic;
23 
25 {
26  /// <summary>
27  /// Provides a base class for defining equity coarse/fine fundamental selection models
28  /// </summary>
30  {
31  private readonly string _market;
32  private readonly bool _fundamentalData;
33  private readonly bool _filterFineData;
34  private readonly UniverseSettings _universeSettings;
35  private readonly Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> _selector;
36 
37  /// <summary>
38  /// Initializes a new instance of the <see cref="FundamentalUniverseSelectionModel"/> class
39  /// </summary>
41  : this(Market.USA, null)
42  {
43  _fundamentalData = true;
44  }
45 
46  /// <summary>
47  /// Initializes a new instance of the <see cref="FundamentalUniverseSelectionModel"/> class
48  /// </summary>
49  /// <param name="market">The target market</param>
50  /// <param name="universeSettings">Universe settings define attributes of created subscriptions, such as their resolution and the minimum time in universe before they can be removed</param>
51  public FundamentalUniverseSelectionModel(string market, UniverseSettings universeSettings)
52  {
53  _market = market;
54  _fundamentalData = true;
55  _universeSettings = universeSettings;
56  }
57 
58  /// <summary>
59  /// Initializes a new instance of the <see cref="FundamentalUniverseSelectionModel"/> class
60  /// </summary>
61  /// <param name="universeSettings">Universe settings define attributes of created subscriptions, such as their resolution and the minimum time in universe before they can be removed</param>
63  : this(Market.USA, universeSettings)
64  {
65  }
66 
67  /// <summary>
68  /// Initializes a new instance of the <see cref="FundamentalUniverseSelectionModel"/> class
69  /// </summary>
70  /// <param name="market">The target market</param>
71  /// <param name="selector">Selects symbols from the provided fundamental data set</param>
72  /// <param name="universeSettings">Universe settings define attributes of created subscriptions, such as their resolution and the minimum time in universe before they can be removed</param>
73  public FundamentalUniverseSelectionModel(string market, Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> selector, UniverseSettings universeSettings = null)
74  {
75  _market = market;
76  _selector = selector;
77  _fundamentalData = true;
78  _universeSettings = universeSettings;
79  }
80 
81  /// <summary>
82  /// Initializes a new instance of the <see cref="FundamentalUniverseSelectionModel"/> class
83  /// </summary>
84  /// <param name="selector">Selects symbols from the provided fundamental data set</param>
85  /// <param name="universeSettings">Universe settings define attributes of created subscriptions, such as their resolution and the minimum time in universe before they can be removed</param>
86  public FundamentalUniverseSelectionModel(Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> selector, UniverseSettings universeSettings = null)
87  : this(Market.USA, selector, universeSettings)
88  {
89  }
90 
91  /// <summary>
92  /// Initializes a new instance of the <see cref="FundamentalUniverseSelectionModel"/> class
93  /// </summary>
94  /// <param name="market">The target market</param>
95  /// <param name="selector">Selects symbols from the provided fundamental data set</param>
96  /// <param name="universeSettings">Universe settings define attributes of created subscriptions, such as their resolution and the minimum time in universe before they can be removed</param>
97  public FundamentalUniverseSelectionModel(string market, PyObject selector, UniverseSettings universeSettings = null) : this(universeSettings)
98  {
99  _market = market;
100  Func<IEnumerable<Fundamental>, object> selectorFunc;
101  if (selector.TryConvertToDelegate(out selectorFunc))
102  {
103  _selector = selectorFunc.ConvertToUniverseSelectionSymbolDelegate();
104  }
105  }
106 
107  /// <summary>
108  /// Initializes a new instance of the <see cref="FundamentalUniverseSelectionModel"/> class
109  /// </summary>
110  /// <param name="selector">Selects symbols from the provided fundamental data set</param>
111  /// <param name="universeSettings">Universe settings define attributes of created subscriptions, such as their resolution and the minimum time in universe before they can be removed</param>
112  public FundamentalUniverseSelectionModel(PyObject selector, UniverseSettings universeSettings = null)
113  : this(Market.USA, selector, universeSettings)
114  {
115  }
116 
117  /// <summary>
118  /// Initializes a new instance of the <see cref="FundamentalUniverseSelectionModel"/> class
119  /// </summary>
120  /// <param name="filterFineData">True to also filter using fine fundamental data, false to only filter on coarse data</param>
121  [Obsolete("Fine and Coarse selection are merged, please use 'FundamentalUniverseSelectionModel()'")]
122  protected FundamentalUniverseSelectionModel(bool filterFineData)
123  : this(filterFineData, null)
124  {
125  }
126 
127  /// <summary>
128  /// Initializes a new instance of the <see cref="FundamentalUniverseSelectionModel"/> class
129  /// </summary>
130  /// <param name="filterFineData">True to also filter using fine fundamental data, false to only filter on coarse data</param>
131  /// <param name="universeSettings">The settings used when adding symbols to the algorithm, specify null to use algorithm.UniverseSettings</param>
132  [Obsolete("Fine and Coarse selection are merged, please use 'FundamentalUniverseSelectionModel(UniverseSettings)'")]
133  protected FundamentalUniverseSelectionModel(bool filterFineData, UniverseSettings universeSettings)
134  {
135  _market = Market.USA;
136  _filterFineData = filterFineData;
137  _universeSettings = universeSettings;
138  }
139 
140  /// <summary>
141  /// Creates a new fundamental universe using this class's selection functions
142  /// </summary>
143  /// <param name="algorithm">The algorithm instance to create universes for</param>
144  /// <returns>The universe defined by this model</returns>
145  public override IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm)
146  {
147  if (_fundamentalData)
148  {
149  var universeSettings = _universeSettings ?? algorithm.UniverseSettings;
150  yield return new FundamentalUniverseFactory(_market, universeSettings, fundamental => Select(algorithm, fundamental));
151  }
152  else
153  {
154  // for backwards compatibility
155  var universe = CreateCoarseFundamentalUniverse(algorithm);
156  if (_filterFineData)
157  {
158  if (universe.UniverseSettings.Asynchronous.HasValue && universe.UniverseSettings.Asynchronous.Value)
159  {
160  throw new ArgumentException("Asynchronous universe setting is not supported for coarse & fine selections, please use the new Fundamental single pass selection");
161  }
162 #pragma warning disable CS0618 // Type or member is obsolete
163  universe = new FineFundamentalFilteredUniverse(universe, fine => SelectFine(algorithm, fine));
164 #pragma warning restore CS0618 // Type or member is obsolete
165  }
166  yield return universe;
167  }
168  }
169 
170  /// <summary>
171  /// Creates the coarse fundamental universe object.
172  /// This is provided to allow more flexibility when creating coarse universe.
173  /// </summary>
174  /// <param name="algorithm">The algorithm instance</param>
175  /// <returns>The coarse fundamental universe</returns>
177  {
178  var universeSettings = _universeSettings ?? algorithm.UniverseSettings;
179  return new CoarseFundamentalUniverse(universeSettings, coarse =>
180  {
181  // if we're using fine fundamental selection than exclude symbols without fine data
182  if (_filterFineData)
183  {
184  coarse = coarse.Where(c => c.HasFundamentalData);
185  }
186 
187 #pragma warning disable CS0618 // Type or member is obsolete
188  return SelectCoarse(algorithm, coarse);
189 #pragma warning restore CS0618 // Type or member is obsolete
190  });
191  }
192 
193  /// <summary>
194  /// Defines the fundamental selection function.
195  /// </summary>
196  /// <param name="algorithm">The algorithm instance</param>
197  /// <param name="fundamental">The fundamental data used to perform filtering</param>
198  /// <returns>An enumerable of symbols passing the filter</returns>
199  public virtual IEnumerable<Symbol> Select(QCAlgorithm algorithm, IEnumerable<Fundamental> fundamental)
200  {
201  if(_selector == null)
202  {
203  throw new NotImplementedException("If inheriting, please overrride the 'Select' fundamental function, else provide it as a constructor parameter");
204  }
205  return _selector(fundamental);
206  }
207 
208  /// <summary>
209  /// Defines the coarse fundamental selection function.
210  /// </summary>
211  /// <param name="algorithm">The algorithm instance</param>
212  /// <param name="coarse">The coarse fundamental data used to perform filtering</param>
213  /// <returns>An enumerable of symbols passing the filter</returns>
214  [Obsolete("Fine and Coarse selection are merged, please use 'Select(QCAlgorithm, IEnumerable<Fundamental>)'")]
215  public virtual IEnumerable<Symbol> SelectCoarse(QCAlgorithm algorithm, IEnumerable<CoarseFundamental> coarse)
216  {
217  throw new NotImplementedException("Please overrride the 'Select' fundamental function");
218  }
219 
220  /// <summary>
221  /// Defines the fine fundamental selection function.
222  /// </summary>
223  /// <param name="algorithm">The algorithm instance</param>
224  /// <param name="fine">The fine fundamental data used to perform filtering</param>
225  /// <returns>An enumerable of symbols passing the filter</returns>
226  [Obsolete("Fine and Coarse selection are merged, please use 'Select(QCAlgorithm, IEnumerable<Fundamental>)'")]
227  public virtual IEnumerable<Symbol> SelectFine(QCAlgorithm algorithm, IEnumerable<FineFundamental> fine)
228  {
229  // default impl performs no filtering of fine data
230  return fine.Select(f => f.Symbol);
231  }
232 
233  /// <summary>
234  /// Convenience method for creating a selection model that uses only coarse data
235  /// </summary>
236  /// <param name="coarseSelector">Selects symbols from the provided coarse data set</param>
237  /// <returns>A new universe selection model that will select US equities according to the selection function specified</returns>
238  [Obsolete("Fine and Coarse selection are merged, please use 'Fundamental(Func<IEnumerable<Fundamental>, IEnumerable<Symbol>>)'")]
239  public static IUniverseSelectionModel Coarse(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>> coarseSelector)
240  {
241  return new CoarseFundamentalUniverseSelectionModel(coarseSelector);
242  }
243 
244  /// <summary>
245  /// Convenience method for creating a selection model that uses coarse and fine data
246  /// </summary>
247  /// <param name="coarseSelector">Selects symbols from the provided coarse data set</param>
248  /// <param name="fineSelector">Selects symbols from the provided fine data set (this set has already been filtered according to the coarse selection)</param>
249  /// <returns>A new universe selection model that will select US equities according to the selection functions specified</returns>
250  [Obsolete("Fine and Coarse selection are merged, please use 'Fundamental(Func<IEnumerable<Fundamental>, IEnumerable<Symbol>>)'")]
251  public static IUniverseSelectionModel Fine(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>> coarseSelector, Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> fineSelector)
252  {
253  return new FineFundamentalUniverseSelectionModel(coarseSelector, fineSelector);
254  }
255 
256  /// <summary>
257  /// Convenience method for creating a selection model that uses fundamental data
258  /// </summary>
259  /// <param name="selector">Selects symbols from the provided fundamental data set</param>
260  /// <returns>A new universe selection model that will select US equities according to the selection functions specified</returns>
261  public static IUniverseSelectionModel Fundamental(Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> selector)
262  {
263  return new FundamentalUniverseSelectionModel(selector);
264  }
265  }
266 }