public void EmitsDelistingEventsBasedOnCurrentTime()
        {
            var config = new SubscriptionDataConfig(typeof(TradeBar),
                                                    Symbols.SPY_C_192_Feb19_2016,
                                                    Resolution.Daily,
                                                    TimeZones.NewYork,
                                                    TimeZones.NewYork,
                                                    true,
                                                    true,
                                                    false);
            var delistingDate = config.Symbol.GetDelistingDate();
            var time          = delistingDate.AddDays(-10);
            var cache         = new SecurityCache();

            cache.AddData(new Tick(DateTime.UtcNow, config.Symbol, 20, 10));
            var timeProvider = new ManualTimeProvider(time);

            IEnumerator <BaseData> enumerator;

            Assert.IsTrue(LiveAuxiliaryDataEnumerator.TryCreate(config, timeProvider, null, cache, TestGlobals.MapFileProvider, TestGlobals.FactorFileProvider, config.Symbol.ID.Date, out enumerator));

            Assert.IsTrue(enumerator.MoveNext());
            Assert.IsNull(enumerator.Current);

            // advance until delisting date, take into account 5 hour offset of NY + TradableDateOffset
            timeProvider.Advance(TimeSpan.FromDays(10));
            timeProvider.Advance(TimeSpan.FromHours(5));
            timeProvider.Advance(Time.LiveAuxiliaryDataOffset);

            Assert.IsTrue(enumerator.MoveNext());
            Assert.AreEqual(DelistingType.Warning, (enumerator.Current as Delisting).Type);
            Assert.AreEqual(config.Symbol, (enumerator.Current as Delisting).Symbol);
            Assert.AreEqual(delistingDate, (enumerator.Current as Delisting).Time);
            Assert.AreEqual(15, (enumerator.Current as Delisting).Price);

            Assert.IsTrue(enumerator.MoveNext());
            Assert.IsNull(enumerator.Current);

            // when the day ends the delisted event will pass through, respecting the offset
            timeProvider.Advance(TimeSpan.FromDays(1));

            cache.AddData(new Tick(DateTime.UtcNow, config.Symbol, 40, 20));

            Assert.IsTrue(enumerator.MoveNext());
            Assert.AreEqual(DelistingType.Delisted, (enumerator.Current as Delisting).Type);
            Assert.AreEqual(config.Symbol, (enumerator.Current as Delisting).Symbol);
            Assert.AreEqual(delistingDate.AddDays(1), (enumerator.Current as Delisting).Time);
            Assert.AreEqual(30, (enumerator.Current as Delisting).Price);

            Assert.IsTrue(enumerator.MoveNext());
            Assert.IsNull(enumerator.Current);
        }
Exemple #2
0
        /// <summary>
        /// Creates a new subscription for the specified security
        /// </summary>
        /// <param name="request">The subscription request</param>
        /// <returns>A new subscription instance of the specified security</returns>
        protected Subscription CreateDataSubscription(SubscriptionRequest request)
        {
            Subscription subscription = null;

            try
            {
                var localEndTime           = request.EndTimeUtc.ConvertFromUtc(request.Security.Exchange.TimeZone);
                var timeZoneOffsetProvider = new TimeZoneOffsetProvider(request.Configuration.ExchangeTimeZone, request.StartTimeUtc, request.EndTimeUtc);

                IEnumerator <BaseData> enumerator;
                if (!_channelProvider.ShouldStreamSubscription(request.Configuration))
                {
                    if (!Quandl.IsAuthCodeSet)
                    {
                        // we're not using the SubscriptionDataReader, so be sure to set the auth token here
                        Quandl.SetAuthCode(Config.Get("quandl-auth-token"));
                    }

                    if (!Tiingo.IsAuthCodeSet)
                    {
                        // we're not using the SubscriptionDataReader, so be sure to set the auth token here
                        Tiingo.SetAuthCode(Config.Get("tiingo-auth-token"));
                    }

                    var factory         = new LiveCustomDataSubscriptionEnumeratorFactory(_timeProvider);
                    var enumeratorStack = factory.CreateEnumerator(request, _dataProvider);

                    _customExchange.AddEnumerator(request.Configuration.Symbol, enumeratorStack);

                    var enqueable = new EnqueueableEnumerator <BaseData>();
                    _customExchange.SetDataHandler(request.Configuration.Symbol, data =>
                    {
                        enqueable.Enqueue(data);

                        subscription.OnNewDataAvailable();
                    });
                    enumerator = enqueable;
                }
                else
                {
                    var auxEnumerators = new List <IEnumerator <BaseData> >();

                    if (LiveAuxiliaryDataEnumerator.TryCreate(request.Configuration, _timeProvider, _dataQueueHandler,
                                                              request.Security.Cache, _mapFileProvider, _factorFileProvider, request.StartTimeLocal, out var auxDataEnumator))
                    {
                        auxEnumerators.Add(auxDataEnumator);
                    }

                    EventHandler handler = (_, _) => subscription?.OnNewDataAvailable();
                    enumerator = Subscribe(request.Configuration, handler);

                    if (request.Configuration.EmitSplitsAndDividends())
                    {
                        auxEnumerators.Add(Subscribe(new SubscriptionDataConfig(request.Configuration, typeof(Dividend)), handler));
                        auxEnumerators.Add(Subscribe(new SubscriptionDataConfig(request.Configuration, typeof(Split)), handler));
                    }

                    if (auxEnumerators.Count > 0)
                    {
                        enumerator = new LiveAuxiliaryDataSynchronizingEnumerator(_timeProvider, request.Configuration.ExchangeTimeZone, enumerator, auxEnumerators);
                    }
                }

                if (request.Configuration.FillDataForward)
                {
                    var fillForwardResolution = _subscriptions.UpdateAndGetFillForwardResolution(request.Configuration);

                    enumerator = new LiveFillForwardEnumerator(_frontierTimeProvider, enumerator, request.Security.Exchange, fillForwardResolution, request.Configuration.ExtendedMarketHours, localEndTime, request.Configuration.Increment, request.Configuration.DataTimeZone);
                }

                // define market hours and user filters to incoming data
                if (request.Configuration.IsFilteredSubscription)
                {
                    enumerator = new SubscriptionFilterEnumerator(enumerator, request.Security, localEndTime, request.Configuration.ExtendedMarketHours, true, request.ExchangeHours);
                }

                // finally, make our subscriptions aware of the frontier of the data feed, prevents future data from spewing into the feed
                enumerator = new FrontierAwareEnumerator(enumerator, _frontierTimeProvider, timeZoneOffsetProvider);

                var subscriptionDataEnumerator = new SubscriptionDataEnumerator(request.Configuration, request.Security.Exchange.Hours, timeZoneOffsetProvider, enumerator, request.IsUniverseSubscription);
                subscription = new Subscription(request, subscriptionDataEnumerator, timeZoneOffsetProvider);
            }
            catch (Exception err)
            {
                Log.Error(err);
            }

            return(subscription);
        }
        public void EmitsMappingEventsBasedOnCurrentMapFileAndTime(DataMappingMode dataMappingMode, string mappingDate, bool delayed)
        {
            var config = new SubscriptionDataConfig(typeof(TradeBar),
                                                    Symbols.ES_Future_Chain,
                                                    Resolution.Daily,
                                                    TimeZones.NewYork,
                                                    TimeZones.NewYork,
                                                    true,
                                                    true,
                                                    false,
                                                    dataMappingMode: dataMappingMode);
            var symbolMaps = new List <SubscriptionDataConfig.NewSymbolEventArgs>();

            config.NewSymbol += (sender, args) => symbolMaps.Add(args);
            var time  = new DateTime(2013, 05, 28);
            var cache = new SecurityCache();

            cache.AddData(new Tick(time, config.Symbol, 20, 10));
            var timeProvider = new ManualTimeProvider(time);

            var futureTicker1 = "es vhle2yxr5blt";

            TestMapFileResolver.MapFile = new MapFile(Futures.Indices.SP500EMini, new []
            {
                new MapFileRow(Time.BeginningOfTime, Futures.Indices.SP500EMini, Exchange.CME),
                new MapFileRow(new DateTime(2013, 06, 01), futureTicker1, Exchange.CME, DataMappingMode.FirstDayMonth),
                new MapFileRow(new DateTime(2013, 06, 15), futureTicker1, Exchange.CME, DataMappingMode.OpenInterest),
                new MapFileRow(new DateTime(2013, 06, 22), futureTicker1, Exchange.CME, DataMappingMode.LastTradingDay),
            });

            IEnumerator <BaseData> enumerator;

            Assert.IsTrue(LiveAuxiliaryDataEnumerator.TryCreate(config, timeProvider, null, cache, new TestMapFileProvider(), TestGlobals.FactorFileProvider, time, out enumerator));

            // get's mapped right away!
            Assert.AreEqual(futureTicker1.ToUpper(), config.MappedSymbol);

            Assert.AreEqual(1, symbolMaps.Count);
            Assert.AreEqual(Symbols.ES_Future_Chain, symbolMaps[0].Old);
            Assert.AreEqual(Futures.Indices.SP500EMini, symbolMaps[0].Old.ID.Symbol);
            Assert.AreEqual(Symbols.ES_Future_Chain, symbolMaps[0].New);
            Assert.AreEqual(futureTicker1.ToUpper(), symbolMaps[0].New.Underlying.ID.ToString());

            Assert.IsTrue(enumerator.MoveNext());
            Assert.IsNull(enumerator.Current);

            var expectedMappingDate = DateTime.ParseExact(mappingDate, DateFormat.EightCharacter, CultureInfo.InvariantCulture);

            if (delayed)
            {
                // we advance to the mapping date, without any new mapFile!
                timeProvider.Advance(expectedMappingDate.ConvertToUtc(config.ExchangeTimeZone) - timeProvider.GetUtcNow() + Time.LiveAuxiliaryDataOffset);
            }
            else
            {
                // just advance a day to show nothing happens until mapping time
                timeProvider.Advance(TimeSpan.FromDays(1));
            }

            Assert.IsTrue(enumerator.MoveNext());
            Assert.IsNull(enumerator.Current);

            var futureTicker2 = "es vk2zrh843z7l";

            TestMapFileResolver.MapFile = new MapFile(Futures.Indices.SP500EMini, TestMapFileResolver.MapFile.Concat(
                                                          new []
            {
                new MapFileRow(new DateTime(2013, 09, 01), futureTicker2, Exchange.CME, DataMappingMode.FirstDayMonth),
                new MapFileRow(new DateTime(2013, 09, 14), futureTicker2, Exchange.CME, DataMappingMode.OpenInterest),
                new MapFileRow(new DateTime(2013, 09, 21), futureTicker2, Exchange.CME, DataMappingMode.LastTradingDay),
            }));

            Assert.IsTrue(enumerator.MoveNext());
            Assert.IsNull(enumerator.Current);

            if (delayed)
            {
                // we got a new mapFile! advance the date and expect mapping to have happened
                timeProvider.Advance(TimeSpan.FromDays(1));
            }
            else
            {
                // we advance to the mapping date
                timeProvider.Advance(expectedMappingDate.ConvertToUtc(config.ExchangeTimeZone) - timeProvider.GetUtcNow() + Time.LiveAuxiliaryDataOffset);
            }

            Assert.IsTrue(enumerator.MoveNext());
            Assert.IsNotNull(enumerator.Current);

            Assert.AreEqual(2, symbolMaps.Count);
            Assert.AreEqual(Symbols.ES_Future_Chain, symbolMaps[1].Old);
            Assert.AreEqual(futureTicker1.ToUpper(), symbolMaps[1].Old.Underlying.ID.ToString());
            Assert.AreEqual(Symbols.ES_Future_Chain, symbolMaps[1].New);
            Assert.AreEqual(futureTicker2.ToUpper(), symbolMaps[1].New.Underlying.ID.ToString());

            Assert.AreEqual(futureTicker2.ToUpper(), config.MappedSymbol);

            Assert.AreEqual(futureTicker2.ToUpper(), (enumerator.Current as SymbolChangedEvent).NewSymbol);
            Assert.AreEqual(futureTicker1.ToUpper(), (enumerator.Current as SymbolChangedEvent).OldSymbol);
            Assert.AreEqual(config.Symbol, (enumerator.Current as SymbolChangedEvent).Symbol);
            Assert.AreEqual(timeProvider.GetUtcNow().Date, (enumerator.Current as SymbolChangedEvent).Time);

            Assert.IsTrue(enumerator.MoveNext());
            Assert.IsNull(enumerator.Current);
        }
Exemple #4
0
        /// <summary>
        /// Creates a new subscription for the specified security
        /// </summary>
        /// <param name="request">The subscription request</param>
        /// <returns>A new subscription instance of the specified security</returns>
        private Subscription CreateDataSubscription(SubscriptionRequest request)
        {
            Subscription subscription = null;

            try
            {
                var localEndTime           = request.EndTimeUtc.ConvertFromUtc(request.Security.Exchange.TimeZone);
                var timeZoneOffsetProvider = new TimeZoneOffsetProvider(request.Configuration.ExchangeTimeZone, request.StartTimeUtc, request.EndTimeUtc);

                IEnumerator <BaseData> enumerator = null;
                // during warmup we might get requested to add some asset which has already expired in which case the live enumerator will be empty
                if (!IsExpired(request.Configuration))
                {
                    if (!_channelProvider.ShouldStreamSubscription(request.Configuration))
                    {
                        if (!Tiingo.IsAuthCodeSet)
                        {
                            // we're not using the SubscriptionDataReader, so be sure to set the auth token here
                            Tiingo.SetAuthCode(Config.Get("tiingo-auth-token"));
                        }

                        var factory         = new LiveCustomDataSubscriptionEnumeratorFactory(_timeProvider);
                        var enumeratorStack = factory.CreateEnumerator(request, _dataProvider);

                        var enqueable = new EnqueueableEnumerator <BaseData>();
                        _customExchange.AddEnumerator(request.Configuration.Symbol, enumeratorStack, handleData: data =>
                        {
                            enqueable.Enqueue(data);

                            subscription?.OnNewDataAvailable();
                        });

                        enumerator = enqueable;
                    }
                    else
                    {
                        var auxEnumerators = new List <IEnumerator <BaseData> >();

                        if (LiveAuxiliaryDataEnumerator.TryCreate(request.Configuration, _timeProvider, _dataQueueHandler,
                                                                  request.Security.Cache, _mapFileProvider, _factorFileProvider, request.StartTimeLocal, out var auxDataEnumator))
                        {
                            auxEnumerators.Add(auxDataEnumator);
                        }

                        EventHandler handler = (_, _) => subscription?.OnNewDataAvailable();
                        enumerator = Subscribe(request.Configuration, handler);

                        if (request.Configuration.EmitSplitsAndDividends())
                        {
                            auxEnumerators.Add(Subscribe(new SubscriptionDataConfig(request.Configuration, typeof(Dividend)), handler));
                            auxEnumerators.Add(Subscribe(new SubscriptionDataConfig(request.Configuration, typeof(Split)), handler));
                        }

                        if (auxEnumerators.Count > 0)
                        {
                            enumerator = new LiveAuxiliaryDataSynchronizingEnumerator(_timeProvider, request.Configuration.ExchangeTimeZone, enumerator, auxEnumerators);
                        }
                    }

                    // scale prices before 'SubscriptionFilterEnumerator' since it updates securities realtime price
                    // and before fill forwarding so we don't happen to apply twice the factor
                    if (request.Configuration.PricesShouldBeScaled(liveMode: true))
                    {
                        enumerator = new PriceScaleFactorEnumerator(
                            enumerator,
                            request.Configuration,
                            _factorFileProvider,
                            liveMode: true);
                    }

                    if (request.Configuration.FillDataForward)
                    {
                        var fillForwardResolution = _subscriptions.UpdateAndGetFillForwardResolution(request.Configuration);

                        enumerator = new LiveFillForwardEnumerator(_frontierTimeProvider, enumerator, request.Security.Exchange, fillForwardResolution, request.Configuration.ExtendedMarketHours, localEndTime, request.Configuration.Increment, request.Configuration.DataTimeZone);
                    }

                    // make our subscriptions aware of the frontier of the data feed, prevents future data from spewing into the feed
                    enumerator = new FrontierAwareEnumerator(enumerator, _frontierTimeProvider, timeZoneOffsetProvider);

                    // define market hours and user filters to incoming data after the frontier enumerator so during warmup we avoid any realtime data making it's way into the securities
                    if (request.Configuration.IsFilteredSubscription)
                    {
                        enumerator = new SubscriptionFilterEnumerator(enumerator, request.Security, localEndTime, request.Configuration.ExtendedMarketHours, true, request.ExchangeHours);
                    }
                }
                else
                {
                    enumerator = Enumerable.Empty <BaseData>().GetEnumerator();
                }

                enumerator = GetWarmupEnumerator(request, enumerator);

                var subscriptionDataEnumerator = new SubscriptionDataEnumerator(request.Configuration, request.Security.Exchange.Hours, timeZoneOffsetProvider, enumerator, request.IsUniverseSubscription);
                subscription = new Subscription(request, subscriptionDataEnumerator, timeZoneOffsetProvider);
            }
            catch (Exception err)
            {
                Log.Error(err);
            }

            return(subscription);
        }