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)
95 var resolution = configs.GetHighestResolution();
100 underlyingSecurity =
AddSecurity(underlyingSymbol.SecurityType,
101 underlyingSymbol.Value,
103 underlyingSymbol.ID.Market,
104 configs.IsFillForward(),
106 configs.IsExtendedMarketHours(),
111 ConfigureUnderlyingSecurity(underlyingSecurity);
113 if (
LiveMode && underlyingSecurity.GetLastData() ==
null)
115 if (requiredHistoryRequests.ContainsKey(underlyingSecurity))
118 var currentResolutionRequest = requiredHistoryRequests[underlyingSecurity];
119 if (currentResolutionRequest !=
Resolution.Minute
120 && resolution < currentResolutionRequest)
122 requiredHistoryRequests[underlyingSecurity] = (
Resolution)Math.Max((
int)resolution, (int)
Resolution.Minute);
127 requiredHistoryRequests.Add(underlyingSecurity, (
Resolution)Math.Max((
int)resolution, (int)
Resolution.Minute));
133 if (derivative !=
null)
140 if (!requiredHistoryRequests.IsNullOrEmpty())
144 foreach (var byResolution
in requiredHistoryRequests.GroupBy(x => x.Value))
146 historyRequests = historyRequests.Concat(
147 CreateBarCountHistoryRequests(byResolution.Select(x => x.Key.Symbol), 3, byResolution.Key));
150 var historicLastData =
History(historyRequests);
151 historicLastData.PushThrough(x =>
153 var security = requiredHistoryRequests.Keys.FirstOrDefault(y => y.Symbol == x.Symbol);
154 security?.Cache.AddData(x);
159 foreach (var userDefinedUniverseAddition
in _pendingUserDefinedUniverseSecurityAdditions)
161 foreach (var subscriptionDataConfig
in userDefinedUniverseAddition.SubscriptionDataConfigs)
163 userDefinedUniverseAddition.Universe.Add(subscriptionDataConfig);
172 _pendingUniverseAdditions =
false;
173 _pendingUserDefinedUniverseSecurityAdditions.Clear();
176 if (!_rawNormalizationWarningSymbols.IsNullOrEmpty())
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))}...");
183 _rawNormalizationWarningSymbols =
null;
209 _pendingUniverseAdditions =
true;
266 return AddUniverseStringSelector<T>(selector,
null, name);
281 return AddUniverse<T>(name,
null,
null, universeSettings, selector);
296 return AddUniverseStringSelector<T>(selector,
null, name,
null,
null, universeSettings);
326 return AddUniverseStringSelector<T>(selector,
null, name, resolution);
342 return AddUniverse<T>(name, resolution, market:
null, universeSettings, selector);
358 return AddUniverseStringSelector<T>(selector,
null, name, resolution, universeSettings: universeSettings);
389 return AddUniverseStringSelector<T>(selector, securityType, name, resolution, market);
405 return AddUniverseStringSelector<T>(selector, securityType, name, resolution, market, universeSettings);
419 Func<IEnumerable<BaseData>, IEnumerable<Symbol>> selector =
null)
421 return AddUniverseSymbolSelector(typeof(
T), name, resolution, market, universeSettings, selector);
445 otherSettings.Schedule.On(dateRule);
456 public Universe AddUniverse(Func<IEnumerable<CoarseFundamental>, IEnumerable<Symbol>> coarseSelector, Func<IEnumerable<FineFundamental>, IEnumerable<Symbol>> fineSelector)
514 var exchangeTimeZone = marketHoursDbEntry.ExchangeHours.TimeZone;
516 var config =
new SubscriptionDataConfig(typeof(
Fundamental), symbol, resolution, dataTimeZone, exchangeTimeZone,
false,
false,
true, isFilteredSubscription:
false);
543 throw new InvalidOperationException($
"Universe not found for underlying Symbol: {underlyingSymbol}.");
568 private Security AddToUserDefinedUniverse(
570 List<SubscriptionDataConfig> configurations)
572 var subscription = configurations.First();
576 if (!subscription.IsInternalFeed && existingSecurity.IsInternalFeed())
589 security = existingSecurity;
603 if (universe ==
null)
607 var uconfig =
new SubscriptionDataConfig(subscription, symbol: universeSymbol, isInternalFeed:
true, fillForward:
false,
608 exchangeTimeZone: DateTimeZone.Utc,
609 dataTimeZone: DateTimeZone.Utc);
619 subscription.Resolution,
621 subscription.FillDataForward,
622 subscription.ExtendedMarketHours,
632 if (userDefinedUniverse !=
null)
634 lock (_pendingUniverseAdditionsLock)
636 _pendingUserDefinedUniverseSecurityAdditions.
Add(
637 new UserDefinedUniverseAddition(userDefinedUniverse, configurations, security));
643 throw new Exception($
"Expected universe with symbol '{universeSymbol.Value}' to be of type {nameof(UserDefinedUniverse)} but was {universe.GetType().Name}.");
653 private void ConfigureUnderlyingSecurity(
Security security)
657 .GetSubscriptionDataConfigs(security.
Symbol);
662 if (_rawNormalizationWarningSymbols !=
null && _rawNormalizationWarningSymbols.
Count <= _rawNormalizationWarningSymbolsMaxCount)
664 _rawNormalizationWarningSymbols.Add(security.
Symbol);
683 if (!TryGetUniverseSymbol(dataType, market, out var universeSymbol))
685 market ??= Market.USA;
686 if (
string.IsNullOrEmpty(name))
688 name = $
"{dataType.Name}-{market}-{Guid.NewGuid()}";
695 var exchangeTimeZone = marketHoursDbEntry.ExchangeHours.TimeZone;
696 return new SubscriptionDataConfig(dataType, universeSymbol, resolution ??
Resolution.Daily, dataTimeZone, exchangeTimeZone,
false,
false,
true,
true, isFilteredSubscription:
false);
699 private bool TryGetUniverseSymbol(Type dataType,
string market, out
Symbol symbol)
711 private Universe AddUniverseStringSelector<T>(Func<IEnumerable<BaseData>, IEnumerable<string>> selector,
SecurityType? securityType =
null,
string name =
null,
714 if (market.IsNullOrEmpty())
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);
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)
726 var config = GetCustomUniverseConfiguration(dataType, name, market, resolution);
734 private class UserDefinedUniverseAddition
738 public List<SubscriptionDataConfig> SubscriptionDataConfigs {
get; }
740 public UserDefinedUniverseAddition(
742 List<SubscriptionDataConfig> subscriptionDataConfigs,
746 SubscriptionDataConfigs = subscriptionDataConfigs;