Пример #1
0
        /// <summary>
        /// Stream IQFeed TickMessages from disk to Lean Tick
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="request"></param>
        /// <param name="tickFunc"></param>
        /// <param name="delete"></param>
        /// <returns>Converted Tick</returns>
        private IEnumerable <BaseData> GetDataFromTickMessages(string filename, HistoryRequest request, Func <DateTime, Symbol, TickMessage, Tick> tickFunc, bool delete)
        {
            var dataTimeZone = _marketHoursDatabase.GetDataTimeZone(request.Symbol.ID.Market, request.Symbol, request.Symbol.SecurityType);

            // We need to discard ticks which are not impacting the price, i.e those having BasisForLast = O
            // To get a better understanding how IQFeed is resampling ticks, have a look to this algorithm:
            // https://github.com/mathpaquette/IQFeed.CSharpApiClient/blob/1b33250e057dfd6cd77e5ee35fa16aebfc8fbe79/src/IQFeed.CSharpApiClient.Extensions/Lookup/Historical/Resample/TickMessageExtensions.cs#L41
            foreach (var tick in TickMessage.ParseFromFile(filename).Where(t => t.BasisForLast != 'O'))
            {
                var timestamp = tick.Timestamp.ConvertTo(TimeZones.NewYork, dataTimeZone);
                yield return(tickFunc(timestamp, request.Symbol, tick));
            }

            if (delete)
            {
                File.Delete(filename);
            }
        }
Пример #2
0
        /// <summary>
        /// Stream IQFeed TickMessages from disk to Lean Tick
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="request"></param>
        /// <param name="isEquity"></param>
        /// <returns>Converted Tick</returns>
        private IEnumerable <BaseData> GetDataFromTickMessages(string filename, HistoryRequest request)
        {
            var dataTimeZone = _marketHoursDatabase.GetDataTimeZone(request.Symbol.ID.Market, request.Symbol, request.Symbol.SecurityType);

            // We need to discard ticks which are not impacting the price, i.e those having BasisForLast = O
            // To get a better understanding how IQFeed is resampling ticks, have a look to this algorithm:
            // https://github.com/mathpaquette/IQFeed.CSharpApiClient/blob/1b33250e057dfd6cd77e5ee35fa16aebfc8fbe79/src/IQFeed.CSharpApiClient.Extensions/Lookup/Historical/Resample/TickMessageExtensions.cs#L41
            foreach (var tick in TickMessage.ParseFromFile(filename).Where(t => t.BasisForLast != 'O'))
            {
                var timestamp = tick.Timestamp.ConvertTo(TimeZones.NewYork, dataTimeZone);

                // trade
                yield return(new Tick(
                                 timestamp,
                                 request.Symbol,
                                 tick.TradeConditions,
                                 tick.TradeMarketCenter.ToStringInvariant(),
                                 tick.LastSize,
                                 (decimal)tick.Last
                                 ));

                // quote
                yield return(new Tick(
                                 timestamp,
                                 request.Symbol,
                                 tick.TradeConditions,
                                 tick.TradeMarketCenter.ToStringInvariant(),
                                 0, // not provided by IQFeed on history
                                 (decimal)tick.Bid,
                                 0, // not provided by IQFeed on history
                                 (decimal)tick.Ask
                                 ));
            }

            File.Delete(filename);
        }
Пример #3
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));
        }