17 using System.Collections.Generic;
30 public partial class QCAlgorithm
35 private readonly
object _pendingUniverseAdditionsLock =
new object();
36 private readonly List<UserDefinedUniverseAddition> _pendingUserDefinedUniverseSecurityAdditions =
new List<UserDefinedUniverseAddition>();
37 private bool _pendingUniverseAdditions;
39 private readonly
int _rawNormalizationWarningSymbolsMaxCount = 10;
44 [DocumentationAttribute(Universes)]
69 lock (_pendingUniverseAdditionsLock)
71 if (!_pendingUniverseAdditions && _pendingUserDefinedUniverseSecurityAdditions.Count == 0)
77 var requiredHistoryRequests =
new Dictionary<Security, Resolution>();
79 foreach (var security
in Securities.Select(kvp => kvp.Value).Union(
80 _pendingUserDefinedUniverseSecurityAdditions.Select(x => x.Security)))
83 if (
Securities.Any(skvp => skvp.Key.SecurityType !=
SecurityType.Base && skvp.Key.HasUnderlyingSymbol(security.Symbol)))
86 ConfigureUnderlyingSecurity(security);
90 .GetSubscriptionDataConfigs(security.Symbol);
91 if (security.Symbol.HasUnderlying && security.Symbol.SecurityType !=
SecurityType.Base)
96 var resolution = configs.GetHighestResolution();
97 var isFillForward = configs.IsFillForward();
101 resolution = universe.UniverseSettings.Resolution;
102 isFillForward = universe.UniverseSettings.FillForward;
108 underlyingSecurity =
AddSecurity(underlyingSymbol.SecurityType,
109 underlyingSymbol.Value,
111 underlyingSymbol.ID.Market,
114 configs.IsExtendedMarketHours(),
119 ConfigureUnderlyingSecurity(underlyingSecurity);
121 if (
LiveMode && underlyingSecurity.GetLastData() ==
null)
123 if (requiredHistoryRequests.ContainsKey(underlyingSecurity))
126 var currentResolutionRequest = requiredHistoryRequests[underlyingSecurity];
127 if (currentResolutionRequest !=
Resolution.Minute
128 && resolution < currentResolutionRequest)
130 requiredHistoryRequests[underlyingSecurity] = (
Resolution)Math.Max((
int)resolution, (int)
Resolution.Minute);
135 requiredHistoryRequests.Add(underlyingSecurity, (
Resolution)Math.Max((
int)resolution, (int)
Resolution.Minute));
141 if (derivative !=
null)
148 if (!requiredHistoryRequests.IsNullOrEmpty())
152 foreach (var byResolution
in requiredHistoryRequests.GroupBy(x => x.Value))
154 historyRequests = historyRequests.Concat(
155 CreateBarCountHistoryRequests(byResolution.Select(x => x.Key.Symbol), 3, byResolution.Key));
158 var historicLastData =
History(historyRequests);
159 historicLastData.PushThrough(x =>
161 var security = requiredHistoryRequests.Keys.FirstOrDefault(y => y.Symbol == x.Symbol);
162 security?.Cache.AddData(x);
167 foreach (var userDefinedUniverseAddition
in _pendingUserDefinedUniverseSecurityAdditions)
169 foreach (var subscriptionDataConfig
in userDefinedUniverseAddition.SubscriptionDataConfigs)
171 userDefinedUniverseAddition.Universe.Add(subscriptionDataConfig);
180 _pendingUniverseAdditions =
false;
181 _pendingUserDefinedUniverseSecurityAdditions.Clear();
184 if (!_rawNormalizationWarningSymbols.IsNullOrEmpty())
187 Debug($
"Warning: The following securities were set to raw price normalization mode to work with options: " +
188 $
"{string.Join(",
", _rawNormalizationWarningSymbols.Take(_rawNormalizationWarningSymbolsMaxCount).Select(x => x.Value))}...");
191 _rawNormalizationWarningSymbols =
null;
217 _pendingUniverseAdditions =
true;
274 return AddUniverseStringSelector<T>(selector,
null, name);
289 return AddUniverse<T>(name,
null,
null, universeSettings, selector);
304 return AddUniverseStringSelector<T>(selector,
null, name,
null,
null, universeSettings);
334 return AddUniverseStringSelector<T>(selector,
null, name, resolution);
350 return AddUniverse<T>(name, resolution, market:
null, universeSettings, selector);
366 return AddUniverseStringSelector<T>(selector,
null, name, resolution, universeSettings: universeSettings);
397 return AddUniverseStringSelector<T>(selector, securityType, name, resolution, market);
413 return AddUniverseStringSelector<T>(selector, securityType, name, resolution, market, universeSettings);
427 Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector =
null)
429 return AddUniverseSymbolSelector(typeof(
T), name, resolution, market, universeSettings, selector);
453 otherSettings.Schedule.On(dateRule);
464 public Universe AddUniverse(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>> coarseSelector, Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> fineSelector)
522 var exchangeTimeZone = marketHoursDbEntry.ExchangeHours.TimeZone;
524 var config =
new SubscriptionDataConfig(typeof(
Fundamental), symbol, resolution, dataTimeZone, exchangeTimeZone,
false,
false,
true, isFilteredSubscription:
false);
551 throw new InvalidOperationException($
"Universe not found for underlying Symbol: {underlyingSymbol}.");
576 private Security AddToUserDefinedUniverse(
578 List<SubscriptionDataConfig> configurations)
580 var subscription = configurations.First();
584 if (!subscription.IsInternalFeed && existingSecurity.IsInternalFeed())
597 security = existingSecurity;
611 if (universe ==
null)
615 var uconfig =
new SubscriptionDataConfig(subscription, symbol: universeSymbol, isInternalFeed:
true, fillForward:
false,
616 exchangeTimeZone: DateTimeZone.Utc,
617 dataTimeZone: DateTimeZone.Utc);
627 subscription.Resolution,
629 subscription.FillDataForward,
630 subscription.ExtendedMarketHours,
640 if (userDefinedUniverse !=
null)
642 lock (_pendingUniverseAdditionsLock)
644 _pendingUserDefinedUniverseSecurityAdditions.
Add(
645 new UserDefinedUniverseAddition(userDefinedUniverse, configurations, security));
651 throw new Exception($
"Expected universe with symbol '{universeSymbol.Value}' to be of type {nameof(UserDefinedUniverse)} but was {universe.GetType().Name}.");
661 private void ConfigureUnderlyingSecurity(
Security security)
665 .GetSubscriptionDataConfigs(security.
Symbol);
670 if (_rawNormalizationWarningSymbols !=
null && _rawNormalizationWarningSymbols.
Count <= _rawNormalizationWarningSymbolsMaxCount)
672 _rawNormalizationWarningSymbols.Add(security.
Symbol);
691 if (!TryGetUniverseSymbol(dataType, market, out var universeSymbol))
693 market ??= Market.USA;
694 if (
string.IsNullOrEmpty(name))
696 name = $
"{dataType.Name}-{market}-{Guid.NewGuid()}";
703 var exchangeTimeZone = marketHoursDbEntry.ExchangeHours.TimeZone;
704 return new SubscriptionDataConfig(dataType, universeSymbol, resolution ??
Resolution.Daily, dataTimeZone, exchangeTimeZone,
false,
false,
true,
true, isFilteredSubscription:
false);
707 private bool TryGetUniverseSymbol(Type dataType,
string market, out
Symbol symbol)
719 private Universe AddUniverseStringSelector<T>(Func<IEnumerable<BaseData>, IEnumerable<string>> selector,
SecurityType? securityType =
null,
string name =
null,
722 if (market.IsNullOrEmpty())
727 Func<IEnumerable<BaseData>, IEnumerable<Symbol>> symbolSelector = data => selector(data).Select(x =>
QuantConnect.
Symbol.
Create(x, securityType.Value, market, baseDataType: typeof(
T)));
728 return AddUniverse<T>(name, resolution, market, universeSettings, symbolSelector);
731 private Universe AddUniverseSymbolSelector(Type dataType,
string name =
null,
Resolution? resolution =
null,
string market =
null,
UniverseSettings universeSettings =
null,
732 Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector =
null)
734 var config = GetCustomUniverseConfiguration(dataType, name, market, resolution);
742 private class UserDefinedUniverseAddition
746 public List<SubscriptionDataConfig> SubscriptionDataConfigs {
get; }
748 public UserDefinedUniverseAddition(
750 List<SubscriptionDataConfig> subscriptionDataConfigs,
754 SubscriptionDataConfigs = subscriptionDataConfigs;