public void AggregatesTicksIntoSecondBars() { var timeProvider = new ManualTimeProvider(TimeZones.NewYork); var enumerator = new TradeBarBuilderEnumerator(Time.OneSecond, TimeZones.NewYork, timeProvider); // noon new york time var currentTime = new DateTime(2015, 10, 08, 12, 0, 0); timeProvider.SetCurrentTime(currentTime); // add some ticks var ticks = new List<Tick> { new Tick(currentTime, "SPY", 199.55m, 199, 200) {Quantity = 10}, new Tick(currentTime, "SPY", 199.56m, 199.21m, 200.02m) {Quantity = 5}, new Tick(currentTime, "SPY", 199.53m, 198.77m, 199.75m) {Quantity = 20}, new Tick(currentTime, "SPY", 198.77m, 199.75m) {Quantity = 0}, new Tick(currentTime, "SPY", 199.73m, 198.77m, 199.75m) {Quantity = 20}, new Tick(currentTime, "SPY", 198.77m, 199.75m) {Quantity = 0}, }; foreach (var tick in ticks) { enumerator.ProcessData(tick); } // even though no data is here, it will still return true Assert.IsTrue(enumerator.MoveNext()); Assert.IsNull(enumerator.Current); // advance a second currentTime = currentTime.AddSeconds(1); timeProvider.SetCurrentTime(currentTime); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNotNull(enumerator.Current); // in the spirit of not duplicating the above code 5 times (OHLCV, we'll assert these ere as well) var bar = (TradeBar)enumerator.Current; Assert.AreEqual(currentTime.AddSeconds(-1), bar.Time); Assert.AreEqual(currentTime, bar.EndTime); Assert.AreEqual("SPY", bar.Symbol.Value); Assert.AreEqual(ticks.First().LastPrice, bar.Open); Assert.AreEqual(ticks.Max(x => x.LastPrice), bar.High); Assert.AreEqual(ticks.Min(x => x.LastPrice), bar.Low); Assert.AreEqual(ticks.Last().LastPrice, bar.Close); Assert.AreEqual(ticks.Sum(x => x.Quantity), bar.Volume); }
/// <summary> /// Primary entry point. /// </summary> public void Run() { IsActive = true; // we want to emit to the bridge minimally once a second since the data feed is // the heartbeat of the application, so this value will contain a second after // the last emit time, and if we pass this time, we'll emit even with no data var nextEmit = DateTime.MinValue; try { while (!_cancellationTokenSource.IsCancellationRequested) { // perform sleeps to wake up on the second? var frontier = _timeProvider.GetUtcNow(); _frontierTimeProvider.SetCurrentTime(frontier); var data = new List <KeyValuePair <Security, List <BaseData> > >(); foreach (var kvp in _subscriptions) { var subscription = kvp.Value; var cache = new KeyValuePair <Security, List <BaseData> >(subscription.Security, new List <BaseData>()); // dequeue data that is time stamped at or before this frontier while (subscription.MoveNext() && subscription.Current != null) { cache.Value.Add(subscription.Current); } // if we have data, add it to be added to the bridge if (cache.Value.Count > 0) { data.Add(cache); } // we have new universe data to select based on if (subscription.IsUniverseSelectionSubscription && cache.Value.Count > 0) { var universe = subscription.Universe; // always wait for other thread to sync up if (!Bridge.Wait(Timeout.Infinite, _cancellationTokenSource.Token)) { break; } // fire the universe selection event OnUniverseSelection(universe, subscription.Configuration, frontier, cache.Value); } } // check for cancellation if (_cancellationTokenSource.IsCancellationRequested) { return; } // emit on data or if we've elapsed a full second since last emit if (data.Count != 0 || frontier >= nextEmit) { Bridge.Add(TimeSlice.Create(frontier, _algorithm.TimeZone, _algorithm.Portfolio.CashBook, data, _changes), _cancellationTokenSource.Token); // force emitting every second nextEmit = frontier.RoundDown(Time.OneSecond).Add(Time.OneSecond); } // reset our security changes _changes = SecurityChanges.None; // take a short nap Thread.Sleep(1); } } catch (Exception err) { Log.Error(err); _algorithm.RunTimeError = err; } IsActive = false; }
public void FillsForwardOnNulls() { var reference = new DateTime(2015, 10, 08); var period = Time.OneSecond; var underlying = new List<BaseData> { // 0 seconds new TradeBar(reference, Symbols.SPY, 10, 20, 5, 15, 123456, period), // 1 seconds null, // 3 seconds new TradeBar(reference.AddSeconds(2), Symbols.SPY, 100, 200, 50, 150, 1234560, period), null, null, null, null }; var timeProvider = new ManualTimeProvider(TimeZones.NewYork); timeProvider.SetCurrentTime(reference); var exchange = new SecurityExchange(SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork)); var fillForward = new LiveFillForwardEnumerator(timeProvider, underlying.GetEnumerator(), exchange, Ref.Create(Time.OneSecond), false, Time.EndOfTime, Time.OneSecond); // first point is always emitted Assert.IsTrue(fillForward.MoveNext()); Assert.AreEqual(underlying[0], fillForward.Current); // stepping again without advancing time does nothing, but we'll still // return true as per IEnumerator contract Assert.IsTrue(fillForward.MoveNext()); Assert.IsNull(fillForward.Current); timeProvider.SetCurrentTime(reference.AddSeconds(1)); // non-null next will fill forward in between Assert.IsTrue(fillForward.MoveNext()); Assert.AreEqual(underlying[0].EndTime, fillForward.Current.Time); Assert.AreEqual(underlying[0].Value, fillForward.Current.Value); Assert.IsTrue(fillForward.Current.IsFillForward); // even without stepping the time this will advance since non-null data is ready Assert.IsTrue(fillForward.MoveNext()); Assert.AreEqual(underlying[2], fillForward.Current); // step ahead into null data territory timeProvider.SetCurrentTime(reference.AddSeconds(4)); Assert.IsTrue(fillForward.MoveNext()); Assert.AreEqual(underlying[2].Value, fillForward.Current.Value); Assert.AreEqual(timeProvider.GetUtcNow().ConvertFromUtc(TimeZones.NewYork), fillForward.Current.EndTime); Assert.IsTrue(fillForward.Current.IsFillForward); Assert.IsTrue(fillForward.MoveNext()); Assert.IsNull(fillForward.Current); timeProvider.SetCurrentTime(reference.AddSeconds(5)); Assert.IsTrue(fillForward.MoveNext()); Assert.AreEqual(underlying[2].Value, fillForward.Current.Value); Assert.AreEqual(timeProvider.GetUtcNow().ConvertFromUtc(TimeZones.NewYork), fillForward.Current.EndTime); Assert.IsTrue(fillForward.Current.IsFillForward); timeProvider.SetCurrentTime(reference.AddSeconds(6)); Assert.IsTrue(fillForward.MoveNext()); Assert.AreEqual(underlying[2].Value, fillForward.Current.Value); Assert.AreEqual(timeProvider.GetUtcNow().ConvertFromUtc(TimeZones.NewYork), fillForward.Current.EndTime); Assert.IsTrue(fillForward.Current.IsFillForward); }
public void CreatesNewBarWhenBarSizeElapses() { var timeProvider = new ManualTimeProvider(); var enumerator = new TradeBarBuilderEnumerator(Time.OneSecond, TimeZones.Utc, timeProvider); // noon new york time var startTime = new DateTime(2015, 10, 08, 12, 0, 0); timeProvider.SetCurrentTime(startTime); enumerator.ProcessData(new Tick{Time = startTime}); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNull(enumerator.Current); timeProvider.AdvanceSeconds(0.99); enumerator.ProcessData(new Tick {Time = timeProvider.GetUtcNow()}); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNull(enumerator.Current); timeProvider.SetCurrentTime(startTime.AddSeconds(1)); // the second just ticked over, so it shouldn't include this tick when we move next enumerator.ProcessData(new Tick {Time = timeProvider.GetUtcNow(), Quantity = 1}); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNotNull(enumerator.Current); Assert.AreEqual(0, ((TradeBar)enumerator.Current).Volume); }