예제 #1
0
        private IEnumerable <Slice> GetSlices(Symbol symbol, int initialVolume)
        {
            var subscriptionDataConfig = new SubscriptionDataConfig(typeof(ZipEntryName), symbol, Resolution.Second, TimeZones.Utc, TimeZones.Utc, true, true, false);
            var security = new Security(SecurityExchangeHours.AlwaysOpen(TimeZones.Utc), subscriptionDataConfig, new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency));
            var refTime  = DateTime.UtcNow;

            return(Enumerable
                   .Range(0, 10)
                   .Select(i =>
            {
                var time = refTime.AddSeconds(i);
                var bid = new Bar(100, 100, 100, 100);
                var ask = new Bar(110, 110, 110, 110);
                var volume = (i + 1) * initialVolume;

                return TimeSlice.Create(
                    time,
                    TimeZones.Utc,
                    new CashBook(),
                    new List <DataFeedPacket>
                {
                    new DataFeedPacket(security, subscriptionDataConfig, new List <BaseData>
                    {
                        new QuoteBar(time, symbol, bid, i * 10, ask, (i + 1) * 11),
                        new TradeBar(time, symbol, 100, 100, 110, 106, volume)
                    }),
                },
                    new SecurityChanges(Enumerable.Empty <Security>(), Enumerable.Empty <Security>()),
                    new Dictionary <Universe, BaseDataCollection>())
                .Slice;
            }));
        }
예제 #2
0
        /// <summary>
        /// Gets the history for the requested securities
        /// </summary>
        /// <param name="requests">The historical data requests</param>
        /// <param name="sliceTimeZone">The time zone used when time stamping the slice instances</param>
        /// <returns>An enumerable of the slices of data covering the span specified in each request</returns>
        public IEnumerable <Slice> GetHistory(IEnumerable <HistoryRequest> requests, DateTimeZone sliceTimeZone)
        {
            var securitiesByDateTime = GetSecuritiesByDateTime(requests);
            var count = securitiesByDateTime.Count;
            var i     = 0;

            foreach (var kvp in securitiesByDateTime)
            {
                var utcDateTime = kvp.Key;
                var securities  = kvp.Value;
                var last        = Convert.ToDecimal(100 + 10 * Math.Sin(Math.PI * (360 - count + i) / 180.0));
                var high        = last * 1.005m;
                var low         = last / 1.005m;

                var packets = new List <DataFeedPacket>();

                foreach (var security in securities)
                {
                    var configuration = security.Subscriptions.FirstOrDefault(x => x.Resolution == security.Resolution);
                    var period        = security.Resolution.ToTimeSpan();
                    var time          = (utcDateTime - period).ConvertFromUtc(configuration.DataTimeZone);
                    var data          = new TradeBar(time, security.Symbol, last, high, last, last, 1000, period);
                    security.SetMarketPrice(data);
                    packets.Add(new DataFeedPacket(security, configuration, new List <BaseData> {
                        data
                    }));
                }

                i++;
                yield return(TimeSlice.Create(utcDateTime, sliceTimeZone, _cashBook, packets, _securityChanges).Slice);
            }
        }
예제 #3
0
        public void TimeSliceCreateDoesNotThrowNullReferanceWhenUnderlyingSecurityLastDataIsNull()
        {
            var optionSymbol           = Symbol.Create("SVXY", SecurityType.Option, Market.USA);
            var underlyingSecurity     = new Equity(optionSymbol.Underlying, SecurityExchangeHours.AlwaysOpen(DateTimeZone.Utc), new Cash("USD", 0, 1), SymbolProperties.GetDefault("USD"));
            var subscriptionDataConfig = new SubscriptionDataConfig(
                typeof(DailyFx), optionSymbol, Resolution.Daily, TimeZones.Utc, TimeZones.Utc, true, true, false, isCustom: true);

            var optionSecurity = new Option(optionSymbol,
                                            SecurityExchangeHours.AlwaysOpen(TimeZones.Utc),
                                            new Cash(CashBook.AccountCurrency, 0, 1m),
                                            new OptionSymbolProperties(SymbolProperties.GetDefault("USD")))
            {
                Underlying = underlyingSecurity
            };

            var refTime   = DateTime.UtcNow;
            var timeSlice = TimeSlice.Create(refTime, TimeZones.Utc, new CashBook(),
                                             new List <DataFeedPacket>
            {
                new DataFeedPacket(optionSecurity, subscriptionDataConfig, new List <BaseData>
                {
                    new QuoteBar {
                        Symbol = optionSymbol, Time = refTime, Value = 1, Ask = new Bar(1, 1, 1, 1), Bid = new Bar(1, 1, 1, 1)
                    }
                })
            },
                                             new SecurityChanges(Enumerable.Empty <Security>(), Enumerable.Empty <Security>()),
                                             new Dictionary <Universe, BaseDataCollection>());

            Assert.AreEqual(timeSlice.SecurityChanges.Count, 0);
        }
예제 #4
0
        public void ChangeState(T nextState)
        {
            if (Equals(nextState, CurrentState))
            {
                return;
            }
            HashSet <OnExit> exitCallbacks;

            if (OnStateExit.TryGetValue(CurrentState, out exitCallbacks))
            {
                foreach (var callback in exitCallbacks)
                {
                    callback(nextState);
                }
            }
            PreviousState = CurrentState;
            CurrentState  = nextState;
            HashSet <OnEnter> enterCallbacks;

            if (OnStateEnter.TryGetValue(CurrentState, out enterCallbacks))
            {
                foreach (var callback in enterCallbacks)
                {
                    callback(PreviousState);
                }
            }
            StateEnterTime = TimeSlice.Create();
            StateChanged.Publish(PreviousState, CurrentState);
        }
예제 #5
0
        public void HandlesMultipleCustomDataOfSameTypeWithDifferentSymbols()
        {
            var symbol1 = Symbol.Create("SCF/CBOE_VX1_EW", SecurityType.Base, Market.USA);
            var symbol2 = Symbol.Create("SCF/CBOE_VX2_EW", SecurityType.Base, Market.USA);

            var subscriptionDataConfig1 = new SubscriptionDataConfig(
                typeof(QuandlFuture), symbol1, Resolution.Daily, TimeZones.Utc, TimeZones.Utc, true, true, false, isCustom: true);
            var subscriptionDataConfig2 = new SubscriptionDataConfig(
                typeof(QuandlFuture), symbol2, Resolution.Daily, TimeZones.Utc, TimeZones.Utc, true, true, false, isCustom: true);

            var security1 = new Security(
                SecurityExchangeHours.AlwaysOpen(TimeZones.Utc),
                subscriptionDataConfig1,
                new Cash(CashBook.AccountCurrency, 0, 1m),
                SymbolProperties.GetDefault(CashBook.AccountCurrency),
                ErrorCurrencyConverter.Instance
                );

            var security2 = new Security(
                SecurityExchangeHours.AlwaysOpen(TimeZones.Utc),
                subscriptionDataConfig1,
                new Cash(CashBook.AccountCurrency, 0, 1m),
                SymbolProperties.GetDefault(CashBook.AccountCurrency),
                ErrorCurrencyConverter.Instance
                );

            var timeSlice = TimeSlice.Create(DateTime.UtcNow, TimeZones.Utc, new CashBook(),
                                             new List <DataFeedPacket>
            {
                new DataFeedPacket(security1, subscriptionDataConfig1, new List <BaseData> {
                    new QuandlFuture {
                        Symbol = symbol1, Time = DateTime.UtcNow.Date, Value = 15
                    }
                }),
                new DataFeedPacket(security2, subscriptionDataConfig2, new List <BaseData> {
                    new QuandlFuture {
                        Symbol = symbol2, Time = DateTime.UtcNow.Date, Value = 20
                    }
                }),
            },
                                             new SecurityChanges(Enumerable.Empty <Security>(), Enumerable.Empty <Security>()),
                                             new Dictionary <Universe, BaseDataCollection>());

            Assert.AreEqual(2, timeSlice.CustomData.Count);

            var data1 = timeSlice.CustomData[0].Data[0];
            var data2 = timeSlice.CustomData[1].Data[0];

            Assert.IsInstanceOf(typeof(QuandlFuture), data1);
            Assert.IsInstanceOf(typeof(QuandlFuture), data2);
            Assert.AreEqual(symbol1, data1.Symbol);
            Assert.AreEqual(symbol2, data2.Symbol);
            Assert.AreEqual(15, data1.Value);
            Assert.AreEqual(20, data2.Value);
        }
예제 #6
0
        public void HandlesTicks_ExpectInOrderWithNoDuplicates()
        {
            var subscriptionDataConfig = new SubscriptionDataConfig(
                typeof(Tick),
                Symbols.EURUSD,
                Resolution.Tick,
                TimeZones.Utc,
                TimeZones.Utc,
                true,
                true,
                false);

            var security = new Security(
                SecurityExchangeHours.AlwaysOpen(TimeZones.Utc),
                subscriptionDataConfig,
                new Cash(CashBook.AccountCurrency, 0, 1m),
                SymbolProperties.GetDefault(CashBook.AccountCurrency),
                ErrorCurrencyConverter.Instance
                );

            DateTime refTime = DateTime.UtcNow;

            Tick[] rawTicks = Enumerable
                              .Range(0, 10)
                              .Select(i => new Tick(refTime.AddSeconds(i), Symbols.EURUSD, 1.3465m, 1.34652m))
                              .ToArray();

            IEnumerable <TimeSlice> timeSlices = rawTicks.Select(t => TimeSlice.Create(
                                                                     t.Time,
                                                                     TimeZones.Utc,
                                                                     new CashBook(),
                                                                     new List <DataFeedPacket> {
                new DataFeedPacket(security, subscriptionDataConfig, new List <BaseData>()
                {
                    t
                })
            },
                                                                     new SecurityChanges(Enumerable.Empty <Security>(), Enumerable.Empty <Security>()),
                                                                     new Dictionary <Universe, BaseDataCollection>()));

            Tick[] timeSliceTicks = timeSlices.SelectMany(ts => ts.Slice.Ticks.Values.SelectMany(x => x)).ToArray();

            Assert.AreEqual(rawTicks.Length, timeSliceTicks.Length);
            for (int i = 0; i < rawTicks.Length; i++)
            {
                Assert.IsTrue(Compare(rawTicks[i], timeSliceTicks[i]));
            }
        }
예제 #7
0
        public void HandlesMultipleCustomDataOfSameTypeSameSymbol()
        {
            var symbol = Symbol.Create("DFX", SecurityType.Base, Market.USA);

            var subscriptionDataConfig = new SubscriptionDataConfig(
                typeof(DailyFx), symbol, Resolution.Daily, TimeZones.Utc, TimeZones.Utc, true, true, false, isCustom: true);

            var security = new Security(
                SecurityExchangeHours.AlwaysOpen(TimeZones.Utc),
                subscriptionDataConfig,
                new Cash(CashBook.AccountCurrency, 0, 1m),
                SymbolProperties.GetDefault(CashBook.AccountCurrency),
                ErrorCurrencyConverter.Instance
                );

            var refTime = DateTime.UtcNow;

            var timeSlice = TimeSlice.Create(refTime, TimeZones.Utc, new CashBook(),
                                             new List <DataFeedPacket>
            {
                new DataFeedPacket(security, subscriptionDataConfig, new List <BaseData>
                {
                    new DailyFx {
                        Symbol = symbol, Time = refTime, Title = "Item 1"
                    },
                    new DailyFx {
                        Symbol = symbol, Time = refTime, Title = "Item 2"
                    },
                }),
            },
                                             new SecurityChanges(Enumerable.Empty <Security>(), Enumerable.Empty <Security>()),
                                             new Dictionary <Universe, BaseDataCollection>());

            Assert.AreEqual(1, timeSlice.CustomData.Count);

            var data1 = timeSlice.CustomData[0].Data[0];
            var data2 = timeSlice.CustomData[0].Data[1];

            Assert.IsInstanceOf(typeof(DailyFx), data1);
            Assert.IsInstanceOf(typeof(DailyFx), data2);
            Assert.AreEqual(symbol, data1.Symbol);
            Assert.AreEqual(symbol, data2.Symbol);
            Assert.AreEqual("Item 1", ((DailyFx)data1).Title);
            Assert.AreEqual("Item 2", ((DailyFx)data2).Title);
        }
예제 #8
0
        public IEnumerable <Slice> GetHistory <T>(Symbol symbol, Resolution resolution, IEnumerable <T> data)
            where T : IBaseData
        {
            var subscriptionDataConfig = GetSubscriptionDataConfig <T>(symbol, resolution);
            var security = GetSecurity(subscriptionDataConfig);

            return(data.Select(t => TimeSlice.Create(
                                   t.Time,
                                   TimeZones.Utc,
                                   new CashBook(),
                                   new List <DataFeedPacket> {
                new DataFeedPacket(security, subscriptionDataConfig, new List <BaseData>()
                {
                    t as BaseData
                })
            },
                                   new SecurityChanges(Enumerable.Empty <Security>(), Enumerable.Empty <Security>())).Slice));
        }
예제 #9
0
            public IEnumerator <TimeSlice> GetEnumerator()
            {
                var dataFeedPacket = new DataFeedPacket(_algorithm.Securities[_symbol],
                                                        _algorithm.SubscriptionManager.Subscriptions.First(s => s.Symbol == _symbol),
                                                        new List <BaseData> {
                    _dividend
                }, Ref.CreateReadOnly(() => false));

                yield return(TimeSlice.Create(DateTime.UtcNow,
                                              TimeZones.NewYork,
                                              _algorithm.Portfolio.CashBook,
                                              new List <DataFeedPacket> {
                    dataFeedPacket
                },
                                              SecurityChanges.None,
                                              new Dictionary <Universe, BaseDataCollection>()
                                              ));
            }
예제 #10
0
        /// <summary>
        /// Creates an enumerable of Slice to update the alpha model
        /// </summary>
        protected virtual IEnumerable <Slice> CreateSlices()
        {
            var cashBook       = new CashBook();
            var changes        = SecurityChanges.None;
            var sliceDateTimes = GetSliceDateTimes(MaxSliceCount);

            for (var i = 0; i < sliceDateTimes.Count; i++)
            {
                var utcDateTime = sliceDateTimes[i];

                var packets = new List <DataFeedPacket>();

                // TODO : Give securities different values -- will require updating all derived types
                var last = Convert.ToDecimal(100 + 10 * Math.Sin(Math.PI * i / 180.0));
                var high = last * 1.005m;
                var low  = last / 1.005m;
                foreach (var kvp in _algorithm.Securities)
                {
                    var security       = kvp.Value;
                    var exchange       = security.Exchange.Hours;
                    var extendedMarket = security.IsExtendedMarketHours;
                    var localDateTime  = utcDateTime.ConvertFromUtc(exchange.TimeZone);
                    if (!exchange.IsOpen(localDateTime, extendedMarket))
                    {
                        continue;
                    }
                    var configuration = security.Subscriptions.FirstOrDefault();
                    var period        = security.Resolution.ToTimeSpan();
                    var time          = (utcDateTime - period).ConvertFromUtc(configuration.DataTimeZone);
                    var tradeBar      = new TradeBar(time, security.Symbol, last, high, low, last, 1000, period);
                    packets.Add(new DataFeedPacket(security, configuration, new List <BaseData> {
                        tradeBar
                    }));
                }

                if (packets.Count > 0)
                {
                    yield return(TimeSlice.Create(utcDateTime, TimeZones.NewYork, cashBook, packets, changes, new Dictionary <Universe, BaseDataCollection>()).Slice);
                }
            }
        }
예제 #11
0
        /// <summary>
        /// Gets the history for the requested securities
        /// </summary>
        /// <param name="requests">The historical data requests</param>
        /// <param name="sliceTimeZone">The time zone used when time stamping the slice instances</param>
        /// <returns>An enumerable of the slices of data covering the span specified in each request</returns>
        public override IEnumerable <Slice> GetHistory(IEnumerable <HistoryRequest> requests, DateTimeZone sliceTimeZone)
        {
            var configsByDateTime = GetSubscriptionDataConfigByDateTime(requests);
            var count             = configsByDateTime.Count;
            var i = 0;

            foreach (var kvp in configsByDateTime)
            {
                var utcDateTime = kvp.Key;
                var configs     = kvp.Value;
                var last        = Convert.ToDecimal(100 + 10 * Math.Sin(Math.PI * (360 - count + i) / 180.0));
                var high        = last * 1.005m;
                var low         = last / 1.005m;

                var packets = new List <DataFeedPacket>();

                foreach (var config in configs)
                {
                    Security security;
                    if (!_securities.TryGetValue(config.Symbol, out security))
                    {
                        continue;
                    }

                    var period = config.Resolution.ToTimeSpan();
                    var time   = (utcDateTime - period).ConvertFromUtc(config.DataTimeZone);
                    var data   = new TradeBar(time, config.Symbol, last, high, last, last, 1000, period);
                    security.SetMarketPrice(data);
                    packets.Add(new DataFeedPacket(security, config, new List <BaseData> {
                        data
                    }));
                }

                i++;
                yield return(TimeSlice.Create(utcDateTime, sliceTimeZone, _cashBook, packets, _securityChanges, new Dictionary <Universe, BaseDataCollection>()).Slice);
            }
        }
예제 #12
0
        private IEnumerable <TimeSlice> Stream(AlgorithmNodePacket job, IAlgorithm algorithm, IDataFeed feed, IResultHandler results, CancellationToken cancellationToken)
        {
            bool setStartTime = false;
            var  timeZone     = algorithm.TimeZone;
            var  history      = algorithm.HistoryProvider;

            // get the required history job from the algorithm
            DateTime?lastHistoryTimeUtc = null;
            var      historyRequests    = algorithm.GetWarmupHistoryRequests().ToList();

            // initialize variables for progress computation
            var start            = DateTime.UtcNow.Ticks;
            var nextStatusTime   = DateTime.UtcNow.AddSeconds(1);
            var minimumIncrement = algorithm.UniverseManager
                                   .Select(x => x.Value.Configuration.Resolution.ToTimeSpan())
                                   .DefaultIfEmpty(Time.OneSecond)
                                   .Min();

            minimumIncrement = minimumIncrement == TimeSpan.Zero ? Time.OneSecond : minimumIncrement;

            if (historyRequests.Count != 0)
            {
                // rewrite internal feed requests
                var subscriptions = algorithm.SubscriptionManager.Subscriptions.Where(x => !x.IsInternalFeed).ToList();
                var minResolution = subscriptions.Count > 0 ? subscriptions.Min(x => x.Resolution) : Resolution.Second;
                foreach (var request in historyRequests)
                {
                    Security security;
                    if (algorithm.Securities.TryGetValue(request.Symbol, out security) && security.SubscriptionDataConfig.IsInternalFeed)
                    {
                        if (request.Resolution < minResolution)
                        {
                            request.Resolution            = minResolution;
                            request.FillForwardResolution = request.FillForwardResolution.HasValue ? minResolution : (Resolution?)null;
                        }
                    }
                }

                // rewrite all to share the same fill forward resolution
                if (historyRequests.Any(x => x.FillForwardResolution.HasValue))
                {
                    minResolution = historyRequests.Where(x => x.FillForwardResolution.HasValue).Min(x => x.FillForwardResolution.Value);
                    foreach (var request in historyRequests.Where(x => x.FillForwardResolution.HasValue))
                    {
                        request.FillForwardResolution = minResolution;
                    }
                }

                foreach (var request in historyRequests)
                {
                    start = Math.Min(request.StartTimeUtc.Ticks, start);
                    Log.Trace(string.Format("AlgorithmManager.Stream(): WarmupHistoryRequest: {0}: Start: {1} End: {2} Resolution: {3}", request.Symbol, request.StartTimeUtc, request.EndTimeUtc, request.Resolution));
                }

                // make the history request and build time slices
                foreach (var slice in history.GetHistory(historyRequests, timeZone))
                {
                    TimeSlice timeSlice;
                    try
                    {
                        // we need to recombine this slice into a time slice
                        var paired = new List <KeyValuePair <Security, List <BaseData> > >();
                        foreach (var symbol in slice.Keys)
                        {
                            var security = algorithm.Securities[symbol];
                            var data     = slice[symbol];
                            var list     = new List <BaseData>();
                            var ticks    = data as List <Tick>;
                            if (ticks != null)
                            {
                                list.AddRange(ticks);
                            }
                            else
                            {
                                list.Add(data);
                            }
                            paired.Add(new KeyValuePair <Security, List <BaseData> >(security, list));
                        }
                        timeSlice = TimeSlice.Create(slice.Time.ConvertToUtc(timeZone), timeZone, algorithm.Portfolio.CashBook, paired, SecurityChanges.None);
                    }
                    catch (Exception err)
                    {
                        Log.Error(err);
                        algorithm.RunTimeError = err;
                        yield break;
                    }

                    if (timeSlice != null)
                    {
                        if (!setStartTime)
                        {
                            setStartTime  = true;
                            _previousTime = timeSlice.Time;
                            algorithm.Debug("Algorithm warming up...");
                        }
                        if (DateTime.UtcNow > nextStatusTime)
                        {
                            // send some status to the user letting them know we're done history, but still warming up,
                            // catching up to real time data
                            nextStatusTime = DateTime.UtcNow.AddSeconds(1);
                            var percent = (int)(100 * (timeSlice.Time.Ticks - start) / (double)(DateTime.UtcNow.Ticks - start));
                            results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.History, string.Format("Catching up to realtime {0}%...", percent));
                        }
                        yield return(timeSlice);

                        lastHistoryTimeUtc = timeSlice.Time;
                    }
                }
            }

            // if we're not live or didn't event request warmup, then set us as not warming up
            if (!algorithm.LiveMode || historyRequests.Count == 0)
            {
                algorithm.SetFinishedWarmingUp();
                results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Running);
                if (historyRequests.Count != 0)
                {
                    algorithm.Debug("Algorithm finished warming up.");
                    Log.Trace("AlgorithmManager.Stream(): Finished warmup");
                }
            }

            foreach (var timeSlice in feed)
            {
                if (!setStartTime)
                {
                    setStartTime  = true;
                    _previousTime = timeSlice.Time;
                }
                if (algorithm.LiveMode && algorithm.IsWarmingUp)
                {
                    // this is hand-over logic, we spin up the data feed first and then request
                    // the history for warmup, so there will be some overlap between the data
                    if (lastHistoryTimeUtc.HasValue)
                    {
                        // make sure there's no historical data, this only matters for the handover
                        var hasHistoricalData = false;
                        foreach (var data in timeSlice.Slice.Ticks.Values.SelectMany(x => x).Concat <BaseData>(timeSlice.Slice.Bars.Values))
                        {
                            // check if any ticks in the list are on or after our last warmup point, if so, skip this data
                            if (data.EndTime.ConvertToUtc(algorithm.Securities[data.Symbol].Exchange.TimeZone) >= lastHistoryTimeUtc)
                            {
                                hasHistoricalData = true;
                                break;
                            }
                        }
                        if (hasHistoricalData)
                        {
                            continue;
                        }

                        // prevent us from doing these checks every loop
                        lastHistoryTimeUtc = null;
                    }

                    // in live mode wait to mark us as finished warming up when
                    // the data feed has caught up to now within the min increment
                    if (timeSlice.Time > DateTime.UtcNow.Subtract(minimumIncrement))
                    {
                        algorithm.SetFinishedWarmingUp();
                        results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Running);
                        algorithm.Debug("Algorithm finished warming up.");
                        Log.Trace("AlgorithmManager.Stream(): Finished warmup");
                    }
                    else if (DateTime.UtcNow > nextStatusTime)
                    {
                        // send some status to the user letting them know we're done history, but still warming up,
                        // catching up to real time data
                        nextStatusTime = DateTime.UtcNow.AddSeconds(1);
                        var percent = (int)(100 * (timeSlice.Time.Ticks - start) / (double)(DateTime.UtcNow.Ticks - start));
                        results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.History, string.Format("Catching up to realtime {0}%...", percent));
                    }
                }
                yield return(timeSlice);
            }
        }
        /// <summary>
        /// Enumerates the subscriptions into slices
        /// </summary>
        private IEnumerable <Slice> CreateSliceEnumerableFromSubscriptions(List <Subscription> subscriptions, DateTimeZone sliceTimeZone)
        {
            // required by TimeSlice.Create, but we don't need it's behavior
            var cashBook = new CashBook();

            cashBook.Clear();
            var frontier = DateTime.MinValue;

            while (true)
            {
                var earlyBirdTicks = long.MaxValue;
                var data           = new List <DataFeedPacket>();
                foreach (var subscription in subscriptions)
                {
                    if (subscription.EndOfStream)
                    {
                        continue;
                    }

                    var packet = new DataFeedPacket(subscription.Security, subscription.Configuration);

                    var offsetProvider     = subscription.OffsetProvider;
                    var currentOffsetTicks = offsetProvider.GetOffsetTicks(frontier);
                    while (subscription.Current.EndTime.Ticks - currentOffsetTicks <= frontier.Ticks)
                    {
                        // we want bars rounded using their subscription times, we make a clone
                        // so we don't interfere with the enumerator's internal logic
                        var clone = subscription.Current.Clone(subscription.Current.IsFillForward);
                        clone.Time = clone.Time.RoundDown(subscription.Configuration.Increment);
                        packet.Add(clone);
                        Interlocked.Increment(ref _dataPointCount);
                        if (!subscription.MoveNext())
                        {
                            break;
                        }
                    }
                    // only add if we have data
                    if (packet.Count != 0)
                    {
                        data.Add(packet);
                    }
                    // udate our early bird ticks (next frontier time)
                    if (subscription.Current != null)
                    {
                        // take the earliest between the next piece of data or the next tz discontinuity
                        var nextDataOrDiscontinuity = Math.Min(subscription.Current.EndTime.Ticks - currentOffsetTicks, offsetProvider.GetNextDiscontinuity());
                        earlyBirdTicks = Math.Min(earlyBirdTicks, nextDataOrDiscontinuity);
                    }
                }

                // end of subscriptions
                if (earlyBirdTicks == long.MaxValue)
                {
                    break;
                }

                if (data.Count != 0)
                {
                    // reuse the slice construction code from TimeSlice.Create
                    yield return(TimeSlice.Create(frontier, sliceTimeZone, cashBook, data, SecurityChanges.None).Slice);
                }

                frontier = new DateTime(Math.Max(earlyBirdTicks, frontier.Ticks), DateTimeKind.Utc);
            }

            // make sure we clean up after ourselves
            foreach (var subscription in subscriptions)
            {
                subscription.Dispose();
            }
        }
예제 #14
0
        /// <summary>
        /// Enumerates the subscriptions into slices
        /// </summary>
        protected IEnumerable <Slice> CreateSliceEnumerableFromSubscriptions(List <Subscription> subscriptions, DateTimeZone sliceTimeZone)
        {
            // required by TimeSlice.Create, but we don't need it's behavior
            var cashBook = new CashBook();

            cashBook.Clear();
            var frontier = DateTime.MinValue;

            while (true)
            {
                var earlyBirdTicks = long.MaxValue;
                var data           = new List <DataFeedPacket>();
                foreach (var subscription in subscriptions)
                {
                    if (subscription.EndOfStream)
                    {
                        continue;
                    }

                    var packet = new DataFeedPacket(subscription.Security, subscription.Configuration);

                    while (subscription.Current.EmitTimeUtc <= frontier)
                    {
                        packet.Add(subscription.Current.Data);
                        Interlocked.Increment(ref _dataPointCount);
                        if (!subscription.MoveNext())
                        {
                            break;
                        }
                    }
                    // only add if we have data
                    if (packet.Count != 0)
                    {
                        data.Add(packet);
                    }
                    // udate our early bird ticks (next frontier time)
                    if (subscription.Current != null)
                    {
                        // take the earliest between the next piece of data or the next tz discontinuity
                        earlyBirdTicks = Math.Min(earlyBirdTicks, subscription.Current.EmitTimeUtc.Ticks);
                    }
                }

                // end of subscriptions
                if (earlyBirdTicks == long.MaxValue)
                {
                    break;
                }

                if (data.Count != 0)
                {
                    // reuse the slice construction code from TimeSlice.Create
                    yield return(TimeSlice.Create(frontier, sliceTimeZone, cashBook, data, SecurityChanges.None, new Dictionary <Universe, BaseDataCollection>()).Slice);
                }

                frontier = new DateTime(Math.Max(earlyBirdTicks, frontier.Ticks), DateTimeKind.Utc);
            }

            // make sure we clean up after ourselves
            foreach (var subscription in subscriptions)
            {
                subscription.Dispose();
            }
        }