Exemple #1
0
        /// <summary>
        /// Creates and adds a list of <see cref="SubscriptionDataConfig" /> for a given symbol and configuration.
        /// Can optionally pass in desired subscription data types to use.
        ///  If the config already existed will return existing instance instead
        /// </summary>
        public List <SubscriptionDataConfig> Add(
            Symbol symbol,
            Resolution?resolution       = null,
            bool fillForward            = true,
            bool extendedMarketHours    = false,
            bool isFilteredSubscription = true,
            bool isInternalFeed         = false,
            bool isCustomData           = false,
            List <Tuple <Type, TickType> > subscriptionDataTypes = null,
            DataNormalizationMode dataNormalizationMode          = DataNormalizationMode.Adjusted
            )
        {
            var dataTypes = subscriptionDataTypes ??
                            LookupSubscriptionConfigDataTypes(symbol.SecurityType, resolution ?? Resolution.Minute, symbol.IsCanonical());

            if (!dataTypes.Any())
            {
                throw new ArgumentNullException(nameof(dataTypes), "At least one type needed to create new subscriptions");
            }

            var resolutionWasProvided = resolution.HasValue;

            foreach (var typeTuple in dataTypes)
            {
                var baseInstance = typeTuple.Item1.GetBaseDataInstance();
                baseInstance.Symbol = symbol;
                if (!resolutionWasProvided)
                {
                    var defaultResolution = baseInstance.DefaultResolution();
                    if (resolution.HasValue && resolution != defaultResolution)
                    {
                        // we are here because there are multiple 'dataTypes'.
                        // if we get different default resolutions lets throw, this shouldn't happen
                        throw new InvalidOperationException(
                                  $"Different data types ({string.Join(",", dataTypes.Select(tuple => tuple.Item1))})" +
                                  $" provided different default resolutions {defaultResolution} and {resolution}, this is an unexpected invalid operation.");
                    }
                    resolution = defaultResolution;
                }
                else
                {
                    // only assert resolution in backtesting, live can use other data source
                    // for example daily data for options
                    if (!_liveMode)
                    {
                        var supportedResolutions = baseInstance.SupportedResolutions();
                        if (supportedResolutions.Contains(resolution.Value))
                        {
                            continue;
                        }

                        throw new ArgumentException($"Sorry {resolution.ToStringInvariant()} is not a supported resolution for {typeTuple.Item1.Name}" +
                                                    $" and SecurityType.{symbol.SecurityType.ToStringInvariant()}." +
                                                    $" Please change your AddData to use one of the supported resolutions ({string.Join(",", supportedResolutions)}).");
                    }
                }
            }

            MarketHoursDatabase.Entry marketHoursDbEntry;
            if (!_marketHoursDatabase.TryGetEntry(symbol.ID.Market, symbol, symbol.ID.SecurityType, out marketHoursDbEntry))
            {
                if (symbol.SecurityType == SecurityType.Base)
                {
                    var baseInstance = dataTypes.Single().Item1.GetBaseDataInstance();
                    baseInstance.Symbol = symbol;
                    _marketHoursDatabase.SetEntryAlwaysOpen(symbol.ID.Market, null, SecurityType.Base, baseInstance.DataTimeZone());
                }

                marketHoursDbEntry = _marketHoursDatabase.GetEntry(symbol.ID.Market, symbol, symbol.ID.SecurityType);
            }

            var exchangeHours = marketHoursDbEntry.ExchangeHours;

            if (symbol.ID.SecurityType.IsOption() ||
                symbol.ID.SecurityType == SecurityType.Future ||
                symbol.ID.SecurityType == SecurityType.Index)
            {
                dataNormalizationMode = DataNormalizationMode.Raw;
            }

            if (marketHoursDbEntry.DataTimeZone == null)
            {
                throw new ArgumentNullException(nameof(marketHoursDbEntry.DataTimeZone),
                                                "DataTimeZone is a required parameter for new subscriptions. Set to the time zone the raw data is time stamped in.");
            }

            if (exchangeHours.TimeZone == null)
            {
                throw new ArgumentNullException(nameof(exchangeHours.TimeZone),
                                                "ExchangeTimeZone is a required parameter for new subscriptions. Set to the time zone the security exchange resides in.");
            }

            var result = (from subscriptionDataType in dataTypes
                          let dataType = subscriptionDataType.Item1
                                         let tickType = subscriptionDataType.Item2
                                                        select new SubscriptionDataConfig(
                              dataType,
                              symbol,
                              resolution.Value,
                              marketHoursDbEntry.DataTimeZone,
                              exchangeHours.TimeZone,
                              fillForward,
                              extendedMarketHours,
                              // if the subscription data types were not provided and the tick type is OpenInterest we make it internal
                              subscriptionDataTypes == null && tickType == TickType.OpenInterest || isInternalFeed,
                              isCustomData,
                              isFilteredSubscription: isFilteredSubscription,
                              tickType: tickType,
                              dataNormalizationMode: dataNormalizationMode)).ToList();

            for (int i = 0; i < result.Count; i++)
            {
                result[i] = SubscriptionManagerGetOrAdd(result[i]);

                // track all registered data types
                _registeredTypesProvider.RegisterType(result[i].Type);
            }
            return(result);
        }