예제 #1
0
파일: QuantBook.cs 프로젝트: yuzhucu/Lean
        /// <summary>
        /// Gets <see cref="OptionHistory"/> object for a given symbol, date and resolution
        /// </summary>
        /// <param name="symbol">The symbol to retrieve historical option data for</param>
        /// <param name="date">Date of the data</param>
        /// <param name="resolution">The resolution to request</param>
        /// <returns>A <see cref="OptionHistory"/> object that contains historical option data.</returns>
        public OptionHistory GetOptionHistory(Symbol symbol, DateTime date, Resolution?resolution = null)
        {
            SetStartDate(date.AddDays(1));
            var option     = _algorithm.Securities[symbol] as Option;
            var underlying = AddEquity(symbol.Underlying.Value, option.Resolution);

            var provider   = new BacktestingOptionChainProvider();
            var allSymbols = provider.GetOptionContractList(symbol.Underlying, date);

            var requests = _algorithm.History(symbol.Underlying, TimeSpan.FromDays(1), resolution)
                           .SelectMany(x => option.ContractFilter.Filter(new OptionFilterUniverse(allSymbols, x)))
                           .Distinct()
                           .Select(x =>
                                   new HistoryRequest(date.AddDays(-1),
                                                      date,
                                                      typeof(QuoteBar),
                                                      x,
                                                      resolution ?? option.Resolution,
                                                      underlying.Exchange.Hours,
                                                      MarketHoursDatabase.FromDataFolder().GetDataTimeZone(underlying.Symbol.ID.Market, underlying.Symbol, underlying.Type),
                                                      Resolution.Minute,
                                                      underlying.IsExtendedMarketHours,
                                                      underlying.IsCustomData(),
                                                      DataNormalizationMode.Raw,
                                                      LeanData.GetCommonTickTypeForCommonDataTypes(typeof(QuoteBar), underlying.Type))
                                   );

            requests = requests.Union(new[] { new HistoryRequest(underlying.Subscriptions.FirstOrDefault(), underlying.Exchange.Hours, date.AddDays(-1), date) });

            return(new OptionHistory(_algorithm.HistoryProvider.GetHistory(requests.OrderByDescending(x => x.Symbol.SecurityType), _algorithm.TimeZone).Memoize()));
        }
예제 #2
0
        /// <summary>
        /// Returns history requirements for the volatility model expressed in the form of history request
        /// </summary>
        /// <param name="security">The security of the request</param>
        /// <param name="utcTime">The date/time of the request</param>
        /// <returns>History request object list, or empty if no requirements</returns>
        public override IEnumerable <HistoryRequest> GetHistoryRequirements(Security security, DateTime utcTime)
        {
            var barCount       = _window.Size + 1;
            var localStartTime = Time.GetStartTimeForTradeBars(security.Exchange.Hours, utcTime.ConvertFromUtc(security.Exchange.TimeZone), _periodSpan, barCount, security.IsExtendedMarketHours);
            var utcStartTime   = localStartTime.ConvertToUtc(security.Exchange.TimeZone);

            if (SubscriptionDataConfigProvider == null)
            {
                throw new Exception(
                          "RelativeStandardDeviationVolatilityModel.GetHistoryRequirements(): " +
                          "SubscriptionDataConfigProvider was not set."
                          );
            }
            var configurations = SubscriptionDataConfigProvider
                                 .GetSubscriptionDataConfigs(security.Symbol)
                                 .ToList();
            var configuration = configurations.First();

            return(new[]
            {
                new HistoryRequest(utcStartTime,
                                   utcTime,
                                   typeof(TradeBar),
                                   configuration.Symbol,
                                   configurations.GetHighestResolution(),
                                   security.Exchange.Hours,
                                   configuration.DataTimeZone,
                                   configurations.GetHighestResolution(),
                                   configurations.IsExtendedMarketHours(),
                                   configurations.IsCustomData(),
                                   configurations.DataNormalizationMode(),
                                   LeanData.GetCommonTickTypeForCommonDataTypes(typeof(TradeBar), security.Type))
            });
        }
예제 #3
0
        /// <summary>
        /// Gets <see cref="FutureHistory"/> object for a given symbol, date and resolution
        /// </summary>
        /// <param name="symbol">The symbol to retrieve historical future data for</param>
        /// <param name="date">Date of the data</param>
        /// <param name="resolution">The resolution to request</param>
        /// <returns>A <see cref="FutureHistory"/> object that contains historical future data.</returns>
        public FutureHistory GetFutureHistory(Symbol symbol, DateTime date, Resolution? resolution = null)
        {
            SetStartDate(date.AddDays(1));
            var future = Securities[symbol] as Future;

            var provider = new BacktestingFutureChainProvider();
            var allSymbols = provider.GetFutureContractList(future.Symbol, date);

            var requests = future.ContractFilter.Filter(new FutureFilterUniverse(allSymbols, new Tick { Time = date }))
                .Select(x =>
                     new HistoryRequest(date.AddDays(-1),
                                        date,
                                        typeof(QuoteBar),
                                        x,
                                        resolution ?? future.Resolution,
                                        future.Exchange.Hours,
                                        MarketHoursDatabase.FromDataFolder().GetDataTimeZone(future.Symbol.ID.Market, future.Symbol, future.Type),
                                        Resolution.Minute,
                                        future.IsExtendedMarketHours,
                                        future.IsCustomData(),
                                        DataNormalizationMode.Raw,
                                        LeanData.GetCommonTickTypeForCommonDataTypes(typeof(QuoteBar), future.Type))
                    );

            return new FutureHistory(HistoryProvider.GetHistory(requests, TimeZone).Memoize());
        }
예제 #4
0
        /// <summary>
        /// Get the last known price using the history provider.
        /// Useful for seeding securities with the correct price
        /// </summary>
        /// <param name="security"><see cref="Security"/> object for which to retrieve historical data</param>
        /// <returns>A single <see cref="BaseData"/> object with the last known price</returns>
        public BaseData GetLastKnownPrice(Security security)
        {
            if (security.Symbol.IsCanonical() || HistoryProvider == null)
            {
                return(null);
            }

            // For speed and memory usage, use Resolution.Minute as the minimum resolution
            var resolution = (Resolution)Math.Max((int)Resolution.Minute, (int)security.Resolution);

            var startTime = GetStartTimeAlgoTzForSecurity(security, 1, resolution);
            var endTime   = Time.RoundDown(resolution.ToTimeSpan());

            // request QuoteBar for Options and Futures
            var dataType = typeof(BaseData);

            if (security.Type == SecurityType.Option || security.Type == SecurityType.Future)
            {
                dataType = LeanData.GetDataType(resolution, TickType.Quote);
            }

            // Get the config with the largest resolution
            var subscriptionDataConfig = GetMatchingSubscription(security, dataType);

            // if subscription resolution is Tick, we also need to update the data type from Tick to TradeBar/QuoteBar
            if (subscriptionDataConfig != null && subscriptionDataConfig.Resolution == Resolution.Tick)
            {
                dataType = LeanData.GetDataType(resolution, subscriptionDataConfig.TickType);
                subscriptionDataConfig = new SubscriptionDataConfig(subscriptionDataConfig, dataType, resolution: resolution);
            }

            var request = new HistoryRequest(
                startTime.ConvertToUtc(_localTimeKeeper.TimeZone),
                endTime.ConvertToUtc(_localTimeKeeper.TimeZone),
                subscriptionDataConfig == null ? typeof(TradeBar) : subscriptionDataConfig.Type,
                security.Symbol,
                resolution,
                security.Exchange.Hours,
                MarketHoursDatabase.FromDataFolder().GetDataTimeZone(security.Symbol.ID.Market, security.Symbol, security.Symbol.SecurityType),
                resolution,
                security.IsExtendedMarketHours,
                security.IsCustomData(),
                security.DataNormalizationMode,
                subscriptionDataConfig == null ? LeanData.GetCommonTickTypeForCommonDataTypes(typeof(TradeBar), security.Type) : subscriptionDataConfig.TickType
                );

            var history = History(new List <HistoryRequest> {
                request
            }).ToList();

            if (history.Any() && history.First().Values.Any())
            {
                return(history.First().Values.First());
            }

            return(null);
        }
예제 #5
0
        /// <summary>
        /// Checks if the subscription is valid for the consolidator
        /// </summary>
        /// <param name="subscription">The subscription configuration</param>
        /// <param name="consolidator">The consolidator</param>
        /// <returns>true if the subscription is valid for the consolidator</returns>
        public static bool IsSubscriptionValidForConsolidator(SubscriptionDataConfig subscription, IDataConsolidator consolidator)
        {
            if (subscription.Type == typeof(Tick))
            {
                var tickType = LeanData.GetCommonTickTypeForCommonDataTypes(consolidator.OutputType, subscription.Symbol.SecurityType);
                return(subscription.TickType == tickType);
            }

            return(consolidator.InputType.IsAssignableFrom(subscription.Type));
        }
예제 #6
0
        /// <summary>
        /// Gets history requests required for warming up the greeks with the provided resolution
        /// </summary>
        /// <param name="security">Security to get history for</param>
        /// <param name="utcTime">UTC time of the request (end time)</param>
        /// <param name="resolution">Resolution of the security</param>
        /// <param name="barCount">Number of bars to lookback for the start date</param>
        /// <returns>Enumerable of history requests</returns>
        /// <exception cref="InvalidOperationException">The <see cref="SubscriptionDataConfigProvider"/> has not been set</exception>
        public IEnumerable <HistoryRequest> GetHistoryRequirements(
            Security security,
            DateTime utcTime,
            Resolution?resolution,
            int barCount)
        {
            if (SubscriptionDataConfigProvider == null)
            {
                throw new InvalidOperationException(
                          "BaseVolatilityModel.GetHistoryRequirements(): " +
                          "SubscriptionDataConfigProvider was not set."
                          );
            }

            var configurations = SubscriptionDataConfigProvider
                                 .GetSubscriptionDataConfigs(security.Symbol)
                                 .OrderBy(c => c.TickType)
                                 .ToList();
            var configuration = configurations.First();

            var bar = configuration.Type.GetBaseDataInstance();

            bar.Symbol = security.Symbol;

            var historyResolution = resolution ?? bar.SupportedResolutions().Max();

            var periodSpan = historyResolution.ToTimeSpan();

            // hour resolution does no have extended market hours data
            var extendedMarketHours = periodSpan != Time.OneHour && configurations.IsExtendedMarketHours();
            var localStartTime      = Time.GetStartTimeForTradeBars(
                security.Exchange.Hours,
                utcTime.ConvertFromUtc(security.Exchange.TimeZone),
                periodSpan,
                barCount,
                extendedMarketHours,
                configuration.DataTimeZone);
            var utcStartTime = localStartTime.ConvertToUtc(security.Exchange.TimeZone);

            return(new[]
            {
                new HistoryRequest(utcStartTime,
                                   utcTime,
                                   configuration.Type,
                                   configuration.Symbol,
                                   historyResolution,
                                   security.Exchange.Hours,
                                   configuration.DataTimeZone,
                                   historyResolution,
                                   extendedMarketHours,
                                   configurations.IsCustomData(),
                                   configurations.DataNormalizationMode(),
                                   LeanData.GetCommonTickTypeForCommonDataTypes(configuration.Type, security.Type))
            });
        }
예제 #7
0
        /// <summary>
        /// Add Market Data Required (Overloaded method for backwards compatibility).
        /// </summary>
        /// <param name="symbol">Symbol of the asset we're like</param>
        /// <param name="resolution">Resolution of Asset Required</param>
        /// <param name="timeZone">The time zone the subscription's data is time stamped in</param>
        /// <param name="exchangeTimeZone">Specifies the time zone of the exchange for the security this subscription is for. This
        /// is this output time zone, that is, the time zone that will be used on BaseData instances</param>
        /// <param name="isCustomData">True if this is custom user supplied data, false for normal QC data</param>
        /// <param name="fillDataForward">when there is no data pass the last tradebar forward</param>
        /// <param name="extendedMarketHours">Request premarket data as well when true </param>
        /// <returns>The newly created <see cref="SubscriptionDataConfig"/></returns>
        public SubscriptionDataConfig Add(Symbol symbol, Resolution resolution, DateTimeZone timeZone, DateTimeZone exchangeTimeZone, bool isCustomData = false, bool fillDataForward = true, bool extendedMarketHours = false)
        {
            //Set the type: market data only comes in two forms -- ticks(trade by trade) or tradebar(time summaries)
            var dataType = typeof(TradeBar);

            if (resolution == Resolution.Tick)
            {
                dataType = typeof(Tick);
            }
            var tickType = LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType);

            return(Add(dataType, tickType, symbol, resolution, timeZone, exchangeTimeZone, isCustomData, fillDataForward, extendedMarketHours));
        }
예제 #8
0
 /// <summary>
 /// Creates and adds a list of <see cref="SubscriptionDataConfig" /> for a given symbol and configuration.
 /// Can optionally pass in desired subscription data type to use.
 /// If the config already existed will return existing instance instead
 /// </summary>
 public SubscriptionDataConfig Add(
     Type dataType,
     Symbol symbol,
     Resolution resolution,
     bool fillForward            = true,
     bool extendedMarketHours    = false,
     bool isFilteredSubscription = true,
     bool isInternalFeed         = false,
     bool isCustomData           = false
     )
 {
     return(Add(symbol, resolution, fillForward, extendedMarketHours, isFilteredSubscription, isInternalFeed, isCustomData,
                new List <Tuple <Type, TickType> > {
         new Tuple <Type, TickType>(dataType, LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType))
     })
            .First());
 }
예제 #9
0
 /// <summary>
 /// Creates and adds a list of <see cref="SubscriptionDataConfig" /> for a given symbol and configuration.
 /// Can optionally pass in desired subscription data type to use.
 /// If the config already existed will return existing instance instead
 /// </summary>
 public SubscriptionDataConfig Add(
     Type dataType,
     Symbol symbol,
     Resolution?resolution       = null,
     bool fillForward            = true,
     bool extendedMarketHours    = false,
     bool isFilteredSubscription = true,
     bool isInternalFeed         = false,
     bool isCustomData           = false,
     DataNormalizationMode dataNormalizationMode = DataNormalizationMode.Adjusted,
     DataMappingMode dataMappingMode             = DataMappingMode.OpenInterest,
     uint contractDepthOffset = 0
     )
 {
     return(Add(symbol, resolution, fillForward, extendedMarketHours, isFilteredSubscription, isInternalFeed, isCustomData,
                new List <Tuple <Type, TickType> > {
         new Tuple <Type, TickType>(dataType, LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType))
     },
                dataNormalizationMode, dataMappingMode, contractDepthOffset)
            .First());
 }
예제 #10
0
 /// <summary>
 /// Creates a security and matching configuration. This applies the default leverage if
 /// leverage is less than or equal to zero.
 /// This method also add the new symbol mapping to the <see cref="SymbolCache"/>
 /// </summary>
 public static Security CreateSecurity(Type dataType,
                                       SecurityPortfolioManager securityPortfolioManager,
                                       SubscriptionManager subscriptionManager,
                                       SecurityExchangeHours exchangeHours,
                                       DateTimeZone dataTimeZone,
                                       SymbolProperties symbolProperties,
                                       ISecurityInitializer securityInitializer,
                                       Symbol symbol,
                                       Resolution resolution,
                                       bool fillDataForward,
                                       decimal leverage,
                                       bool extendedMarketHours,
                                       bool isInternalFeed,
                                       bool isCustomData,
                                       bool isLiveMode,
                                       bool addToSymbolCache       = true,
                                       bool isFilteredSubscription = true)
 {
     return(CreateSecurity(
                new List <Tuple <Type, TickType> >
     {
         new Tuple <Type, TickType>(dataType, LeanData.GetCommonTickTypeForCommonDataTypes(dataType, symbol.SecurityType))
     },
                securityPortfolioManager,
                subscriptionManager,
                exchangeHours,
                dataTimeZone,
                symbolProperties,
                securityInitializer,
                symbol,
                resolution,
                fillDataForward,
                leverage,
                extendedMarketHours,
                isInternalFeed,
                isCustomData,
                isLiveMode,
                addToSymbolCache,
                isFilteredSubscription));
 }
예제 #11
0
        /// <summary>
        /// Returns history requirements for the volatility model expressed in the form of history request
        /// </summary>
        /// <param name="security">The security of the request</param>
        /// <param name="utcTime">The date of the request</param>
        /// <returns>History request object list, or empty if no requirements</returns>
        public IEnumerable <HistoryRequest> GetHistoryRequirements(Security security, DateTime utcTime)
        {
            var barCount       = _window.Size + 1;
            var localStartTime = Time.GetStartTimeForTradeBars(security.Exchange.Hours, utcTime.ConvertFromUtc(security.Exchange.TimeZone), _periodSpan, barCount, security.IsExtendedMarketHours);
            var utcStartTime   = localStartTime.ConvertToUtc(security.Exchange.TimeZone);

            return(new[]
            {
                new HistoryRequest(utcStartTime,
                                   utcTime,
                                   typeof(TradeBar),
                                   security.Symbol,
                                   Resolution.Daily,
                                   security.Exchange.Hours,
                                   MarketHoursDatabase.FromDataFolder().GetDataTimeZone(security.Symbol.ID.Market, security.Symbol, security.Type),
                                   Resolution.Daily,
                                   security.IsExtendedMarketHours,
                                   security.IsCustomData(),
                                   security.DataNormalizationMode,
                                   LeanData.GetCommonTickTypeForCommonDataTypes(typeof(TradeBar), security.Type))
            });
        }
예제 #12
0
        public override IEnumerable <HistoryRequest> GetHistoryRequirements(Security security, DateTime utcTime)
        {
            var configuration = SubscriptionDataConfigProvider.GetSubscriptionDataConfigs(security.Symbol).First();

            return(new[]
            {
                new HistoryRequest(
                    utcTime,
                    utcTime,
                    typeof(TradeBar),
                    configuration.Symbol,
                    configuration.Resolution,
                    security.Exchange.Hours,
                    configuration.DataTimeZone,
                    configuration.Resolution,
                    configuration.ExtendedMarketHours,
                    configuration.IsCustomData,
                    configuration.DataNormalizationMode,
                    LeanData.GetCommonTickTypeForCommonDataTypes(typeof(TradeBar), security.Type)
                    )
            });
        }
예제 #13
0
 public BaseData GetLastKnownPrice(Security security)
 {
     return(GetLastKnownPrices(security.Symbol)
            // since we are returning a single data point let's respect order
            .OrderByDescending(data => GetTickTypeOrder(data.Symbol.SecurityType, LeanData.GetCommonTickTypeForCommonDataTypes(data.GetType(), data.Symbol.SecurityType)))
            .LastOrDefault());
 }
예제 #14
0
 public void LeanData_GetCommonTickTypeForCommonDataTypes_ReturnsCorrectDataForTickResolution()
 {
     Assert.AreEqual(LeanData.GetCommonTickTypeForCommonDataTypes(typeof(Tick), SecurityType.Cfd), TickType.Quote);
     Assert.AreEqual(LeanData.GetCommonTickTypeForCommonDataTypes(typeof(Tick), SecurityType.Forex), TickType.Quote);
 }
예제 #15
0
        /// <summary>
        /// Constructor for Data Subscriptions
        /// </summary>
        /// <param name="objectType">Type of the data objects.</param>
        /// <param name="symbol">Symbol of the asset we're requesting</param>
        /// <param name="resolution">Resolution of the asset we're requesting</param>
        /// <param name="dataTimeZone">The time zone the raw data is time stamped in</param>
        /// <param name="exchangeTimeZone">Specifies the time zone of the exchange for the security this subscription is for. This
        /// is this output time zone, that is, the time zone that will be used on BaseData instances</param>
        /// <param name="fillForward">Fill in gaps with historical data</param>
        /// <param name="extendedHours">Equities only - send in data from 4am - 8pm</param>
        /// <param name="isInternalFeed">Set to true if this subscription is added for the sole purpose of providing currency conversion rates,
        /// setting this flag to true will prevent the data from being sent into the algorithm's OnData methods</param>
        /// <param name="isCustom">True if this is user supplied custom data, false for normal QC data</param>
        /// <param name="tickType">Specifies if trade or quote data is subscribed</param>
        /// <param name="isFilteredSubscription">True if this subscription should have filters applied to it (market hours/user filters from security), false otherwise</param>
        /// <param name="dataNormalizationMode">Specifies normalization mode used for this subscription</param>
        public SubscriptionDataConfig(Type objectType,
                                      Symbol symbol,
                                      Resolution resolution,
                                      DateTimeZone dataTimeZone,
                                      DateTimeZone exchangeTimeZone,
                                      bool fillForward,
                                      bool extendedHours,
                                      bool isInternalFeed,
                                      bool isCustom               = false,
                                      TickType?tickType           = null,
                                      bool isFilteredSubscription = true,
                                      DataNormalizationMode dataNormalizationMode = DataNormalizationMode.Adjusted)
        {
            if (objectType == null)
            {
                throw new ArgumentNullException("objectType");
            }
            if (symbol == null)
            {
                throw new ArgumentNullException("symbol");
            }
            if (dataTimeZone == null)
            {
                throw new ArgumentNullException("dataTimeZone");
            }
            if (exchangeTimeZone == null)
            {
                throw new ArgumentNullException("exchangeTimeZone");
            }

            Type                   = objectType;
            SecurityType           = symbol.ID.SecurityType;
            Resolution             = resolution;
            _sid                   = symbol.ID;
            Symbol                 = symbol;
            FillDataForward        = fillForward;
            ExtendedMarketHours    = extendedHours;
            PriceScaleFactor       = 1;
            IsInternalFeed         = isInternalFeed;
            IsCustomData           = isCustom;
            Market                 = symbol.ID.Market;
            DataTimeZone           = dataTimeZone;
            ExchangeTimeZone       = exchangeTimeZone;
            IsFilteredSubscription = isFilteredSubscription;
            Consolidators          = new HashSet <IDataConsolidator>();
            DataNormalizationMode  = dataNormalizationMode;

            TickType = tickType ?? LeanData.GetCommonTickTypeForCommonDataTypes(objectType, SecurityType);

            switch (resolution)
            {
            case Resolution.Tick:
                //Ticks are individual sales and fillforward doesn't apply.
                Increment       = TimeSpan.FromSeconds(0);
                FillDataForward = false;
                break;

            case Resolution.Second:
                Increment = TimeSpan.FromSeconds(1);
                break;

            case Resolution.Minute:
                Increment = TimeSpan.FromMinutes(1);
                break;

            case Resolution.Hour:
                Increment = TimeSpan.FromHours(1);
                break;

            case Resolution.Daily:
                Increment = TimeSpan.FromDays(1);
                break;

            default:
                throw new InvalidEnumArgumentException("Unexpected Resolution: " + resolution);
            }
        }
예제 #16
0
        /// <summary>
        /// Get the last known price using the history provider.
        /// Useful for seeding securities with the correct price
        /// </summary>
        /// <param name="security"><see cref="Security"/> object for which to retrieve historical data</param>
        /// <returns>A single <see cref="BaseData"/> object with the last known price</returns>
        public BaseData GetLastKnownPrice(Security security)
        {
            if (security.Symbol.IsCanonical() || HistoryProvider == null)
            {
                return(null);
            }

            var configs = SubscriptionManager.SubscriptionDataConfigService
                          .GetSubscriptionDataConfigs(security.Symbol);

            var dataTimeZone = MarketHoursDatabase
                               .GetDataTimeZone(security.Symbol.ID.Market, security.Symbol, security.Symbol.SecurityType);

            // For speed and memory usage, use Resolution.Minute as the minimum resolution
            var resolution            = (Resolution)Math.Max((int)Resolution.Minute, (int)configs.GetHighestResolution());
            var isExtendedMarketHours = configs.IsExtendedMarketHours();

            // request QuoteBar for Options and Futures
            var dataType = typeof(BaseData);

            if (security.Type == SecurityType.Option || security.Type == SecurityType.Future)
            {
                dataType = LeanData.GetDataType(resolution, TickType.Quote);
            }

            // Get the config with the largest resolution
            var subscriptionDataConfig = GetMatchingSubscription(security.Symbol, dataType);

            TickType tickType;

            if (subscriptionDataConfig == null)
            {
                dataType = typeof(TradeBar);
                tickType = LeanData.GetCommonTickTypeForCommonDataTypes(dataType, security.Type);
            }
            else
            {
                // if subscription resolution is Tick, we also need to update the data type from Tick to TradeBar/QuoteBar
                if (subscriptionDataConfig.Resolution == Resolution.Tick)
                {
                    dataType = LeanData.GetDataType(resolution, subscriptionDataConfig.TickType);
                    subscriptionDataConfig = new SubscriptionDataConfig(subscriptionDataConfig, dataType, resolution: resolution);
                }

                dataType = subscriptionDataConfig.Type;
                tickType = subscriptionDataConfig.TickType;
            }

            Func <int, BaseData> getLastKnownPriceForPeriods = backwardsPeriods =>
            {
                var startTimeUtc = _historyRequestFactory
                                   .GetStartTimeAlgoTz(security.Symbol, backwardsPeriods, resolution, security.Exchange.Hours, dataTimeZone)
                                   .ConvertToUtc(_localTimeKeeper.TimeZone);

                var request = new HistoryRequest(
                    startTimeUtc,
                    UtcTime,
                    dataType,
                    security.Symbol,
                    resolution,
                    security.Exchange.Hours,
                    dataTimeZone,
                    resolution,
                    isExtendedMarketHours,
                    configs.IsCustomData(),
                    configs.DataNormalizationMode(),
                    tickType
                    );

                BaseData result = null;
                History(new List <HistoryRequest> {
                    request
                })
                .PushThrough(bar =>
                {
                    if (!bar.IsFillForward)
                    {
                        result = bar;
                    }
                });

                return(result);
            };

            var lastKnownPrice = getLastKnownPriceForPeriods(1);

            if (lastKnownPrice != null)
            {
                return(lastKnownPrice);
            }

            // If the first attempt to get the last know price returns null, it maybe the case of an illiquid security.
            // We increase the look-back period for this case accordingly to the resolution to cover 3 trading days
            var periods =
                resolution == Resolution.Daily ? 3 :
                resolution == Resolution.Hour ? 24 : 1440;

            return(getLastKnownPriceForPeriods(periods));
        }