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(LiveDelistingEventProviderEnumerator.TryCreate(config, timeProvider, null, cache, new LocalDiskMapFileProvider(), out enumerator));

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

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

            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.IsFalse(enumerator.MoveNext());
            Assert.IsNull(enumerator.Current);

            // when the day ends the delisted event will pass through
            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.IsFalse(enumerator.MoveNext());
            Assert.IsNull(enumerator.Current);
        }
Exemplo n.º 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.Security.Exchange.TimeZone, 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
                {
                    EventHandler handler = (sender, args) => subscription?.OnNewDataAvailable();
                    enumerator = _dataQueueHandler.Subscribe(request.Configuration, handler);

                    var securityType   = request.Configuration.SecurityType;
                    var auxEnumerators = new List <IEnumerator <BaseData> >();

                    if (securityType == SecurityType.Equity)
                    {
                        auxEnumerators.Add(_dataQueueHandler.Subscribe(new SubscriptionDataConfig(request.Configuration, typeof(Dividend)), handler));
                        auxEnumerators.Add(_dataQueueHandler.Subscribe(new SubscriptionDataConfig(request.Configuration, typeof(Split)), handler));
                    }

                    IEnumerator <BaseData> delistingEnumerator;
                    if (LiveDelistingEventProviderEnumerator.TryCreate(request.Configuration, _timeProvider, _dataQueueHandler, request.Security.Cache, _mapFileProvider, out delistingEnumerator))
                    {
                        auxEnumerators.Add(delistingEnumerator);
                    }

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

                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);
                subscription = new Subscription(request, subscriptionDataEnumerator, timeZoneOffsetProvider);
            }
            catch (Exception err)
            {
                Log.Error(err);
            }

            return(subscription);
        }