private IDataFeed RunDataFeed(out FuncDataQueueHandler dataQueueHandler, Func <FuncDataQueueHandler, IEnumerable <BaseData> > getNextTicksFunction = null, Resolution resolution = Resolution.Second, List <string> equities = null, List <string> forex = null, List <string> crypto = null) { _algorithm.SetStartDate(_startDate); var lastTime = _manualTimeProvider.GetUtcNow(); getNextTicksFunction = getNextTicksFunction ?? (fdqh => { var time = _manualTimeProvider.GetUtcNow(); if (time == lastTime) { return(Enumerable.Empty <BaseData>()); } lastTime = time; var tickTime = lastTime.AddMinutes(-1).ConvertFromUtc(TimeZones.NewYork); return(fdqh.Subscriptions.Where(symbol => !_algorithm.UniverseManager.ContainsKey(symbol)) // its not a universe .Select(symbol => new Tick(tickTime, symbol, 1, 2) { Quantity = 1, // Symbol could not be in the Securities collections for the custom Universe tests. AlgorithmManager is in charge of adding them, and we are not executing that code here. TickType = _algorithm.Securities.ContainsKey(symbol) ? _algorithm.Securities[symbol].SubscriptionDataConfig.TickType : TickType.Trade }).ToList()); }); // job is used to send into DataQueueHandler var job = new LiveNodePacket(); // result handler is used due to dependency in SubscriptionDataReader var resultHandler = new BacktestingResultHandler(); dataQueueHandler = new FuncDataQueueHandler(getNextTicksFunction); var feed = new TestableLiveTradingDataFeed(dataQueueHandler); var mapFileProvider = new LocalDiskMapFileProvider(); var fileProvider = new DefaultDataProvider(); var marketHoursDatabase = MarketHoursDatabase.FromDataFolder(); var symbolPropertiesDataBase = SymbolPropertiesDatabase.FromDataFolder(); var securityService = new SecurityService(_algorithm.Portfolio.CashBook, marketHoursDatabase, symbolPropertiesDataBase, _algorithm); _algorithm.Securities.SetSecurityService(securityService); _dataManager = new DataManager(feed, new UniverseSelection(_algorithm, securityService), _algorithm, _algorithm.TimeKeeper, marketHoursDatabase, true); _algorithm.SubscriptionManager.SetDataManager(_dataManager); _algorithm.AddSecurities(resolution, equities, forex, crypto); _synchronizer = new TestableLiveSynchronizer(_manualTimeProvider); _synchronizer.Initialize(_algorithm, _dataManager); feed.Initialize(_algorithm, job, resultHandler, mapFileProvider, new LocalDiskFactorFileProvider(mapFileProvider), fileProvider, _dataManager, _synchronizer); _algorithm.PostInitialize(); Thread.Sleep(150); // small handicap for the data to be pumped so TimeSlices have data of all subscriptions return(feed); }
private IDataFeed RunDataFeed(out FuncDataQueueHandler dataQueueHandler, Func <FuncDataQueueHandler, IEnumerable <BaseData> > getNextTicksFunction = null, Resolution resolution = Resolution.Second, List <string> equities = null, List <string> forex = null) { _algorithm.SetStartDate(_startDate); var lastTime = _manualTimeProvider.GetUtcNow(); getNextTicksFunction = getNextTicksFunction ?? (fdqh => { var time = _manualTimeProvider.GetUtcNow(); if (time == lastTime) { return(Enumerable.Empty <BaseData>()); } lastTime = time; return(fdqh.Subscriptions.Where(symbol => !_algorithm.UniverseManager.ContainsKey(symbol)) // its not a universe .Select(symbol => new Tick(lastTime.ConvertFromUtc(TimeZones.NewYork), symbol, 1, 2) { Quantity = 1, // Symbol could not be in the Securities collections for the custom Universe tests. AlgorithmManager is in charge of adding them, and we are not executing that code here. TickType = _algorithm.Securities.ContainsKey(symbol) ? _algorithm.Securities[symbol].SubscriptionDataConfig.TickType : TickType.Trade })); }); // job is used to send into DataQueueHandler var job = new LiveNodePacket(); // result handler is used due to dependency in SubscriptionDataReader var resultHandler = new BacktestingResultHandler(); dataQueueHandler = new FuncDataQueueHandler(getNextTicksFunction); var feed = new TestableLiveTradingDataFeed(dataQueueHandler, _manualTimeProvider); var mapFileProvider = new LocalDiskMapFileProvider(); var fileProvider = new DefaultDataProvider(); var dataManager = new DataManager(feed, new UniverseSelection(feed, _algorithm), _algorithm.Settings, _algorithm.TimeKeeper); _algorithm.SubscriptionManager.SetDataManager(dataManager); _algorithm.AddSecurities(resolution, equities, forex); feed.Initialize(_algorithm, job, resultHandler, mapFileProvider, new LocalDiskFactorFileProvider(mapFileProvider), fileProvider, dataManager); _algorithm.PostInitialize(); Thread.Sleep(150); // small handicap for the data to be pumped so TimeSlices have data of all subscriptions var feedThreadStarted = new ManualResetEvent(false); Task.Factory.StartNew(() => { feedThreadStarted.Set(); feed.Run(); }); // wait for feed.Run to actually begin feedThreadStarted.WaitOne(); return(feed); }
public void OptionChainEnumerator(bool fillForward) { var job = new BacktestNodePacket(); var resultHandler = new BacktestingResultHandler(); var feed = new FileSystemDataFeed(); var algorithm = new AlgorithmStub(feed); algorithm.Transactions.SetOrderProcessor(new FakeOrderProcessor()); algorithm.SetStartDate(new DateTime(2014, 06, 06)); algorithm.SetEndDate(new DateTime(2014, 06, 09)); algorithm.SetOptionChainProvider(new BacktestingOptionChainProvider(TestGlobals.DataCacheProvider, TestGlobals.MapFileProvider)); var dataPermissionManager = new DataPermissionManager(); using var synchronizer = new Synchronizer(); synchronizer.Initialize(algorithm, algorithm.DataManager); feed.Initialize(algorithm, job, resultHandler, TestGlobals.MapFileProvider, TestGlobals.FactorFileProvider, TestGlobals.DataProvider, algorithm.DataManager, synchronizer, dataPermissionManager.DataChannelProvider); var option = algorithm.AddOption("AAPL", fillDataForward: fillForward); option.SetFilter(filter => filter.FrontMonth()); algorithm.PostInitialize(); using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); var count = 0; var lastMonth = algorithm.StartDate.Month; foreach (var timeSlice in synchronizer.StreamData(cancellationTokenSource.Token)) { if (!timeSlice.IsTimePulse && timeSlice.UniverseData?.Count > 0) { var baseDataCollection = timeSlice.UniverseData.Single().Value; if (baseDataCollection.Symbol.SecurityType == SecurityType.Option) { var nyTime = timeSlice.Time.ConvertFromUtc(algorithm.TimeZone); Assert.AreEqual(new TimeSpan(9, 30, 0).Add(TimeSpan.FromMinutes((count % 390) + 1)), nyTime.TimeOfDay, $"Failed on: {nyTime}"); Assert.IsNotNull(baseDataCollection.Underlying); // make sure the underlying time stamp is getting updated Assert.AreEqual(nyTime.TimeOfDay, baseDataCollection.Underlying.EndTime.TimeOfDay); Assert.AreEqual(nyTime.TimeOfDay, baseDataCollection.EndTime.ConvertFromUtc(algorithm.TimeZone).TimeOfDay); Assert.IsTrue(!baseDataCollection.FilteredContracts.IsNullOrEmpty()); count++; } } } feed.Exit(); algorithm.DataManager.RemoveAllSubscriptions(); // 9:30 to 15:59 -> 6.5 hours * 60 => 390 minutes * 2 days = 780 Assert.AreEqual(780, count); }
public void CoarseUniverseRotatesActiveSecurity() { var startDate = new DateTime(2014, 3, 24); var endDate = new DateTime(2014, 3, 29); var timeProvider = new ManualTimeProvider(TimeZones.NewYork); timeProvider.SetCurrentTime(startDate); var coarseTimes = new List <DateTime> { new DateTime(2014, 3, 25, 5, 0, 0, 0), new DateTime(2014, 3, 26, 5, 0, 0, 0), new DateTime(2014, 3, 27, 5, 0, 0, 0), new DateTime(2014, 3, 28, 5, 0, 0, 0), new DateTime(2014, 3, 29, 5, 0, 0, 0) }.ToHashSet(); var coarseSymbols = new List <Symbol> { Symbols.SPY, Symbols.AAPL, Symbols.MSFT }; var emitted = new AutoResetEvent(false); var dataQueueHandler = new FuncDataQueueHandler(fdqh => Enumerable.Empty <BaseData>(), timeProvider); 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, new DataChannelProvider()); var symbolIndex = 0; var coarseUniverseSelectionCount = 0; algorithm.AddUniverse( coarse => { Log.Trace($"Emitted at {algorithm.Time}. Coarse {coarse.First().Time} to {coarse.First().EndTime}"); Interlocked.Increment(ref coarseUniverseSelectionCount); emitted.Set(); // 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(5); var timer = Ref.Create <Timer>(null); timer.Value = new Timer(state => { try { var currentTime = timeProvider.GetUtcNow().ConvertFromUtc(TimeZones.NewYork); if (currentTime.Date > endDate.Date) { feed.Exit(); cancellationTokenSource.Cancel(); return; } timeProvider.Advance(TimeSpan.FromHours(1)); var time = timeProvider.GetUtcNow().ConvertFromUtc(TimeZones.NewYork); algorithm.SetDateTime(timeProvider.GetUtcNow()); if (coarseTimes.Contains(time)) { // lets wait for coarse to emit if (!emitted.WaitOne(TimeSpan.FromMilliseconds(15000))) { throw new TimeoutException($"Timeout waiting for coarse to emit at {time}"); } } var activeSecuritiesCount = algorithm.ActiveSecurities.Count; Assert.That(activeSecuritiesCount <= 1); // restart the timer timer.Value.Change(timerInterval, Timeout.InfiniteTimeSpan); } catch (Exception exception) { Log.Error(exception); exceptionThrown = exception; feed.Exit(); cancellationTokenSource.Cancel(); } }, null, timerInterval, Timeout.InfiniteTimeSpan); foreach (var _ in synchronizer.StreamData(cancellationTokenSource.Token)) { } timer.Value.DisposeSafely(); algorithm.DataManager.RemoveAllSubscriptions(); dataQueueHandler.DisposeSafely(); synchronizer.DisposeSafely(); emitted.DisposeSafely(); if (exceptionThrown != null) { throw new Exception("Exception in timer: ", exceptionThrown); } Assert.AreEqual(coarseTimes.Count, coarseUniverseSelectionCount, message: "coarseUniverseSelectionCount"); }
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); }
public void FutureChainEnumerator(bool fillForward) { var job = new BacktestNodePacket(); var resultHandler = new BacktestingResultHandler(); var feed = new FileSystemDataFeed(); var algorithm = new AlgorithmStub(feed); algorithm.Transactions.SetOrderProcessor(new FakeOrderProcessor()); algorithm.SetStartDate(new DateTime(2013, 10, 07)); algorithm.SetEndDate(new DateTime(2013, 10, 08)); algorithm.SetFutureChainProvider(new BacktestingFutureChainProvider(TestGlobals.DataCacheProvider)); var dataPermissionManager = new DataPermissionManager(); using var synchronizer = new Synchronizer(); synchronizer.Initialize(algorithm, algorithm.DataManager); feed.Initialize(algorithm, job, resultHandler, TestGlobals.MapFileProvider, TestGlobals.FactorFileProvider, TestGlobals.DataProvider, algorithm.DataManager, synchronizer, dataPermissionManager.DataChannelProvider); var future = algorithm.AddFuture("ES", fillDataForward: fillForward); future.SetFilter(0, 300); algorithm.PostInitialize(); using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); var count = 0L; var lastMonth = algorithm.StartDate.Month; foreach (var timeSlice in synchronizer.StreamData(cancellationTokenSource.Token)) { if (!timeSlice.IsTimePulse && timeSlice.UniverseData?.Count > 0) { var nyTime = timeSlice.Time.ConvertFromUtc(algorithm.TimeZone); var currentExpectedTime = new TimeSpan(0, 0, 0).Add(TimeSpan.FromMinutes(count % (24 * 60))); while (!future.Exchange.DateTimeIsOpen(nyTime.Date.Add(currentExpectedTime).AddMinutes(-1))) { // skip closed market times currentExpectedTime = new TimeSpan(0, 0, 0).Add(TimeSpan.FromMinutes(++count % (24 * 60))); } var universeData = timeSlice.UniverseData.OrderBy(kvp => kvp.Key.Configuration.Symbol).ToList(); var chainData = universeData[0].Value; Log.Trace($"{nyTime}. Count: {count}. Universe Data Count {universeData.Count}"); Assert.AreEqual(currentExpectedTime, nyTime.TimeOfDay, $"Failed on: {nyTime}. Count: {count}"); Assert.IsTrue(timeSlice.UniverseData.All(kvp => kvp.Value.EndTime.ConvertFromUtc(algorithm.TimeZone).TimeOfDay == nyTime.TimeOfDay)); if (chainData.FilteredContracts.IsNullOrEmpty()) { Assert.AreEqual(new DateTime(2013, 10, 09), nyTime, $"Unexpected chain FilteredContracts was empty on {nyTime}"); } if (universeData.Count == 1) { // the chain Assert.IsTrue(universeData.Any(kvp => kvp.Key.Configuration.Symbol == future.Symbol)); } else { // we have 2 universe data, the chain and the continuous future Assert.AreEqual(2, universeData.Count); Assert.IsTrue(universeData.All(kvp => kvp.Key.Configuration.Symbol.SecurityType == SecurityType.Future)); Assert.IsTrue(universeData.Any(kvp => kvp.Key.Configuration.Symbol == future.Symbol)); Assert.IsTrue(universeData.Any(kvp => kvp.Key.Configuration.Symbol.ID.Symbol.Contains("CONTINUOUS", StringComparison.InvariantCultureIgnoreCase))); var continuousData = universeData[1].Value; Assert.AreEqual(currentExpectedTime, nyTime.TimeOfDay, $"Failed on: {nyTime}"); Assert.IsTrue(!chainData.FilteredContracts.IsNullOrEmpty()); } count++; } } feed.Exit(); algorithm.DataManager.RemoveAllSubscriptions(); // 2 days worth of minute data Assert.AreEqual(24 * 2 * 60 + 1, count); }