Lean  $LEAN_TAG$
QCAlgorithm.Universe.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.Collections.Generic;
18 using System.Linq;
19 using NodaTime;
21 using QuantConnect.Data;
26 using QuantConnect.Util;
27 
28 namespace QuantConnect.Algorithm
29 {
30  public partial class QCAlgorithm
31  {
32  // save universe additions and apply at end of time step
33  // this removes temporal dependencies from w/in initialize method
34  // original motivation: adding equity/options to enforce equity raw data mode
35  private readonly object _pendingUniverseAdditionsLock = new object();
36  private readonly List<UserDefinedUniverseAddition> _pendingUserDefinedUniverseSecurityAdditions = new List<UserDefinedUniverseAddition>();
37  private bool _pendingUniverseAdditions;
38  private ConcurrentSet<Symbol> _rawNormalizationWarningSymbols = new ConcurrentSet<Symbol>();
39  private readonly int _rawNormalizationWarningSymbolsMaxCount = 10;
40 
41  /// <summary>
42  /// Gets universe manager which holds universes keyed by their symbol
43  /// </summary>
44  [DocumentationAttribute(Universes)]
46  {
47  get;
48  private set;
49  }
50 
51  /// <summary>
52  /// Gets the universe settings to be used when adding securities via universe selection
53  /// </summary>
54  [DocumentationAttribute(Universes)]
56  {
57  get;
58  private set;
59  }
60 
61  /// <summary>
62  /// Invoked at the end of every time step. This allows the algorithm
63  /// to process events before advancing to the next time step.
64  /// </summary>
65  [DocumentationAttribute(HandlingData)]
66  public void OnEndOfTimeStep()
67  {
68  // rewrite securities w/ derivatives to be in raw mode
69  lock (_pendingUniverseAdditionsLock)
70  {
71  if (!_pendingUniverseAdditions && _pendingUserDefinedUniverseSecurityAdditions.Count == 0)
72  {
73  // no point in looping through everything if there's no pending changes
74  return;
75  }
76 
77  var requiredHistoryRequests = new Dictionary<Security, Resolution>();
78 
79  foreach (var security in Securities.Select(kvp => kvp.Value).Union(
80  _pendingUserDefinedUniverseSecurityAdditions.Select(x => x.Security)))
81  {
82  // check for any derivative securities and mark the underlying as raw
83  if (Securities.Any(skvp => skvp.Key.SecurityType != SecurityType.Base && skvp.Key.HasUnderlyingSymbol(security.Symbol)))
84  {
85  // set data mode raw and default volatility model
86  ConfigureUnderlyingSecurity(security);
87  }
88 
90  .GetSubscriptionDataConfigs(security.Symbol);
91  if (security.Symbol.HasUnderlying && security.Symbol.SecurityType != SecurityType.Base)
92  {
93  Security underlyingSecurity;
94  var underlyingSymbol = security.Symbol.Underlying;
95  var resolution = configs.GetHighestResolution();
96 
97  // create the underlying security object if it doesn't already exist
98  if (!Securities.TryGetValue(underlyingSymbol, out underlyingSecurity))
99  {
100  underlyingSecurity = AddSecurity(underlyingSymbol.SecurityType,
101  underlyingSymbol.Value,
102  resolution,
103  underlyingSymbol.ID.Market,
104  configs.IsFillForward(),
106  configs.IsExtendedMarketHours(),
107  dataNormalizationMode: DataNormalizationMode.Raw);
108  }
109 
110  // set data mode raw and default volatility model
111  ConfigureUnderlyingSecurity(underlyingSecurity);
112 
113  if (LiveMode && underlyingSecurity.GetLastData() == null)
114  {
115  if (requiredHistoryRequests.ContainsKey(underlyingSecurity))
116  {
117  // lets request the higher resolution
118  var currentResolutionRequest = requiredHistoryRequests[underlyingSecurity];
119  if (currentResolutionRequest != Resolution.Minute // Can not be less than Minute
120  && resolution < currentResolutionRequest)
121  {
122  requiredHistoryRequests[underlyingSecurity] = (Resolution)Math.Max((int)resolution, (int)Resolution.Minute);
123  }
124  }
125  else
126  {
127  requiredHistoryRequests.Add(underlyingSecurity, (Resolution)Math.Max((int)resolution, (int)Resolution.Minute));
128  }
129  }
130  // set the underlying security on the derivative -- we do this in two places since it's possible
131  // to do AddOptionContract w/out the underlying already added and normalized properly
132  var derivative = security as IDerivativeSecurity;
133  if (derivative != null)
134  {
135  derivative.Underlying = underlyingSecurity;
136  }
137  }
138  }
139 
140  if (!requiredHistoryRequests.IsNullOrEmpty())
141  {
142  // Create requests
143  var historyRequests = Enumerable.Empty<HistoryRequest>();
144  foreach (var byResolution in requiredHistoryRequests.GroupBy(x => x.Value))
145  {
146  historyRequests = historyRequests.Concat(
147  CreateBarCountHistoryRequests(byResolution.Select(x => x.Key.Symbol), 3, byResolution.Key));
148  }
149  // Request data
150  var historicLastData = History(historyRequests);
151  historicLastData.PushThrough(x =>
152  {
153  var security = requiredHistoryRequests.Keys.FirstOrDefault(y => y.Symbol == x.Symbol);
154  security?.Cache.AddData(x);
155  });
156  }
157 
158  // add subscriptionDataConfig to their respective user defined universes
159  foreach (var userDefinedUniverseAddition in _pendingUserDefinedUniverseSecurityAdditions)
160  {
161  foreach (var subscriptionDataConfig in userDefinedUniverseAddition.SubscriptionDataConfigs)
162  {
163  userDefinedUniverseAddition.Universe.Add(subscriptionDataConfig);
164  }
165  }
166 
167  // finally add any pending universes, this will make them available to the data feed
168  // The universe will be added at the end of time step, same as the AddData user defined universes.
169  // This is required to be independent of the start and end date set during initialize
171 
172  _pendingUniverseAdditions = false;
173  _pendingUserDefinedUniverseSecurityAdditions.Clear();
174  }
175 
176  if (!_rawNormalizationWarningSymbols.IsNullOrEmpty())
177  {
178  // Log our securities being set to raw price mode
179  Debug($"Warning: The following securities were set to raw price normalization mode to work with options: " +
180  $"{string.Join(", ", _rawNormalizationWarningSymbols.Take(_rawNormalizationWarningSymbolsMaxCount).Select(x => x.Value))}...");
181 
182  // Set our warning list to null to stop emitting these warnings after its done once
183  _rawNormalizationWarningSymbols = null;
184  }
185  }
186 
187  /// <summary>
188  /// Gets a helper that provides pre-defined universe definitions, such as top dollar volume
189  /// </summary>
190  [DocumentationAttribute(Universes)]
192  {
193  get;
194  private set;
195  }
196 
197  /// <summary>
198  /// Adds the universe to the algorithm
199  /// </summary>
200  /// <param name="universe">The universe to be added</param>
201  [DocumentationAttribute(Universes)]
202  public Universe AddUniverse(Universe universe)
203  {
204  if (universe.UniverseSettings == null)
205  {
206  // set default value so that users don't need to pass it
208  }
209  _pendingUniverseAdditions = true;
210  // note: UniverseManager.Add uses TryAdd, so don't need to worry about duplicates here
211  UniverseManager.Add(universe.Configuration.Symbol, universe);
212  return universe;
213  }
214 
215  /// <summary>
216  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
217  /// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
218  /// of SecurityType.Equity, Resolution.Daily, Market.USA, and UniverseSettings
219  /// </summary>
220  /// <typeparam name="T">The data type</typeparam>
221  /// <param name="selector">Function delegate that performs selection on the universe data</param>
222  [DocumentationAttribute(Universes)]
223  public Universe AddUniverse<T>(Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
224  {
225  return AddUniverse<T>(null, selector);
226  }
227 
228  /// <summary>
229  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
230  /// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
231  /// of SecurityType.Equity, Resolution.Daily, Market.USA, and UniverseSettings
232  /// </summary>
233  /// <typeparam name="T">The data type</typeparam>
234  /// <param name="selector">Function delegate that performs selection on the universe data</param>
235  [DocumentationAttribute(Universes)]
236  public Universe AddUniverse<T>(Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
237  {
238  return AddUniverse<T>(null, selector);
239  }
240 
241  /// <summary>
242  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
243  /// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
244  /// of SecurityType.Equity, Resolution.Daily, Market.USA, and UniverseSettings
245  /// </summary>
246  /// <typeparam name="T">The data type</typeparam>
247  /// <param name="name">A unique name for this universe</param>
248  /// <param name="selector">Function delegate that performs selection on the universe data</param>
249  [DocumentationAttribute(Universes)]
250  public Universe AddUniverse<T>(string name, Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
251  {
252  return AddUniverse<T>(name, null, null, null, selector);
253  }
254 
255  /// <summary>
256  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
257  /// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
258  /// of SecurityType.Equity, Resolution.Daily, Market.USA, and UniverseSettings
259  /// </summary>
260  /// <typeparam name="T">The data type</typeparam>
261  /// <param name="name">A unique name for this universe</param>
262  /// <param name="selector">Function delegate that performs selection on the universe data</param>
263  [DocumentationAttribute(Universes)]
264  public Universe AddUniverse<T>(string name, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
265  {
266  return AddUniverseStringSelector<T>(selector, null, name);
267  }
268 
269  /// <summary>
270  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
271  /// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
272  /// of SecurityType.Equity, Resolution.Daily, and Market.USA
273  /// </summary>
274  /// <typeparam name="T">The data type</typeparam>
275  /// <param name="name">A unique name for this universe</param>
276  /// <param name="universeSettings">The settings used for securities added by this universe</param>
277  /// <param name="selector">Function delegate that performs selection on the universe data</param>
278  [DocumentationAttribute(Universes)]
279  public Universe AddUniverse<T>(string name, UniverseSettings universeSettings, Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
280  {
281  return AddUniverse<T>(name, null, null, universeSettings, selector);
282  }
283 
284  /// <summary>
285  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
286  /// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
287  /// of SecurityType.Equity, Resolution.Daily, and Market.USA
288  /// </summary>
289  /// <typeparam name="T">The data type</typeparam>
290  /// <param name="name">A unique name for this universe</param>
291  /// <param name="universeSettings">The settings used for securities added by this universe</param>
292  /// <param name="selector">Function delegate that performs selection on the universe data</param>
293  [DocumentationAttribute(Universes)]
294  public Universe AddUniverse<T>(string name, UniverseSettings universeSettings, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
295  {
296  return AddUniverseStringSelector<T>(selector, null, name, null, null, universeSettings);
297  }
298 
299  /// <summary>
300  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
301  /// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
302  /// of SecurityType.Equity, Market.USA and UniverseSettings
303  /// </summary>
304  /// <typeparam name="T">The data type</typeparam>
305  /// <param name="name">A unique name for this universe</param>
306  /// <param name="resolution">The expected resolution of the universe data</param>
307  /// <param name="selector">Function delegate that performs selection on the universe data</param>
308  [DocumentationAttribute(Universes)]
309  public Universe AddUniverse<T>(string name, Resolution resolution, Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
310  {
311  return AddUniverse<T>(name, resolution, null, null, selector);
312  }
313 
314  /// <summary>
315  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
316  /// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
317  /// of SecurityType.Equity, Market.USA and UniverseSettings
318  /// </summary>
319  /// <typeparam name="T">The data type</typeparam>
320  /// <param name="name">A unique name for this universe</param>
321  /// <param name="resolution">The expected resolution of the universe data</param>
322  /// <param name="selector">Function delegate that performs selection on the universe data</param>
323  [DocumentationAttribute(Universes)]
324  public Universe AddUniverse<T>(string name, Resolution resolution, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
325  {
326  return AddUniverseStringSelector<T>(selector, null, name, resolution);
327  }
328 
329  /// <summary>
330  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
331  /// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
332  /// of SecurityType.Equity, and Market.USA
333  /// </summary>
334  /// <typeparam name="T">The data type</typeparam>
335  /// <param name="name">A unique name for this universe</param>
336  /// <param name="resolution">The expected resolution of the universe data</param>
337  /// <param name="universeSettings">The settings used for securities added by this universe</param>
338  /// <param name="selector">Function delegate that performs selection on the universe data</param>
339  [DocumentationAttribute(Universes)]
340  public Universe AddUniverse<T>(string name, Resolution resolution, UniverseSettings universeSettings, Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
341  {
342  return AddUniverse<T>(name, resolution, market: null, universeSettings, selector);
343  }
344 
345  /// <summary>
346  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
347  /// specified via the <see cref="UniverseSettings"/> property. This universe will use the defaults
348  /// of SecurityType.Equity, and Market.USA
349  /// </summary>
350  /// <typeparam name="T">The data type</typeparam>
351  /// <param name="name">A unique name for this universe</param>
352  /// <param name="resolution">The expected resolution of the universe data</param>
353  /// <param name="universeSettings">The settings used for securities added by this universe</param>
354  /// <param name="selector">Function delegate that performs selection on the universe data</param>
355  [DocumentationAttribute(Universes)]
356  public Universe AddUniverse<T>(string name, Resolution resolution, UniverseSettings universeSettings, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
357  {
358  return AddUniverseStringSelector<T>(selector, null, name, resolution, universeSettings: universeSettings);
359  }
360 
361  /// <summary>
362  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
363  /// specified via the <see cref="UniverseSettings"/> property.
364  /// </summary>
365  /// <typeparam name="T">The data type</typeparam>
366  /// <param name="name">A unique name for this universe</param>
367  /// <param name="resolution">The expected resolution of the universe data</param>
368  /// <param name="market">The market for selected symbols</param>
369  /// <param name="selector">Function delegate that performs selection on the universe data</param>
370  [DocumentationAttribute(Universes)]
371  public Universe AddUniverse<T>(string name, Resolution resolution, string market, Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector)
372  {
373  return AddUniverse<T>(name, resolution, market, null, selector);
374  }
375 
376  /// <summary>
377  /// Creates a new universe and adds it to the algorithm. This will use the default universe settings
378  /// specified via the <see cref="UniverseSettings"/> property.
379  /// </summary>
380  /// <typeparam name="T">The data type</typeparam>
381  /// <param name="securityType">The security type the universe produces</param>
382  /// <param name="name">A unique name for this universe</param>
383  /// <param name="resolution">The expected resolution of the universe data</param>
384  /// <param name="market">The market for selected symbols</param>
385  /// <param name="selector">Function delegate that performs selection on the universe data</param>
386  [DocumentationAttribute(Universes)]
387  public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
388  {
389  return AddUniverseStringSelector<T>(selector, securityType, name, resolution, market);
390  }
391 
392  /// <summary>
393  /// Creates a new universe and adds it to the algorithm
394  /// </summary>
395  /// <typeparam name="T">The data type</typeparam>
396  /// <param name="securityType">The security type the universe produces</param>
397  /// <param name="name">A unique name for this universe</param>
398  /// <param name="resolution">The expected resolution of the universe data</param>
399  /// <param name="market">The market for selected symbols</param>
400  /// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
401  /// <param name="selector">Function delegate that performs selection on the universe data</param>
402  [DocumentationAttribute(Universes)]
403  public Universe AddUniverse<T>(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, Func<IEnumerable<BaseData>, IEnumerable<string>> selector)
404  {
405  return AddUniverseStringSelector<T>(selector, securityType, name, resolution, market, universeSettings);
406  }
407 
408  /// <summary>
409  /// Creates a new universe and adds it to the algorithm
410  /// </summary>
411  /// <typeparam name="T">The data type</typeparam>
412  /// <param name="name">A unique name for this universe</param>
413  /// <param name="resolution">The expected resolution of the universe data</param>
414  /// <param name="market">The market for selected symbols</param>
415  /// <param name="universeSettings">The subscription settings to use for newly created subscriptions</param>
416  /// <param name="selector">Function delegate that performs selection on the universe data</param>
417  [DocumentationAttribute(Universes)]
418  public Universe AddUniverse<T>(string name = null, Resolution? resolution = null, string market = null, UniverseSettings universeSettings = null,
419  Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector = null)
420  {
421  return AddUniverseSymbolSelector(typeof(T), name, resolution, market, universeSettings, selector);
422  }
423 
424  /// <summary>
425  /// Creates a new universe and adds it to the algorithm. This is for coarse fundamental US Equity data and
426  /// will be executed on day changes in the NewYork time zone (<see cref="TimeZones.NewYork"/>)
427  /// </summary>
428  /// <param name="selector">Defines an initial coarse selection</param>
429  [DocumentationAttribute(Universes)]
430  public Universe AddUniverse(Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> selector)
431  {
432  return AddUniverse(FundamentalUniverse.USA(selector));
433  }
434 
435  /// <summary>
436  /// Creates a new universe and adds it to the algorithm. This is for coarse fundamental US Equity data and
437  /// will be executed based on the provided <see cref="IDateRule"/> in the NewYork time zone (<see cref="TimeZones.NewYork"/>)
438  /// </summary>
439  /// <param name="dateRule">Date rule that will be used to set the <see cref="Data.UniverseSelection.UniverseSettings.Schedule"/></param>
440  /// <param name="selector">Defines an initial coarse selection</param>
441  [DocumentationAttribute(Universes)]
442  public Universe AddUniverse(IDateRule dateRule, Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> selector)
443  {
444  var otherSettings = new UniverseSettings(UniverseSettings);
445  otherSettings.Schedule.On(dateRule);
446  return AddUniverse(FundamentalUniverse.USA(selector, otherSettings));
447  }
448 
449  /// <summary>
450  /// Creates a new universe and adds it to the algorithm. This is for coarse and fine fundamental US Equity data and
451  /// will be executed on day changes in the NewYork time zone (<see cref="TimeZones.NewYork"/>)
452  /// </summary>
453  /// <param name="coarseSelector">Defines an initial coarse selection</param>
454  /// <param name="fineSelector">Defines a more detailed selection with access to more data</param>
455  [DocumentationAttribute(Universes)]
456  public Universe AddUniverse(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>> coarseSelector, Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> fineSelector)
457  {
458  var coarse = new CoarseFundamentalUniverse(UniverseSettings, coarseSelector);
459 
460  return AddUniverse(new FineFundamentalFilteredUniverse(coarse, fineSelector));
461  }
462 
463  /// <summary>
464  /// Creates a new universe and adds it to the algorithm. This is for fine fundamental US Equity data and
465  /// will be executed on day changes in the NewYork time zone (<see cref="TimeZones.NewYork"/>)
466  /// </summary>
467  /// <param name="universe">The universe to be filtered with fine fundamental selection</param>
468  /// <param name="fineSelector">Defines a more detailed selection with access to more data</param>
469  [DocumentationAttribute(Universes)]
470  public Universe AddUniverse(Universe universe, Func<IEnumerable<Fundamental>, IEnumerable<Symbol>> fineSelector)
471  {
472  return AddUniverse(new FundamentalFilteredUniverse(universe, fineSelector));
473  }
474 
475  /// <summary>
476  /// Creates a new universe and adds it to the algorithm. This can be used to return a list of string
477  /// symbols retrieved from anywhere and will loads those symbols under the US Equity market.
478  /// </summary>
479  /// <param name="name">A unique name for this universe</param>
480  /// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
481  [DocumentationAttribute(Universes)]
482  public Universe AddUniverse(string name, Func<DateTime, IEnumerable<string>> selector)
483  {
484  return AddUniverse(SecurityType.Equity, name, Resolution.Daily, Market.USA, UniverseSettings, selector);
485  }
486 
487  /// <summary>
488  /// Creates a new universe and adds it to the algorithm. This can be used to return a list of string
489  /// symbols retrieved from anywhere and will loads those symbols under the US Equity market.
490  /// </summary>
491  /// <param name="name">A unique name for this universe</param>
492  /// <param name="resolution">The resolution this universe should be triggered on</param>
493  /// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
494  [DocumentationAttribute(Universes)]
495  public Universe AddUniverse(string name, Resolution resolution, Func<DateTime, IEnumerable<string>> selector)
496  {
497  return AddUniverse(SecurityType.Equity, name, resolution, Market.USA, UniverseSettings, selector);
498  }
499 
500  /// <summary>
501  /// Creates a new user defined universe that will fire on the requested resolution during market hours.
502  /// </summary>
503  /// <param name="securityType">The security type of the universe</param>
504  /// <param name="name">A unique name for this universe</param>
505  /// <param name="resolution">The resolution this universe should be triggered on</param>
506  /// <param name="market">The market of the universe</param>
507  /// <param name="universeSettings">The subscription settings used for securities added from this universe</param>
508  /// <param name="selector">Function delegate that accepts a DateTime and returns a collection of string symbols</param>
509  [DocumentationAttribute(Universes)]
510  public Universe AddUniverse(SecurityType securityType, string name, Resolution resolution, string market, UniverseSettings universeSettings, Func<DateTime, IEnumerable<string>> selector)
511  {
512  var marketHoursDbEntry = MarketHoursDatabase.GetEntry(market, name, securityType);
513  var dataTimeZone = marketHoursDbEntry.DataTimeZone;
514  var exchangeTimeZone = marketHoursDbEntry.ExchangeHours.TimeZone;
515  var symbol = QuantConnect.Symbol.Create(name, securityType, market);
516  var config = new SubscriptionDataConfig(typeof(Fundamental), symbol, resolution, dataTimeZone, exchangeTimeZone, false, false, true, isFilteredSubscription: false);
517  return AddUniverse(new UserDefinedUniverse(config, universeSettings, resolution.ToTimeSpan(), selector));
518  }
519 
520  /// <summary>
521  /// Adds a new universe that creates options of the security by monitoring any changes in the Universe the provided security is in.
522  /// Additionally, a filter can be applied to the options generated when the universe of the security changes.
523  /// </summary>
524  /// <param name="underlyingSymbol">Underlying Symbol to add as an option. For Futures, the option chain constructed will be per-contract, as long as a canonical Symbol is provided.</param>
525  /// <param name="optionFilter">User-defined filter used to select the options we want out of the option chain provided.</param>
526  /// <exception cref="InvalidOperationException">The underlying Symbol's universe is not found.</exception>
527  [DocumentationAttribute(Universes)]
528  public void AddUniverseOptions(Symbol underlyingSymbol, Func<OptionFilterUniverse, OptionFilterUniverse> optionFilter)
529  {
530  // We need to load the universe associated with the provided Symbol and provide that universe to the option filter universe.
531  // The option filter universe will subscribe to any changes in the universe of the underlying Symbol,
532  // ensuring that we load the option chain for every asset found in the underlying's Universe.
533  Universe universe;
534  if (!UniverseManager.TryGetValue(underlyingSymbol, out universe))
535  {
536  underlyingSymbol = AddSecurity(underlyingSymbol).Symbol;
537 
538  // Recheck again, we should have a universe addition pending for the provided Symbol
539  if (!UniverseManager.TryGetValue(underlyingSymbol, out universe))
540  {
541  // Should never happen, but it could be that the subscription
542  // created with AddSecurity is not aligned with the Symbol we're using.
543  throw new InvalidOperationException($"Universe not found for underlying Symbol: {underlyingSymbol}.");
544  }
545  }
546 
547  // Allow all option contracts through without filtering if we're provided a null filter.
548  AddUniverseOptions(universe, optionFilter ?? (_ => _));
549  }
550 
551  /// <summary>
552  /// Creates a new universe selection model and adds it to the algorithm. This universe selection model will chain to the security
553  /// changes of a given <see cref="Universe"/> selection output and create a new <see cref="OptionChainUniverse"/> for each of them
554  /// </summary>
555  /// <param name="universe">The universe we want to chain an option universe selection model too</param>
556  /// <param name="optionFilter">The option filter universe to use</param>
557  [DocumentationAttribute(Universes)]
558  public void AddUniverseOptions(Universe universe, Func<OptionFilterUniverse, OptionFilterUniverse> optionFilter)
559  {
560  AddUniverseSelection(new OptionChainedUniverseSelectionModel(universe, optionFilter));
561  }
562 
563  /// <summary>
564  /// Adds the security to the user defined universe
565  /// </summary>
566  /// <param name="security">The security to add</param>
567  /// <param name="configurations">The <see cref="SubscriptionDataConfig"/> instances we want to add</param>
568  private Security AddToUserDefinedUniverse(
569  Security security,
570  List<SubscriptionDataConfig> configurations)
571  {
572  var subscription = configurations.First();
573  // if we are adding a non-internal security which already has an internal feed, we remove it first
574  if (Securities.TryGetValue(security.Symbol, out var existingSecurity))
575  {
576  if (!subscription.IsInternalFeed && existingSecurity.IsInternalFeed())
577  {
578  var securityUniverse = UniverseManager.Select(x => x.Value).OfType<UserDefinedUniverse>().FirstOrDefault(x => x.Members.ContainsKey(security.Symbol));
579  securityUniverse?.Remove(security.Symbol);
580 
581  Securities.Remove(security.Symbol);
582  Securities.Add(security);
583  }
584  else
585  {
586  var isTradable = security.IsTradable;
587  // We will reuse existing so we return it to the user.
588  // We will use the IsTradable flag of the new security, since existing could of been set to false when removed
589  security = existingSecurity;
590  security.IsTradable = isTradable;
591  }
592  }
593  else
594  {
595  Securities.Add(security);
596  }
597 
598  // add this security to the user defined universe
599  Universe universe;
600  var universeSymbol = UserDefinedUniverse.CreateSymbol(security.Type, security.Symbol.ID.Market);
601  if (!UniverseManager.TryGetValue(universeSymbol, out universe))
602  {
603  if (universe == null)
604  {
605  // create a new universe, these subscription settings don't currently get used
606  // since universe selection proper is never invoked on this type of universe
607  var uconfig = new SubscriptionDataConfig(subscription, symbol: universeSymbol, isInternalFeed: true, fillForward: false,
608  exchangeTimeZone: DateTimeZone.Utc,
609  dataTimeZone: DateTimeZone.Utc);
610 
611  // this is the universe symbol, has no real entry in the mhdb, will default to market and security type
612  // set entry in market hours database for the universe subscription to match the config
613  var symbolString = MarketHoursDatabase.GetDatabaseSymbolKey(uconfig.Symbol);
614  MarketHoursDatabase.SetEntry(uconfig.Market, symbolString, uconfig.SecurityType,
615  SecurityExchangeHours.AlwaysOpen(uconfig.ExchangeTimeZone), uconfig.DataTimeZone);
616 
617  universe = new UserDefinedUniverse(uconfig,
618  new UniverseSettings(
619  subscription.Resolution,
620  security.Leverage,
621  subscription.FillDataForward,
622  subscription.ExtendedMarketHours,
623  TimeSpan.Zero),
625  new List<Symbol>());
626 
627  AddUniverse(universe);
628  }
629  }
630 
631  var userDefinedUniverse = universe as UserDefinedUniverse;
632  if (userDefinedUniverse != null)
633  {
634  lock (_pendingUniverseAdditionsLock)
635  {
636  _pendingUserDefinedUniverseSecurityAdditions.Add(
637  new UserDefinedUniverseAddition(userDefinedUniverse, configurations, security));
638  }
639  }
640  else
641  {
642  // should never happen, someone would need to add a non-user defined universe with this symbol
643  throw new Exception($"Expected universe with symbol '{universeSymbol.Value}' to be of type {nameof(UserDefinedUniverse)} but was {universe.GetType().Name}.");
644  }
645 
646  return security;
647  }
648 
649  /// <summary>
650  /// Configures the security to be in raw data mode and ensures that a reasonable default volatility model is supplied
651  /// </summary>
652  /// <param name="security">The underlying security</param>
653  private void ConfigureUnderlyingSecurity(Security security)
654  {
655  // force underlying securities to be raw data mode
657  .GetSubscriptionDataConfigs(security.Symbol);
658  if (configs.DataNormalizationMode() != DataNormalizationMode.Raw)
659  {
660  // Add this symbol to our set of raw normalization warning symbols to alert the user at the end
661  // Set a hard limit to avoid growing this collection unnecessarily large
662  if (_rawNormalizationWarningSymbols != null && _rawNormalizationWarningSymbols.Count <= _rawNormalizationWarningSymbolsMaxCount)
663  {
664  _rawNormalizationWarningSymbols.Add(security.Symbol);
665  }
666 
667  configs.SetDataNormalizationMode(DataNormalizationMode.Raw);
668  // For backward compatibility we need to refresh the security DataNormalizationMode Property
670  }
671  }
672 
673  /// <summary>
674  /// Helper method to create the configuration of a custom universe
675  /// </summary>
676  private SubscriptionDataConfig GetCustomUniverseConfiguration(Type dataType, string name, string market, Resolution? resolution = null)
677  {
678  if (dataType == typeof(CoarseFundamental) || dataType == typeof(FineFundamental))
679  {
680  dataType = typeof(FundamentalUniverse);
681  }
682 
683  if (!TryGetUniverseSymbol(dataType, market, out var universeSymbol))
684  {
685  market ??= Market.USA;
686  if (string.IsNullOrEmpty(name))
687  {
688  name = $"{dataType.Name}-{market}-{Guid.NewGuid()}";
689  }
690  // same as 'AddData<>' 'T' type will be treated as custom/base data type with always open market hours
691  universeSymbol = QuantConnect.Symbol.Create(name, SecurityType.Base, market, baseDataType: dataType);
692  }
693  var marketHoursDbEntry = MarketHoursDatabase.GetEntry(universeSymbol, new[] { dataType });
694  var dataTimeZone = marketHoursDbEntry.DataTimeZone;
695  var exchangeTimeZone = marketHoursDbEntry.ExchangeHours.TimeZone;
696  return new SubscriptionDataConfig(dataType, universeSymbol, resolution ?? Resolution.Daily, dataTimeZone, exchangeTimeZone, false, false, true, true, isFilteredSubscription: false);
697  }
698 
699  private bool TryGetUniverseSymbol(Type dataType, string market, out Symbol symbol)
700  {
701  symbol = null;
702  if (dataType.IsAssignableTo(typeof(BaseDataCollection)))
703  {
704  var instance = dataType.GetBaseDataInstance() as BaseDataCollection;
705  symbol = instance.UniverseSymbol(market);
706  return true;
707  }
708  return false;
709  }
710 
711  private Universe AddUniverseStringSelector<T>(Func<IEnumerable<BaseData>, IEnumerable<string>> selector, SecurityType? securityType = null, string name = null,
712  Resolution? resolution = null, string market = null, UniverseSettings universeSettings = null)
713  {
714  if (market.IsNullOrEmpty())
715  {
716  market = Market.USA;
717  }
718  securityType ??= SecurityType.Equity;
719  Func<IEnumerable<BaseData>, IEnumerable<Symbol>> symbolSelector = data => selector(data).Select(x => QuantConnect.Symbol.Create(x, securityType.Value, market, baseDataType: typeof(T)));
720  return AddUniverse<T>(name, resolution, market, universeSettings, symbolSelector);
721  }
722 
723  private Universe AddUniverseSymbolSelector(Type dataType, string name = null, Resolution? resolution = null, string market = null, UniverseSettings universeSettings = null,
724  Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector = null)
725  {
726  var config = GetCustomUniverseConfiguration(dataType, name, market, resolution);
727  return AddUniverse(new FuncUniverse(config, universeSettings, selector));
728  }
729 
730  /// <summary>
731  /// Helper class used to store <see cref="UserDefinedUniverse"/> additions.
732  /// They will be consumed at <see cref="OnEndOfTimeStep"/>
733  /// </summary>
734  private class UserDefinedUniverseAddition
735  {
736  public Security Security { get; }
737  public UserDefinedUniverse Universe { get; }
738  public List<SubscriptionDataConfig> SubscriptionDataConfigs { get; }
739 
740  public UserDefinedUniverseAddition(
741  UserDefinedUniverse universe,
742  List<SubscriptionDataConfig> subscriptionDataConfigs,
743  Security security)
744  {
745  Universe = universe;
746  SubscriptionDataConfigs = subscriptionDataConfigs;
747  Security = security;
748  }
749  }
750  }
751 }