Пример #1
0
        private void AddSubscriptionForUniverseSelectionMarket(string market)
        {
            var exchangeHours          = SecurityExchangeHoursProvider.FromDataFolder().GetExchangeHours(market, null, SecurityType.Equity);
            var symbolName             = market + "-market";
            var subscriptionDataConfig = new SubscriptionDataConfig(typeof(CoarseFundamental), SecurityType.Equity, symbolName, Resolution.Daily, market, exchangeHours.TimeZone,
                                                                    true, false, true);
            var security = new Security(exchangeHours, subscriptionDataConfig, 1);

            var cf   = new CoarseFundamental();
            var list = new List <BaseData>();

            foreach (var date in Time.EachTradeableDay(security, _algorithm.StartDate, _algorithm.EndDate))
            {
                var factory = new BaseDataSubscriptionFactory(subscriptionDataConfig, date, false);
                var source  = cf.GetSource(subscriptionDataConfig, date, false);
                var coarseFundamentalForDate = factory.Read(source);
                list.AddRange(coarseFundamentalForDate);
            }


            // spoof a subscription for the market that emits at midnight of each tradeable day
            var subscription = new Subscription(security,
                                                list.GetEnumerator(),
                                                _algorithm.StartDate.ConvertToUtc(exchangeHours.TimeZone),
                                                _algorithm.EndDate.ConvertToUtc(exchangeHours.TimeZone),
                                                false,
                                                true
                                                );

            // let user know if we fail to load the universe subscription, very important for when understanding backtest results!
            PrimeSubscriptionPump(subscription, true);
            _subscriptions.AddOrUpdate(new SymbolSecurityType(subscription), subscription);
        }
Пример #2
0
        /// <summary>
        /// Creates a new univese and adds it to the algorithm. This is for coarse fundamntal US Equity data and
        /// will be executed on day changes in the NewYork time zone (<see cref="TimeZones.NewYork"/>
        /// </summary>
        /// <param name="selector">Defines an initial coarse selection</param>
        public void AddUniverse(Func <IEnumerable <CoarseFundamental>, IEnumerable <Symbol> > selector)
        {
            var symbol = CoarseFundamental.CreateUniverseSymbol(Market.USA);
            var config = new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, true, isFilteredSubscription: false);

            AddUniverse(new FuncUniverse(config, UniverseSettings, SecurityInitializer, selectionData => selector(selectionData.OfType <CoarseFundamental>())));
        }
Пример #3
0
        /// <summary>
        /// Gets the <see cref="CoarseFundamental"/> data for the specified market/date
        /// </summary>
        public static IEnumerable <CoarseFundamental> GetCoarseFundamentals(string market, DateTimeZone timeZone, DateTime date, bool isLiveMode)
        {
            var factory = new CoarseFundamental();
            var config  = new SubscriptionDataConfig(typeof(CoarseFundamental), SecurityType.Equity, new Symbol(market + "-coarse"), Resolution.Daily, market, timeZone, true, false, true, false);
            var reader  = new BaseDataSubscriptionFactory(config, date, isLiveMode);
            var source  = factory.GetSource(config, date, isLiveMode);

            return(reader.Read(source).OfType <CoarseFundamental>());
        }
Пример #4
0
        /// <summary>
        /// Creates a new coarse universe that contains the bottom count of stocks
        /// by daily dollar volume
        /// </summary>
        /// <param name="count">The number of stock to select</param>
        /// <param name="universeSettings">The settings for stocks added by this universe.
        /// Defaults to <see cref="QCAlgorithm.UniverseSettings"/></param>
        /// <returns>A new coarse universe for the bottom count of stocks by dollar volume</returns>
        public Universe Bottom(int count, UniverseSettings universeSettings = null)
        {
            universeSettings = universeSettings ?? _algorithm.UniverseSettings;
            var symbol = CoarseFundamental.CreateUniverseSymbol(Market.USA);
            var config = new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, true);

            return(new FuncUniverse(config, universeSettings, _algorithm.SecurityInitializer, selectionData => (
                                        from c in selectionData.OfType <CoarseFundamental>()
                                        orderby c.DollarVolume descending
                                        select c.Symbol).Take(count)
                                    ));
        }
        public void ReturnsExpectedTimestamps()
        {
            var symbol   = CoarseFundamental.CreateUniverseSymbol(Market.USA);
            var config   = new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, false, false, TickType.Trade, false);
            var security = new Security(
                SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork),
                config,
                new Cash(Currencies.USD, 0, 1),
                SymbolProperties.GetDefault(Currencies.USD),
                ErrorCurrencyConverter.Instance,
                RegisteredSecurityDataTypesProvider.Null,
                new SecurityCache()
                );

            var universeSettings    = new UniverseSettings(Resolution.Daily, 2m, true, false, TimeSpan.FromDays(1));
            var securityInitializer = new BrokerageModelSecurityInitializer(new DefaultBrokerageModel(), SecuritySeeder.Null);
            var universe            = new CoarseFundamentalUniverse(universeSettings, securityInitializer, x => new List <Symbol> {
                Symbols.AAPL
            });

            var fileProvider = new DefaultDataProvider();

            var factory = new BaseDataCollectionSubscriptionEnumeratorFactory();

            var dateStart = new DateTime(2014, 3, 26);
            var dateEnd   = new DateTime(2014, 3, 27);
            var days      = (dateEnd - dateStart).Days + 1;

            var request = new SubscriptionRequest(true, universe, security, config, dateStart, dateEnd);

            using (var enumerator = factory.CreateEnumerator(request, fileProvider))
            {
                dateStart = dateStart.AddDays(-1);
                for (var i = 0; i <= days; i++)
                {
                    Assert.IsTrue(enumerator.MoveNext());

                    var current = enumerator.Current as BaseDataCollection;
                    Assert.IsNotNull(current);
                    Assert.AreEqual(dateStart.AddDays(i), current.Time);
                    Assert.AreEqual(dateStart.AddDays(i), current.EndTime);
                    Assert.AreEqual(dateStart.AddDays(i - 1), current.Data[0].Time);
                    Assert.AreEqual(dateStart.AddDays(i), current.Data[0].EndTime);
                }

                Assert.IsFalse(enumerator.MoveNext());
                Assert.IsNotNull(enumerator.Current);
            }
        }
        public void DoesNotLeakMemory()
        {
            var symbol   = CoarseFundamental.CreateUniverseSymbol(Market.USA);
            var config   = new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, false, false, TickType.Trade, false);
            var security = new Security(
                SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork),
                config,
                new Cash(Currencies.USD, 0, 1),
                SymbolProperties.GetDefault(Currencies.USD),
                ErrorCurrencyConverter.Instance,
                RegisteredSecurityDataTypesProvider.Null,
                new SecurityCache()
                );

            var universeSettings    = new UniverseSettings(Resolution.Daily, 2m, true, false, TimeSpan.FromDays(1));
            var securityInitializer = new BrokerageModelSecurityInitializer(new DefaultBrokerageModel(), SecuritySeeder.Null);
            var universe            = new CoarseFundamentalUniverse(universeSettings, securityInitializer, x => new List <Symbol> {
                Symbols.AAPL
            });

            var fileProvider = new DefaultDataProvider();

            var factory = new BaseDataCollectionSubscriptionEnumeratorFactory();

            GC.Collect();
            var ramUsageBeforeLoop = OS.TotalPhysicalMemoryUsed;

            var date = new DateTime(2014, 3, 25);

            const int iterations = 1000;

            for (var i = 0; i < iterations; i++)
            {
                var request = new SubscriptionRequest(true, universe, security, config, date, date);
                using (var enumerator = factory.CreateEnumerator(request, fileProvider))
                {
                    enumerator.MoveNext();
                }
            }

            GC.Collect();
            var ramUsageAfterLoop = OS.TotalPhysicalMemoryUsed;

            Log.Trace($"RAM usage - before: {ramUsageBeforeLoop} MB, after: {ramUsageAfterLoop} MB");

            Assert.IsTrue(ramUsageAfterLoop - ramUsageBeforeLoop < 10);
        }
Пример #7
0
        public void ToRow(string coarseLine)
        {
            var config = new SubscriptionDataConfig(typeof(CoarseFundamental),
                                                    Symbols.SPY,
                                                    Resolution.Second,
                                                    DateTimeZone.Utc,
                                                    DateTimeZone.Utc,
                                                    false,
                                                    false,
                                                    false);
            var factory    = new CoarseFundamental();
            var coarseRead = (CoarseFundamental)factory.Reader(config, coarseLine, DateTime.UtcNow, false);

            var row = CoarseFundamental.ToRow(coarseRead);

            Assert.AreEqual(coarseLine, row);
        }
Пример #8
0
        /// <summary>
        /// Creates a new coarse universe that contains stocks in the specified
        /// dollar volume percentile
        /// </summary>
        /// <param name="percentile">The desired dollar volume percentile (0 to 100 inclusive)</param>
        /// <param name="universeSettings">The settings for stocks added by this universe.
        /// Defaults to <see cref="QCAlgorithm.UniverseSettings"/></param>
        /// <returns>A new coarse universe for the bottom count of stocks by dollar volume</returns>
        public Universe Percentile(double percentile, UniverseSettings universeSettings = null)
        {
            universeSettings = universeSettings ?? _algorithm.UniverseSettings;
            var symbol = CoarseFundamental.CreateUniverseSymbol(Market.USA);
            var config = new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, true);

            return(new FuncUniverse(config, universeSettings, _algorithm.SecurityInitializer, selectionData =>
            {
                var list = selectionData as IReadOnlyList <CoarseFundamental> ?? selectionData.OfType <CoarseFundamental>().ToList();

                // using quantiles since the Percentile implementation requires integers, so scale into quantile space
                var lowerBound = (decimal)list.Select(x => (double)x.DollarVolume).Quantile(percentile / 100d);

                return from c in list
                where c.DollarVolume >= lowerBound
                orderby c.DollarVolume descending
                select c.Symbol;
            }));
        }
Пример #9
0
        public void ParsesCoarseCsvLine(string line, bool hasFundamentalData, decimal price, decimal priceFactor, decimal splitFactor, decimal adjustedPrice)
        {
            var cf = new CoarseFundamental();

            var config = new SubscriptionDataConfig(typeof(TradeBar),
                                                    Symbols.AAPL,
                                                    Resolution.Second,
                                                    TimeZones.NewYork,
                                                    TimeZones.NewYork,
                                                    false,
                                                    false,
                                                    false,
                                                    false,
                                                    TickType.Trade,
                                                    false);

            cf = (CoarseFundamental)cf.Reader(config, line, DateTime.MinValue, false);

            Assert.AreEqual(hasFundamentalData, cf.HasFundamentalData);
            Assert.AreEqual(price, cf.Price);
            Assert.AreEqual(priceFactor, cf.PriceFactor);
            Assert.AreEqual(splitFactor, cf.SplitFactor);
            Assert.AreEqual(adjustedPrice, cf.AdjustedPrice);
        }
Пример #10
0
        /// <summary>
        /// Adds a new subscription for universe selection
        /// </summary>
        /// <param name="universe">The universe to add a subscription for</param>
        /// <param name="startTimeUtc">The start time of the subscription in utc</param>
        /// <param name="endTimeUtc">The end time of the subscription in utc</param>
        public void AddUniverseSubscription(Universe universe, DateTime startTimeUtc, DateTime endTimeUtc)
        {
            // TODO : Consider moving the creating of universe subscriptions to a separate, testable class

            // grab the relevant exchange hours
            var config = universe.Configuration;

            var marketHoursDatabase = MarketHoursDatabase.FromDataFolder();
            var exchangeHours       = marketHoursDatabase.GetExchangeHours(config);

            // create a canonical security object
            var security = new Security(exchangeHours, config, _algorithm.Portfolio.CashBook[CashBook.AccountCurrency], SymbolProperties.GetDefault(CashBook.AccountCurrency));

            var localStartTime = startTimeUtc.ConvertFromUtc(security.Exchange.TimeZone);
            var localEndTime   = endTimeUtc.ConvertFromUtc(security.Exchange.TimeZone);

            // define our data enumerator
            IEnumerator <BaseData> enumerator;

            var tradeableDates = Time.EachTradeableDay(security, localStartTime, localEndTime);

            var userDefined = universe as UserDefinedUniverse;

            if (userDefined != null)
            {
                // spoof a tick on the requested interval to trigger the universe selection function
                enumerator = userDefined.GetTriggerTimes(startTimeUtc, endTimeUtc, marketHoursDatabase)
                             .Select(x => new Tick {
                    Time = x, Symbol = config.Symbol
                }).GetEnumerator();

                // route these custom subscriptions through the exchange for buffering
                var enqueueable = new EnqueueableEnumerator <BaseData>(true);

                // add this enumerator to our exchange
                ScheduleEnumerator(enumerator, enqueueable, GetLowerThreshold(config.Resolution), GetUpperThreshold(config.Resolution));

                enumerator = enqueueable;
            }
            else if (config.Type == typeof(CoarseFundamental))
            {
                var cf = new CoarseFundamental();

                var enqueueable = new EnqueueableEnumerator <BaseData>(true);

                // load coarse data day by day
                var coarse = from date in Time.EachTradeableDay(security, _algorithm.StartDate, _algorithm.EndDate)
                             let dateInDataTimeZone = date.ConvertTo(config.ExchangeTimeZone, config.DataTimeZone).Date
                                                      let source = cf.GetSource(config, dateInDataTimeZone, false)
                                                                   let factory = SubscriptionFactory.ForSource(source, config, dateInDataTimeZone, false)
                                                                                 let coarseFundamentalForDate = factory.Read(source)
                                                                                                                select new BaseDataCollection(date, config.Symbol, coarseFundamentalForDate);


                ScheduleEnumerator(coarse.GetEnumerator(), enqueueable, 5, 100000, 2);

                enumerator = enqueueable;
            }
            else
            {
                // normal reader for all others
                enumerator = new SubscriptionDataReader(config, localStartTime, localEndTime, _resultHandler, MapFileResolver.Empty, _factorFileProvider, tradeableDates, false);

                // route these custom subscriptions through the exchange for buffering
                var enqueueable = new EnqueueableEnumerator <BaseData>(true);

                // add this enumerator to our exchange
                ScheduleEnumerator(enumerator, enqueueable, GetLowerThreshold(config.Resolution), GetUpperThreshold(config.Resolution));

                enumerator = enqueueable;
            }

            // create the subscription
            var timeZoneOffsetProvider = new TimeZoneOffsetProvider(security.Exchange.TimeZone, startTimeUtc, endTimeUtc);
            var subscription           = new Subscription(universe, security, enumerator, timeZoneOffsetProvider, startTimeUtc, endTimeUtc, true);

            _subscriptions.AddOrUpdate(subscription.Security.Symbol, subscription);
        }
Пример #11
0
        /// <summary>
        /// Adds a new subscription for universe selection
        /// </summary>
        /// <param name="universe">The universe to add a subscription for</param>
        /// <param name="startTimeUtc">The start time of the subscription in utc</param>
        /// <param name="endTimeUtc">The end time of the subscription in utc</param>
        public void AddUniverseSubscription(Universe universe, DateTime startTimeUtc, DateTime endTimeUtc)
        {
            // TODO : Consider moving the creating of universe subscriptions to a separate, testable class

            // grab the relevant exchange hours
            var config = universe.Configuration;

            var marketHoursDatabase = MarketHoursDatabase.FromDataFolder();
            var exchangeHours       = marketHoursDatabase.GetExchangeHours(config);

            Security security;

            if (!_algorithm.Securities.TryGetValue(config.Symbol, out security))
            {
                // create a canonical security object if it doesn't exist
                security = new Security(exchangeHours, config, _algorithm.Portfolio.CashBook[CashBook.AccountCurrency], SymbolProperties.GetDefault(CashBook.AccountCurrency));
            }

            var localStartTime = startTimeUtc.ConvertFromUtc(security.Exchange.TimeZone);
            var localEndTime   = endTimeUtc.ConvertFromUtc(security.Exchange.TimeZone);

            // define our data enumerator
            IEnumerator <BaseData> enumerator;

            var tradeableDates = Time.EachTradeableDayInTimeZone(security.Exchange.Hours, localStartTime, localEndTime, config.DataTimeZone, config.ExtendedMarketHours);

            var userDefined = universe as UserDefinedUniverse;

            if (userDefined != null)
            {
                // spoof a tick on the requested interval to trigger the universe selection function
                enumerator = userDefined.GetTriggerTimes(startTimeUtc, endTimeUtc, marketHoursDatabase)
                             .Select(x => new Tick {
                    Time = x, Symbol = config.Symbol
                }).GetEnumerator();

                // route these custom subscriptions through the exchange for buffering
                var enqueueable = new EnqueueableEnumerator <BaseData>(true);

                // add this enumerator to our exchange
                ScheduleEnumerator(enumerator, enqueueable, GetLowerThreshold(config.Resolution), GetUpperThreshold(config.Resolution));

                enumerator = enqueueable;
            }
            else if (config.Type == typeof(CoarseFundamental))
            {
                var cf = new CoarseFundamental();

                // load coarse data day by day
                enumerator = (from date in Time.EachTradeableDayInTimeZone(security.Exchange.Hours, _algorithm.StartDate, _algorithm.EndDate, config.DataTimeZone, config.ExtendedMarketHours)
                              let source = cf.GetSource(config, date, false)
                                           let factory = SubscriptionDataSourceReader.ForSource(source, config, date, false)
                                                         let coarseFundamentalForDate = factory.Read(source)
                                                                                        select new BaseDataCollection(date.AddDays(1), config.Symbol, coarseFundamentalForDate)
                              ).GetEnumerator();

                var enqueueable = new EnqueueableEnumerator <BaseData>(true);
                ScheduleEnumerator(enumerator, enqueueable, 5, 100000, 2);

                enumerator = enqueueable;
            }
            else if (config.SecurityType == SecurityType.Option && security is Option)
            {
                var configs     = universe.GetSubscriptions(security);
                var enumerators = configs.Select(c =>
                                                 CreateSubscriptionEnumerator(security, c, localStartTime, localEndTime, _mapFileProvider.Get(c.Market), tradeableDates, false, true)
                                                 ).ToList();

                var sync = new SynchronizingEnumerator(enumerators);
                enumerator = new OptionChainUniverseDataCollectionAggregatorEnumerator(sync, config.Symbol);

                var enqueueable = new EnqueueableEnumerator <BaseData>(true);

                // add this enumerator to our exchange
                ScheduleEnumerator(enumerator, enqueueable, GetLowerThreshold(config.Resolution), GetUpperThreshold(config.Resolution));

                enumerator = enqueueable;
            }
            else
            {
                // normal reader for all others
                enumerator = CreateSubscriptionEnumerator(security, config, localStartTime, localEndTime, MapFileResolver.Empty, tradeableDates, true, false);

                // route these custom subscriptions through the exchange for buffering
                var enqueueable = new EnqueueableEnumerator <BaseData>(true);

                // add this enumerator to our exchange
                ScheduleEnumerator(enumerator, enqueueable, GetLowerThreshold(config.Resolution), GetUpperThreshold(config.Resolution));

                enumerator = enqueueable;
            }

            // create the subscription
            var timeZoneOffsetProvider = new TimeZoneOffsetProvider(security.Exchange.TimeZone, startTimeUtc, endTimeUtc);
            var subscription           = new Subscription(universe, security, config, enumerator, timeZoneOffsetProvider, startTimeUtc, endTimeUtc, true);

            _subscriptions.TryAdd(subscription);

            UpdateFillForwardResolution();
        }
Пример #12
0
        public void CoarseUniverseRotatesActiveSecurity()
        {
            var startDate = new DateTime(2014, 3, 24);
            var endDate   = new DateTime(2014, 3, 28);

            var timeProvider = new ManualTimeProvider(TimeZones.NewYork);

            timeProvider.SetCurrentTime(startDate);

            var coarseTimes = new List <DateTime>
            {
                new DateTime(2014, 3, 25),
                new DateTime(2014, 3, 25, 23, 0, 0),
                new DateTime(2014, 3, 27, 1, 0, 0)
            }.ToHashSet();

            var coarseSymbols = new List <Symbol> {
                Symbols.SPY, Symbols.AAPL, Symbols.MSFT
            };

            var coarseUsaSymbol = CoarseFundamental.CreateUniverseSymbol(Market.USA, false);

            var coarseDataEmittedCount = 0;
            var lastTime         = DateTime.MinValue;
            var dataQueueHandler = new FuncDataQueueHandler(fdqh =>
            {
                var time = timeProvider.GetUtcNow().ConvertFromUtc(TimeZones.NewYork);
                if (time != lastTime)
                {
                    lastTime = time;

                    if (coarseTimes.Contains(time))
                    {
                        // emit coarse data at selected times
                        var coarseData = new BaseDataCollection {
                            Symbol = coarseUsaSymbol
                        };
                        foreach (var symbol in coarseSymbols)
                        {
                            coarseData.Data.Add(
                                new CoarseFundamental
                            {
                                Symbol = symbol,
                                Time   = time,
                                Market = Market.USA,
                                Value  = 100
                            });
                        }
                        coarseDataEmittedCount++;
                        return(new List <BaseData> {
                            coarseData
                        });
                    }
                }
                return(Enumerable.Empty <BaseData>());
            });

            var feed = new TestableLiveTradingDataFeed(dataQueueHandler);

            var algorithm = new AlgorithmStub(feed);

            algorithm.SetLiveMode(true);

            var mock = new Mock <ITransactionHandler>();

            mock.Setup(m => m.GetOpenOrders(It.IsAny <Func <Order, bool> >())).Returns(new List <Order>());
            algorithm.Transactions.SetOrderProcessor(mock.Object);

            var synchronizer = new TestableLiveSynchronizer(timeProvider);

            synchronizer.Initialize(algorithm, algorithm.DataManager);

            var mapFileProvider = new LocalDiskMapFileProvider();

            feed.Initialize(algorithm, new LiveNodePacket(), new BacktestingResultHandler(),
                            mapFileProvider, new LocalDiskFactorFileProvider(mapFileProvider), new DefaultDataProvider(), algorithm.DataManager, synchronizer);

            var symbolIndex = 0;
            var coarseUniverseSelectionCount = 0;

            algorithm.AddUniverse(
                coarse =>
            {
                coarseUniverseSelectionCount++;

                // rotate single symbol in universe
                if (symbolIndex == coarseSymbols.Count)
                {
                    symbolIndex = 0;
                }

                return(new[] { coarseSymbols[symbolIndex++] });
            });

            algorithm.PostInitialize();

            var cancellationTokenSource = new CancellationTokenSource();

            Exception exceptionThrown = null;

            // create a timer to advance time much faster than realtime
            var timerInterval = TimeSpan.FromMilliseconds(50);
            var timer         = Ref.Create <Timer>(null);

            timer.Value = new Timer(state =>
            {
                try
                {
                    // stop the timer to prevent reentrancy
                    timer.Value.Change(Timeout.Infinite, Timeout.Infinite);

                    var currentTime = timeProvider.GetUtcNow().ConvertFromUtc(TimeZones.NewYork);

                    if (currentTime.Date > endDate.Date)
                    {
                        feed.Exit();
                        cancellationTokenSource.Cancel();
                        return;
                    }

                    timeProvider.Advance(TimeSpan.FromHours(1));

                    var activeSecuritiesCount = algorithm.ActiveSecurities.Count;

                    Assert.That(activeSecuritiesCount <= 1);

                    // restart the timer
                    timer.Value.Change(timerInterval, timerInterval);
                }
                catch (Exception exception)
                {
                    Log.Error(exception);
                    exceptionThrown = exception;

                    feed.Exit();
                    cancellationTokenSource.Cancel();
                }
            }, null, TimeSpan.FromSeconds(1), timerInterval);

            foreach (var _ in synchronizer.StreamData(cancellationTokenSource.Token))
            {
            }

            timer.Value.Dispose();

            if (exceptionThrown != null)
            {
                throw new Exception("Exception in timer: ", exceptionThrown);
            }

            Assert.AreEqual(coarseTimes.Count, coarseDataEmittedCount);
            Assert.AreEqual(coarseTimes.Count, coarseUniverseSelectionCount);
        }
Пример #13
0
        public void HandlesCoarseFundamentalData()
        {
            var    algorithm = new AlgorithmStub();
            Symbol symbol    = CoarseFundamental.CreateUniverseSymbol(Market.USA);

            algorithm.SetUniverse(new FuncUniverse(
                                      new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, false),
                                      new SubscriptionSettings(Resolution.Second, 1, true, false),
                                      coarse => coarse.Take(10).Select(x => x.Symbol)
                                      ));

            var lck = new object();
            BaseDataCollection list = null;
            const int          coarseDataPointCount = 100000;
            var timer = new Timer(state =>
            {
                var currentTime = DateTime.UtcNow.ConvertFromUtc(TimeZones.NewYork);
                Console.WriteLine(currentTime + ": timer.Elapsed");

                lock (state)
                {
                    list = new BaseDataCollection {
                        Symbol = symbol
                    };
                    list.Data.AddRange(Enumerable.Range(0, coarseDataPointCount).Select(x => new CoarseFundamental
                    {
                        Symbol = SymbolCache.GetSymbol(x.ToString()),
                        Time   = currentTime - Time.OneDay, // hard-coded coarse period of one day
                    }));
                }
            }, lck, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(500));

            bool yieldedUniverseData = false;
            var  feed = RunDataFeed(algorithm, fdqh =>
            {
                lock (lck)
                {
                    if (list != null)
                    {
                        try
                        {
                            var tmp = list;
                            return(new List <BaseData> {
                                tmp
                            });
                        }
                        finally
                        {
                            list = null;
                            yieldedUniverseData = true;
                        }
                    }
                }
                return(Enumerable.Empty <BaseData>());
            });

            Assert.IsTrue(feed.Subscriptions.Any(x => x.IsUniverseSelectionSubscription));

            var universeSelectionHadAllData = false;

            feed.UniverseSelection += (sender, args) =>
            {
                universeSelectionHadAllData = args.Data.Count == coarseDataPointCount;
                Console.WriteLine(DateTime.UtcNow.ConvertFromUtc(TimeZones.NewYork).ToString("o") + ": Fired universe selection. Count: " + args.Data.Count);
                return(SecurityChanges.None);
            };


            ConsumeBridge(feed, TimeSpan.FromSeconds(5), ts =>
            {
            });

            Assert.IsTrue(yieldedUniverseData);
            Assert.IsTrue(universeSelectionHadAllData);
        }
Пример #14
0
        public void FineCoarseFundamentalDataGetsPipedCorrectly()
        {
            var lck = new object();
            BaseDataCollection list = null;
            var timer = new Timer(state =>
            {
                lock (state)
                {
                    list = new BaseDataCollection {
                        Symbol = CoarseFundamental.CreateUniverseSymbol(Market.USA, false)
                    };
                    list.Data.Add(new CoarseFundamental
                    {
                        Symbol = Symbols.AAPL,
                        Time   = new DateTime(2014, 04, 24)
                    });
                }
            }, lck, TimeSpan.FromSeconds(0.5), TimeSpan.FromMilliseconds(-1));

            var yieldedUniverseData = false;
            var feed = RunDataFeed(getNextTicksFunction: fdqh =>
            {
                lock (lck)
                {
                    if (list != null)
                    {
                        try
                        {
                            var tmp = list;
                            return(new List <BaseData> {
                                tmp
                            });
                        }
                        finally
                        {
                            list = null;
                            yieldedUniverseData = true;
                        }
                    }
                }
                return(Enumerable.Empty <BaseData>());
            });

            var fineWasCalled = false;

            _algorithm.AddUniverse(coarse => coarse.Take(1).Select(x => x.Symbol),
                                   fine =>
            {
                var symbol = fine.First().Symbol;
                if (symbol == Symbols.AAPL)
                {
                    fineWasCalled = true;
                }
                return(new[] { symbol });
            });

            var receivedFundamentalsData = false;

            ConsumeBridge(feed, TimeSpan.FromSeconds(2), ts =>
            {
                if (ts.UniverseData.Count > 0 &&
                    ts.UniverseData.First().Value.Data.First() is Fundamentals)
                {
                    receivedFundamentalsData = true;
                }
            }, sendUniverseData: true);

            timer.Dispose();
            Assert.IsTrue(yieldedUniverseData);
            Assert.IsTrue(receivedFundamentalsData);
            Assert.IsTrue(fineWasCalled);
        }
Пример #15
0
        public void CoarseFundamentalDataGetsPipedCorrectly()
        {
            var lck = new object();
            BaseDataCollection list = null;
            var timer = new Timer(state =>
            {
                var currentTime = DateTime.UtcNow.ConvertFromUtc(TimeZones.NewYork);
                lock (state)
                {
                    list = new BaseDataCollection {
                        Symbol = CoarseFundamental.CreateUniverseSymbol(Market.USA, false)
                    };
                    list.Data.Add(new CoarseFundamental
                    {
                        Symbol = Symbols.SPY,
                        Time   = currentTime - Time.OneDay, // hard-coded coarse period of one day
                    });
                }
            }, lck, TimeSpan.FromSeconds(0.5), TimeSpan.FromMilliseconds(-1));

            var yieldedUniverseData = false;
            var feed = RunDataFeed(getNextTicksFunction: fdqh =>
            {
                lock (lck)
                {
                    if (list != null)
                    {
                        try
                        {
                            var tmp = list;
                            return(new List <BaseData> {
                                tmp
                            });
                        }
                        finally
                        {
                            list = null;
                            yieldedUniverseData = true;
                        }
                    }
                }
                return(Enumerable.Empty <BaseData>());
            });

            _algorithm.AddUniverse(coarse => coarse.Take(10).Select(x => x.Symbol));

            var receivedCoarseData = false;

            ConsumeBridge(feed, TimeSpan.FromSeconds(2), ts =>
            {
                if (ts.UniverseData.Count > 0 &&
                    ts.UniverseData.First().Value.Data.First() is CoarseFundamental)
                {
                    receivedCoarseData = true;
                }
            }, sendUniverseData: true);

            timer.Dispose();
            Assert.IsTrue(yieldedUniverseData);
            Assert.IsTrue(receivedCoarseData);
        }
Пример #16
0
        public void HandlesCoarseFundamentalData()
        {
            Symbol symbol = CoarseFundamental.CreateUniverseSymbol(Market.USA);

            _algorithm.AddUniverse(new FuncUniverse(
                                       new SubscriptionDataConfig(typeof(CoarseFundamental), symbol, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, false, false, false),
                                       new UniverseSettings(Resolution.Second, 1, true, false, TimeSpan.Zero), SecurityInitializer.Null,
                                       coarse => coarse.Take(10).Select(x => x.Symbol)
                                       ));

            var lck = new object();
            BaseDataCollection list = null;
            const int          coarseDataPointCount = 100000;
            var timer = new Timer(state =>
            {
                var currentTime = DateTime.UtcNow.ConvertFromUtc(TimeZones.NewYork);
                Console.WriteLine(currentTime + ": timer.Elapsed");

                lock (state)
                {
                    list = new BaseDataCollection {
                        Symbol = symbol
                    };
                    list.Data.AddRange(Enumerable.Range(0, coarseDataPointCount).Select(x => new CoarseFundamental
                    {
                        Symbol = SymbolCache.GetSymbol(x.ToString()),
                        Time   = currentTime - Time.OneDay, // hard-coded coarse period of one day
                    }));
                }
            }, lck, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(500));

            bool yieldedUniverseData = false;
            var  feed = RunDataFeed(getNextTicksFunction: fdqh =>
            {
                lock (lck)
                {
                    if (list != null)
                    {
                        try
                        {
                            var tmp = list;
                            return(new List <BaseData> {
                                tmp
                            });
                        }
                        finally
                        {
                            list = null;
                            yieldedUniverseData = true;
                        }
                    }
                }
                return(Enumerable.Empty <BaseData>());
            });


            ConsumeBridge(feed, TimeSpan.FromSeconds(5), ts =>
            {
                Assert.IsTrue(feed.Subscriptions.Any(x => x.IsUniverseSelectionSubscription));
            });

            timer.Dispose();
            Assert.IsTrue(yieldedUniverseData);
        }
Пример #17
0
        /// <summary>
        /// Creates a new subscription for universe selection
        /// </summary>
        /// <param name="request">The subscription request</param>
        private Subscription CreateUniverseSubscription(SubscriptionRequest request)
        {
            Subscription subscription = null;

            // TODO : Consider moving the creating of universe subscriptions to a separate, testable class

            // grab the relevant exchange hours
            var config           = request.Universe.Configuration;
            var localEndTime     = request.EndTimeUtc.ConvertFromUtc(request.Security.Exchange.TimeZone);
            var tzOffsetProvider = new TimeZoneOffsetProvider(request.Security.Exchange.TimeZone, request.StartTimeUtc, request.EndTimeUtc);

            IEnumerator <BaseData> enumerator;

            var timeTriggered = request.Universe as ITimeTriggeredUniverse;

            if (timeTriggered != null)
            {
                Log.Trace("LiveTradingDataFeed.CreateUniverseSubscription(): Creating user defined universe: " + config.Symbol.ToString());

                // spoof a tick on the requested interval to trigger the universe selection function
                var enumeratorFactory = new TimeTriggeredUniverseSubscriptionEnumeratorFactory(timeTriggered, MarketHoursDatabase.FromDataFolder());
                enumerator = enumeratorFactory.CreateEnumerator(request, _dataProvider);

                enumerator = new FrontierAwareEnumerator(enumerator, _timeProvider, tzOffsetProvider);

                var enqueueable = new EnqueueableEnumerator <BaseData>();
                _customExchange.AddEnumerator(new EnumeratorHandler(config.Symbol, enumerator, enqueueable));
                enumerator = enqueueable;

                // Trigger universe selection when security added/removed after Initialize
                if (timeTriggered is UserDefinedUniverse)
                {
                    var userDefined = (UserDefinedUniverse)timeTriggered;
                    userDefined.CollectionChanged += (sender, args) =>
                    {
                        var items =
                            args.Action == NotifyCollectionChangedAction.Add ? args.NewItems :
                            args.Action == NotifyCollectionChangedAction.Remove ? args.OldItems : null;

                        var currentFrontierUtcTime = _frontierTimeProvider.GetUtcNow();
                        if (items == null || currentFrontierUtcTime == DateTime.MinValue)
                        {
                            return;
                        }

                        var symbol = items.OfType <Symbol>().FirstOrDefault();
                        if (symbol == null)
                        {
                            return;
                        }

                        var collection = new BaseDataCollection(currentFrontierUtcTime, symbol);
                        var changes    = _universeSelection.ApplyUniverseSelection(userDefined, currentFrontierUtcTime, collection);
                        _algorithm.OnSecuritiesChanged(changes);

                        subscription.OnNewDataAvailable();
                    };
                }
            }
            else if (config.Type == typeof(CoarseFundamental))
            {
                Log.Trace("LiveTradingDataFeed.CreateUniverseSubscription(): Creating coarse universe: " + config.Symbol.ToString());

                // we subscribe using a normalized symbol, without a random GUID,
                // since the ticker plant will send the coarse data using this symbol
                var normalizedSymbol = CoarseFundamental.CreateUniverseSymbol(config.Symbol.ID.Market, false);

                // since we're binding to the data queue exchange we'll need to let him
                // know that we expect this data
                _dataQueueHandler.Subscribe(_job, new[] { normalizedSymbol });

                var enqueable = new EnqueueableEnumerator <BaseData>();
                // We `AddDataHandler` not `Set` so we can have multiple handlers for the coarse data
                _exchange.AddDataHandler(normalizedSymbol, data =>
                {
                    enqueable.Enqueue(data);

                    subscription.OnNewDataAvailable();
                });

                enumerator = GetConfiguredFrontierAwareEnumerator(enqueable, tzOffsetProvider,
                                                                  // advance time if before 23pm or after 5am and not on Saturdays
                                                                  time => time.Hour < 23 && time.Hour > 5 && time.DayOfWeek != DayOfWeek.Saturday);
            }
            else if (request.Universe is OptionChainUniverse)
            {
                Log.Trace("LiveTradingDataFeed.CreateUniverseSubscription(): Creating option chain universe: " + config.Symbol.ToString());

                Func <SubscriptionRequest, IEnumerator <BaseData>, IEnumerator <BaseData> > configure = (subRequest, input) =>
                {
                    // we check if input enumerator is an underlying enumerator. If yes, we subscribe it to the data.
                    var aggregator = input as TradeBarBuilderEnumerator;

                    if (aggregator != null)
                    {
                        _exchange.SetDataHandler(request.Configuration.Symbol, data =>
                        {
                            aggregator.ProcessData((Tick)data);
                        });
                    }

                    var fillForwardResolution = _subscriptions.UpdateAndGetFillForwardResolution(request.Configuration);

                    return(new LiveFillForwardEnumerator(_frontierTimeProvider, input, request.Security.Exchange, fillForwardResolution, request.Configuration.ExtendedMarketHours, localEndTime, request.Configuration.Increment, request.Configuration.DataTimeZone, request.StartTimeLocal));
                };

                var symbolUniverse = _dataQueueHandler as IDataQueueUniverseProvider;
                if (symbolUniverse == null)
                {
                    throw new NotSupportedException("The DataQueueHandler does not support Options.");
                }

                var enumeratorFactory = new OptionChainUniverseSubscriptionEnumeratorFactory(configure, symbolUniverse, _timeProvider);
                enumerator = enumeratorFactory.CreateEnumerator(request, _dataProvider);

                enumerator = GetConfiguredFrontierAwareEnumerator(enumerator, tzOffsetProvider,
                                                                  time => symbolUniverse.CanAdvanceTime(config.SecurityType));
            }
            else if (request.Universe is FuturesChainUniverse)
            {
                Log.Trace("LiveTradingDataFeed.CreateUniverseSubscription(): Creating futures chain universe: " + config.Symbol.ToString());

                var symbolUniverse = _dataQueueHandler as IDataQueueUniverseProvider;
                if (symbolUniverse == null)
                {
                    throw new NotSupportedException("The DataQueueHandler does not support Futures.");
                }

                var enumeratorFactory = new FuturesChainUniverseSubscriptionEnumeratorFactory(symbolUniverse, _timeProvider);
                enumerator = enumeratorFactory.CreateEnumerator(request, _dataProvider);

                enumerator = GetConfiguredFrontierAwareEnumerator(enumerator, tzOffsetProvider,
                                                                  time => symbolUniverse.CanAdvanceTime(config.SecurityType));
            }
            else
            {
                Log.Trace("LiveTradingDataFeed.CreateUniverseSubscription(): Creating custom universe: " + config.Symbol.ToString());

                var factory         = new LiveCustomDataSubscriptionEnumeratorFactory(_timeProvider);
                var enumeratorStack = factory.CreateEnumerator(request, _dataProvider);
                enumerator = new BaseDataCollectionAggregatorEnumerator(enumeratorStack, config.Symbol, liveMode: true);

                var enqueueable = new EnqueueableEnumerator <BaseData>();
                _customExchange.AddEnumerator(new EnumeratorHandler(config.Symbol, enumerator, enqueueable));
                enumerator = enqueueable;
            }

            // create the subscription
            var subscriptionDataEnumerator = new SubscriptionDataEnumerator(request.Configuration, request.Security.Exchange.Hours, tzOffsetProvider, enumerator);

            subscription = new Subscription(request, subscriptionDataEnumerator, tzOffsetProvider);

            return(subscription);
        }
Пример #18
0
        /// <summary>
        /// Creates a new subscription for universe selection
        /// </summary>
        /// <param name="request">The subscription request</param>
        private Subscription CreateUniverseSubscription(SubscriptionRequest request)
        {
            Subscription subscription = null;

            // TODO : Consider moving the creating of universe subscriptions to a separate, testable class

            // grab the relevant exchange hours
            var config           = request.Universe.Configuration;
            var localEndTime     = request.EndTimeUtc.ConvertFromUtc(request.Security.Exchange.TimeZone);
            var tzOffsetProvider = new TimeZoneOffsetProvider(request.Security.Exchange.TimeZone, request.StartTimeUtc, request.EndTimeUtc);

            IEnumerator <BaseData> enumerator = null;

            var timeTriggered = request.Universe as ITimeTriggeredUniverse;

            if (timeTriggered != null)
            {
                Log.Trace($"LiveTradingDataFeed.CreateUniverseSubscription(): Creating user defined universe: {config.Symbol.ID}");

                // spoof a tick on the requested interval to trigger the universe selection function
                var enumeratorFactory = new TimeTriggeredUniverseSubscriptionEnumeratorFactory(timeTriggered, MarketHoursDatabase.FromDataFolder(), _frontierTimeProvider);
                enumerator = enumeratorFactory.CreateEnumerator(request, _dataProvider);

                enumerator = new FrontierAwareEnumerator(enumerator, _timeProvider, tzOffsetProvider);

                var enqueueable = new EnqueueableEnumerator <BaseData>();
                _customExchange.AddEnumerator(new EnumeratorHandler(config.Symbol, enumerator, enqueueable));
                enumerator = enqueueable;
            }
            else if (config.Type == typeof(CoarseFundamental))
            {
                Log.Trace($"LiveTradingDataFeed.CreateUniverseSubscription(): Creating coarse universe: {config.Symbol.ID}");

                // we subscribe using a normalized symbol, without a random GUID,
                // since the ticker plant will send the coarse data using this symbol
                var normalizedSymbol = CoarseFundamental.CreateUniverseSymbol(config.Symbol.ID.Market, false);

                // Will try to pull coarse data from the data folder every 30min, file with today's date.
                // If lean is started today it will trigger initial coarse universe selection
                var factory = new LiveCustomDataSubscriptionEnumeratorFactory(_timeProvider,
                                                                              // we adjust time to the previous tradable date
                                                                              time => Time.GetStartTimeForTradeBars(request.Security.Exchange.Hours, time, Time.OneDay, 1, false, config.DataTimeZone)
                                                                              );
                var enumeratorStack = factory.CreateEnumerator(request, _dataProvider);

                // aggregates each coarse data point into a single BaseDataCollection
                var aggregator = new BaseDataCollectionAggregatorEnumerator(enumeratorStack, normalizedSymbol, true);
                _customExchange.AddEnumerator(normalizedSymbol, aggregator);

                var enqueable = new EnqueueableEnumerator <BaseData>();
                _customExchange.SetDataHandler(normalizedSymbol, data =>
                {
                    var coarseData = data as BaseDataCollection;
                    enqueable.Enqueue(new BaseDataCollection(coarseData.Time, config.Symbol, coarseData.Data));
                    subscription.OnNewDataAvailable();
                });
                enumerator = GetConfiguredFrontierAwareEnumerator(enqueable, tzOffsetProvider,
                                                                  // advance time if before 23pm or after 5am and not on Saturdays
                                                                  time => time.Hour < 23 && time.Hour > 5 && time.DayOfWeek != DayOfWeek.Saturday);
            }
            else if (request.Universe is OptionChainUniverse)
            {
                Log.Trace("LiveTradingDataFeed.CreateUniverseSubscription(): Creating option chain universe: " + config.Symbol.ID);

                Func <SubscriptionRequest, IEnumerator <BaseData> > configure = (subRequest) =>
                {
                    var fillForwardResolution = _subscriptions.UpdateAndGetFillForwardResolution(subRequest.Configuration);
                    var input = _dataQueueHandler.Subscribe(subRequest.Configuration, (sender, args) => subscription.OnNewDataAvailable());
                    return(new LiveFillForwardEnumerator(_frontierTimeProvider, input, subRequest.Security.Exchange, fillForwardResolution, subRequest.Configuration.ExtendedMarketHours, localEndTime, subRequest.Configuration.Increment, subRequest.Configuration.DataTimeZone));
                };

                var symbolUniverse = _dataQueueHandler as IDataQueueUniverseProvider;
                if (symbolUniverse == null)
                {
                    throw new NotSupportedException("The DataQueueHandler does not support Options.");
                }

                var timeProvider = new PredicateTimeProvider(_timeProvider,
                                                             time => symbolUniverse.CanAdvanceTime(config.SecurityType));

                var enumeratorFactory = new OptionChainUniverseSubscriptionEnumeratorFactory(configure, symbolUniverse, timeProvider);
                enumerator = enumeratorFactory.CreateEnumerator(request, _dataProvider);

                enumerator = new FrontierAwareEnumerator(enumerator, _frontierTimeProvider, tzOffsetProvider);
            }
            else if (request.Universe is FuturesChainUniverse)
            {
                Log.Trace("LiveTradingDataFeed.CreateUniverseSubscription(): Creating futures chain universe: " + config.Symbol.ID);

                var symbolUniverse = _dataQueueHandler as IDataQueueUniverseProvider;
                if (symbolUniverse == null)
                {
                    throw new NotSupportedException("The DataQueueHandler does not support Futures.");
                }

                var timeProvider = new PredicateTimeProvider(_timeProvider,
                                                             time => symbolUniverse.CanAdvanceTime(config.SecurityType));

                var enumeratorFactory = new FuturesChainUniverseSubscriptionEnumeratorFactory(symbolUniverse, timeProvider);
                enumerator = enumeratorFactory.CreateEnumerator(request, _dataProvider);

                enumerator = new FrontierAwareEnumerator(enumerator, _frontierTimeProvider, tzOffsetProvider);
            }
            else
            {
                Log.Trace("LiveTradingDataFeed.CreateUniverseSubscription(): Creating custom universe: " + config.Symbol.ID);

                var factory         = new LiveCustomDataSubscriptionEnumeratorFactory(_timeProvider);
                var enumeratorStack = factory.CreateEnumerator(request, _dataProvider);
                enumerator = new BaseDataCollectionAggregatorEnumerator(enumeratorStack, config.Symbol, liveMode: true);

                var enqueueable = new EnqueueableEnumerator <BaseData>();
                _customExchange.AddEnumerator(new EnumeratorHandler(config.Symbol, enumerator, enqueueable));
                enumerator = enqueueable;
            }

            // create the subscription
            var subscriptionDataEnumerator = new SubscriptionDataEnumerator(request.Configuration, request.Security.Exchange.Hours, tzOffsetProvider, enumerator);

            subscription = new Subscription(request, subscriptionDataEnumerator, tzOffsetProvider);

            // send the subscription for the new symbol through to the data queuehandler
            if (_channelProvider.ShouldStreamSubscription(_job, subscription.Configuration))
            {
                _dataQueueHandler.Subscribe(request.Configuration, (sender, args) => subscription.OnNewDataAvailable());
            }

            return(subscription);
        }