diff --git a/Common/Data/Consolidators/BaseTimelessConsolidator.cs b/Common/Data/Consolidators/BaseTimelessConsolidator.cs index 18d9e9e91d98..53dd0905280f 100644 --- a/Common/Data/Consolidators/BaseTimelessConsolidator.cs +++ b/Common/Data/Consolidators/BaseTimelessConsolidator.cs @@ -199,6 +199,15 @@ public virtual void Dispose() DataConsolidatedHandler = null; } + /// + /// Resets the consolidator + /// + public virtual void Reset() + { + Consolidated = null; + CurrentBar = default(T); + } + /// /// Scans this consolidator to see if it should emit a bar due to time passing /// diff --git a/Common/Data/Consolidators/ClassicRenkoConsolidator.cs b/Common/Data/Consolidators/ClassicRenkoConsolidator.cs index fc5626e64e6c..4aa2a099e1e6 100644 --- a/Common/Data/Consolidators/ClassicRenkoConsolidator.cs +++ b/Common/Data/Consolidators/ClassicRenkoConsolidator.cs @@ -119,6 +119,15 @@ public ClassicRenkoConsolidator(decimal barSize, _evenBars = evenBars; } + /// + /// Resets the ClassicRenkoConsolidator + /// + public override void Reset() + { + base.Reset(); + _lastCloseValue = null; + } + /// /// Updates the current RangeBar being created with the given data. /// Additionally, if it's the case, it consolidates the current RangeBar diff --git a/Common/Data/Consolidators/DataConsolidator.cs b/Common/Data/Consolidators/DataConsolidator.cs index a4c42cb845d8..8f5f57e46169 100644 --- a/Common/Data/Consolidators/DataConsolidator.cs +++ b/Common/Data/Consolidators/DataConsolidator.cs @@ -58,7 +58,7 @@ public void Update(IBaseData data) /// public IBaseData Consolidated { - get; private set; + get; protected set; } /// @@ -108,6 +108,14 @@ protected virtual void OnDataConsolidated(IBaseData consolidated) Consolidated = consolidated; } + /// + /// Resets the consolidator + /// + public virtual void Reset() + { + Consolidated = null; + } + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// 2 public void Dispose() diff --git a/Common/Data/Consolidators/IDataConsolidator.cs b/Common/Data/Consolidators/IDataConsolidator.cs index 95d41fcf30a2..e982a20129bf 100644 --- a/Common/Data/Consolidators/IDataConsolidator.cs +++ b/Common/Data/Consolidators/IDataConsolidator.cs @@ -65,6 +65,11 @@ public interface IDataConsolidator : IDisposable /// The current time in the local time zone (same as ) void Scan(DateTime currentLocalTime); + /// + /// Resets the consolidator + /// + void Reset(); + /// /// Event handler that fires when a new piece of data is produced /// diff --git a/Common/Data/Consolidators/IdentityDataConsolidator.cs b/Common/Data/Consolidators/IdentityDataConsolidator.cs index d482dc978baa..65dc1ea81db6 100644 --- a/Common/Data/Consolidators/IdentityDataConsolidator.cs +++ b/Common/Data/Consolidators/IdentityDataConsolidator.cs @@ -66,5 +66,14 @@ public override void Update(T data) public override void Scan(DateTime currentLocalTime) { } + + /// + /// Resets the consolidator + /// + public override void Reset() + { + base.Reset(); + _last = default(T); + } } } \ No newline at end of file diff --git a/Common/Data/Consolidators/MarketHourAwareConsolidator.cs b/Common/Data/Consolidators/MarketHourAwareConsolidator.cs index 69d04d5429c1..8fa437885378 100644 --- a/Common/Data/Consolidators/MarketHourAwareConsolidator.cs +++ b/Common/Data/Consolidators/MarketHourAwareConsolidator.cs @@ -156,6 +156,17 @@ public void Dispose() Consolidator.Dispose(); } + /// + /// Resets the consolidator + /// + public void Reset() + { + _useStrictEndTime = false; + ExchangeHours = null; + DataTimeZone = null; + Consolidator.Reset(); + } + /// /// Perform late initialization based on the datas symbol /// diff --git a/Common/Data/Consolidators/PeriodCountConsolidatorBase.cs b/Common/Data/Consolidators/PeriodCountConsolidatorBase.cs index 1b2477d7fa08..386d6a0ad310 100644 --- a/Common/Data/Consolidators/PeriodCountConsolidatorBase.cs +++ b/Common/Data/Consolidators/PeriodCountConsolidatorBase.cs @@ -255,6 +255,20 @@ public override void Scan(DateTime currentLocalTime) } } + /// + /// Resets the consolidator + /// + public override void Reset() + { + base.Reset(); + _securityIdentifier = null; + _securityIdentifierIsSet = false; + _currentCount = 0; + _workingBar = null; + _lastEmit = null; + _validateTimeSpan = false; + } + /// /// Returns true if this consolidator is time-based, false otherwise /// diff --git a/Common/Data/Consolidators/RangeConsolidator.cs b/Common/Data/Consolidators/RangeConsolidator.cs index 0ebd5b5aa6c2..c178e15b3e63 100644 --- a/Common/Data/Consolidators/RangeConsolidator.cs +++ b/Common/Data/Consolidators/RangeConsolidator.cs @@ -96,6 +96,17 @@ public RangeConsolidator(int range, _firstTick = true; } + /// + /// Resets the consolidator + /// + public override void Reset() + { + base.Reset(); + _firstTick = true; + _minimumPriceVariation = 0m; + RangeSize = 0m; + } + /// /// Updates the current RangeBar being created with the given data. /// Additionally, if it's the case, it consolidates the current RangeBar diff --git a/Common/Data/Consolidators/RenkoConsolidator.cs b/Common/Data/Consolidators/RenkoConsolidator.cs index bfb37c4eb6e4..b2ddf9d8fba9 100644 --- a/Common/Data/Consolidators/RenkoConsolidator.cs +++ b/Common/Data/Consolidators/RenkoConsolidator.cs @@ -241,6 +241,23 @@ public void Dispose() _dataConsolidatedHandler = null; } + /// + /// Resets the consolidator + /// + public void Reset() + { + _firstTick = true; + _lastWicko = null; + _currentBar = null; + _consolidated = null; + CloseOn = default; + CloseRate = default; + HighRate = default; + LowRate = default; + OpenOn = default; + OpenRate = default; + } + /// /// Event invocator for the DataConsolidated event. This should be invoked /// by derived classes when they have consolidated a new piece of data. diff --git a/Common/Data/Consolidators/SequentialConsolidator.cs b/Common/Data/Consolidators/SequentialConsolidator.cs index e5f5ef999d1a..6ce0fccd9e49 100644 --- a/Common/Data/Consolidators/SequentialConsolidator.cs +++ b/Common/Data/Consolidators/SequentialConsolidator.cs @@ -141,5 +141,14 @@ public void Dispose() Second.Dispose(); DataConsolidated = null; } + + /// + /// Resets the consolidator + /// + public void Reset() + { + First.Reset(); + Second.Reset(); + } } } diff --git a/Common/Data/Consolidators/VolumeRenkoConsolidator.cs b/Common/Data/Consolidators/VolumeRenkoConsolidator.cs index de9a74fab7fc..8f964b9f3d29 100644 --- a/Common/Data/Consolidators/VolumeRenkoConsolidator.cs +++ b/Common/Data/Consolidators/VolumeRenkoConsolidator.cs @@ -113,6 +113,15 @@ public override void Scan(DateTime currentLocalTime) { } + /// + /// Resets the consolidator + /// + public override void Reset() + { + base.Reset(); + _currentBar = null; + } + /// /// Event invocator for the DataConsolidated event. This should be invoked /// by derived classes when they have consolidated a new piece of data. diff --git a/Common/Python/DataConsolidatorPythonWrapper.cs b/Common/Python/DataConsolidatorPythonWrapper.cs index 439da81de6dd..c2264726e217 100644 --- a/Common/Python/DataConsolidatorPythonWrapper.cs +++ b/Common/Python/DataConsolidatorPythonWrapper.cs @@ -109,5 +109,13 @@ public void Update(IBaseData data) public void Dispose() { } + + /// + /// Resets the consolidator + /// + public void Reset() + { + InvokeMethod(nameof(Reset)); + } } } diff --git a/Common/Python/PythonConsolidator.cs b/Common/Python/PythonConsolidator.cs index 7b7c40130593..c2344acbebbe 100644 --- a/Common/Python/PythonConsolidator.cs +++ b/Common/Python/PythonConsolidator.cs @@ -38,5 +38,12 @@ public void OnDataConsolidated(PyObject consolidator, IBaseData data) { DataConsolidated?.Invoke(consolidator, data); } + + /// + /// Resets the consolidator + /// + public virtual void Reset() + { + } } } diff --git a/Tests/Common/Data/BaseConsolidatorTests.cs b/Tests/Common/Data/BaseConsolidatorTests.cs new file mode 100644 index 000000000000..0d0038c14064 --- /dev/null +++ b/Tests/Common/Data/BaseConsolidatorTests.cs @@ -0,0 +1,109 @@ +/* + * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. + * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using Python.Runtime; +using QuantConnect.Data; +using QuantConnect.Data.Consolidators; +using QuantConnect.Data.Market; +using QuantConnect.Indicators; + +namespace QuantConnect.Tests.Common.Data +{ + [TestFixture] + public abstract class BaseConsolidatorTests + { + protected abstract IDataConsolidator CreateConsolidator(); + + protected virtual void AssertConsolidator(IDataConsolidator consolidator) + { + Assert.IsNull(consolidator.Consolidated); + } + + protected virtual Func AssertConsolidatedValues => (first, second) => + { + Assert.AreEqual(first.Value, second.Value); + Assert.AreEqual(first.Price, second.Price); + Assert.AreEqual(first.DataType, second.DataType); + Assert.AreEqual(first.Symbol, second.Symbol); + Assert.AreEqual(first.EndTime, second.EndTime); + return true; + }; + + protected virtual dynamic GetTestValues() + { + var time = new DateTime(2016, 1, 1); + return new List() + { + new IndicatorDataPoint(time, 1.38687m), + new IndicatorDataPoint(time.AddSeconds(1), 1.38687m), + new IndicatorDataPoint(time.AddSeconds(2), 1.38688m), + new IndicatorDataPoint(time.AddSeconds(3), 1.38687m), + new IndicatorDataPoint(time.AddSeconds(4), 1.38686m), + new IndicatorDataPoint(time.AddSeconds(5), 1.38685m), + new IndicatorDataPoint(time.AddSeconds(6), 1.38683m), + new IndicatorDataPoint(time.AddSeconds(7), 1.38682m), + new IndicatorDataPoint(time.AddSeconds(8), 1.38682m), + new IndicatorDataPoint(time.AddSeconds(9), 1.38684m), + new IndicatorDataPoint(time.AddSeconds(10), 1.38682m), + new IndicatorDataPoint(time.AddSeconds(11), 1.38680m), + new IndicatorDataPoint(time.AddSeconds(12), 1.38681m), + new IndicatorDataPoint(time.AddSeconds(13), 1.38686m), + new IndicatorDataPoint(time.AddSeconds(14), 1.38688m), + }; + } + + [Test] + public void ResetWorksAsExpected() + { + // Test Renko bar consistency amongst three consolidators starting at different times + + var time = new DateTime(2016, 1, 1); + var testValues = GetTestValues(); + + var consolidatedBarsBefore = new List(); + var consolidator = CreateConsolidator(); + foreach (var data in testValues) + { + consolidator.Update(data); + if (consolidator.Consolidated != null) + { + consolidatedBarsBefore.Add(consolidator.Consolidated); + } + } + + consolidator.Reset(); + AssertConsolidator(consolidator); + + var consolidatedBarsAfter = new List(); + foreach (var data in testValues) + { + consolidator.Update(data); + if (consolidator.Consolidated != null) + { + consolidatedBarsAfter.Add(consolidator.Consolidated); + } + } + + Assert.AreEqual(consolidatedBarsBefore.Count, consolidatedBarsAfter.Count); + consolidatedBarsBefore.Zip(consolidatedBarsAfter, AssertConsolidatedValues); + consolidator.Dispose(); + } + } +} diff --git a/Tests/Common/Data/BaseDataConsolidatorTests.cs b/Tests/Common/Data/BaseDataConsolidatorTests.cs index f85ae7a417a7..86643979e520 100644 --- a/Tests/Common/Data/BaseDataConsolidatorTests.cs +++ b/Tests/Common/Data/BaseDataConsolidatorTests.cs @@ -15,7 +15,9 @@ */ using System; +using System.Collections.Generic; using NUnit.Framework; +using QuantConnect.Data; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; using QuantConnect.Indicators; @@ -23,7 +25,7 @@ namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class BaseDataConsolidatorTests + public class BaseDataConsolidatorTests: BaseConsolidatorTests { [Test] public void AggregatesTickToNewTradeBarProperly() @@ -331,5 +333,29 @@ public void RegisterIndicator(IndicatorBase indicator, IData indicator.Update(consolidated.EndTime, consolidated.Value); }; } + + protected override IDataConsolidator CreateConsolidator() + { + return new BaseDataConsolidator(4); + } + + protected override IEnumerable GetTestValues() + { + var time = new DateTime(2015, 04, 13, 8, 31, 0); + return new List() + { + new TradeBar(){ Time = time, Period = Time.OneMinute, Symbol = Symbols.SPY, High = 10 }, + new TradeBar(){ Time = time.AddMinutes(1), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 12, Close = 5 }, + new TradeBar(){ Time = time.AddMinutes(2), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 10, Close = 7 }, + new TradeBar(){ Time = time.AddMinutes(3), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 5, Close = 2 }, + new TradeBar(){ Time = time.AddMinutes(4), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 15 , Close = 2 }, + new TradeBar(){ Time = time.AddMinutes(5), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 20 , Close = 2 }, + new TradeBar(){ Time = time.AddMinutes(6), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 18 , Close = 8 }, + new TradeBar(){ Time = time.AddMinutes(7), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 12 , Close = 4 }, + new TradeBar(){ Time = time.AddMinutes(8), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 25 , Close = 5 }, + new TradeBar(){ Time = time.AddMinutes(9), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 30 , Close = 4 }, + new TradeBar(){ Time = time.AddMinutes(10), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 26 , Close = 7 }, + }; + } } } diff --git a/Tests/Common/Data/ClassicRangeConsolidatorTests.cs b/Tests/Common/Data/ClassicRangeConsolidatorTests.cs index 8b905c49013e..0d94f8b3c9c3 100644 --- a/Tests/Common/Data/ClassicRangeConsolidatorTests.cs +++ b/Tests/Common/Data/ClassicRangeConsolidatorTests.cs @@ -23,7 +23,7 @@ namespace QuantConnect.Tests.Common.Data { public class ClassicRangeConsolidatorTests : RangeConsolidatorTests { - protected override RangeConsolidator CreateConsolidator(int range) + protected override RangeConsolidator CreateRangeConsolidator(int range) { return new ClassicRangeConsolidator(range, x => x.Value, x => 10m); } diff --git a/Tests/Common/Data/ClassicRenkoConsolidatorTests.cs b/Tests/Common/Data/ClassicRenkoConsolidatorTests.cs index 4837d7681140..5a8d048e55eb 100644 --- a/Tests/Common/Data/ClassicRenkoConsolidatorTests.cs +++ b/Tests/Common/Data/ClassicRenkoConsolidatorTests.cs @@ -24,7 +24,7 @@ namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class ClassicRenkoConsolidatorTests + public class ClassicRenkoConsolidatorTests: BaseConsolidatorTests { [Test] public void ClassicOutputTypeIsRenkoBar() @@ -279,5 +279,10 @@ def getConsolidator(): } } } + + protected override IDataConsolidator CreateConsolidator() + { + return new ClassicRenkoConsolidator(0.0001m); + } } } diff --git a/Tests/Common/Data/ConsolidatorWrapperTests.cs b/Tests/Common/Data/ConsolidatorWrapperTests.cs index d41341c03a9c..b130fe040b67 100644 --- a/Tests/Common/Data/ConsolidatorWrapperTests.cs +++ b/Tests/Common/Data/ConsolidatorWrapperTests.cs @@ -192,6 +192,10 @@ public void Consolidate(BaseData dataPoint) Consolidated = dataPoint; DataConsolidated?.Invoke(this, dataPoint); } + + public void Reset() + { + } } } } diff --git a/Tests/Common/Data/DynamicDataConsolidatorTests.cs b/Tests/Common/Data/DynamicDataConsolidatorTests.cs index bda6abd14da9..1f48f4046f75 100644 --- a/Tests/Common/Data/DynamicDataConsolidatorTests.cs +++ b/Tests/Common/Data/DynamicDataConsolidatorTests.cs @@ -14,6 +14,7 @@ */ using System; +using System.Collections.Generic; using NUnit.Framework; using QuantConnect.Data; using QuantConnect.Data.Consolidators; @@ -22,7 +23,7 @@ namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class DynamicDataConsolidatorTests + public class DynamicDataConsolidatorTests: BaseConsolidatorTests { [Test] public void AggregatesTimeValuePairsWithOutVolumeProperly() @@ -248,6 +249,53 @@ public void AggregatesTradeBarsWithOutVolumeProperly() Assert.AreEqual(0, consolidated.Volume); } + protected override IEnumerable GetTestValues() + { + var reference = DateTime.Today; + dynamic bar1 = new CustomData(); + bar1.Symbol = Symbols.SPY; + bar1.Time = reference; + bar1.Open = 10; + bar1.High = 100m; + bar1.Low = 1m; + bar1.Close = 50m; + + dynamic bar2 = new CustomData(); + bar2.Symbol = Symbols.SPY; + bar2.Time = reference.AddHours(1); + bar2.Open = 50m; + bar2.High = 123m; + bar2.Low = 35m; + bar2.Close = 75m; + + dynamic bar3 = new CustomData(); + bar3.Symbol = Symbols.SPY; + bar3.Time = reference.AddHours(2); + bar3.Open = 75m; + bar3.High = 100m; + bar3.Low = 50m; + bar3.Close = 83m; + + return new List() + { + bar1, + bar2, + bar3, + bar1, + bar3, + bar2, + bar1, + bar1, + bar3, + bar1 + }; + } + + protected override IDataConsolidator CreateConsolidator() + { + return new DynamicDataConsolidator(3); + } + private class CustomData : DynamicData { public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode) diff --git a/Tests/Common/Data/IdentityDataConsolidatorTests.cs b/Tests/Common/Data/IdentityDataConsolidatorTests.cs index f559c7981d9a..ccc9fd5f53fd 100644 --- a/Tests/Common/Data/IdentityDataConsolidatorTests.cs +++ b/Tests/Common/Data/IdentityDataConsolidatorTests.cs @@ -17,11 +17,12 @@ using NUnit.Framework; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; +using QuantConnect.Indicators; namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class IdentityDataConsolidatorTests + public class IdentityDataConsolidatorTests: BaseConsolidatorTests { [Test] public void ThrowsOnDataOfWrongType() @@ -92,5 +93,10 @@ public void AcceptsTickDataWithSameTimestamps() Assert.AreEqual(2, count); } + + protected override IDataConsolidator CreateConsolidator() + { + return new IdentityDataConsolidator(); + } } } diff --git a/Tests/Common/Data/MarketHourAwareConsolidatorTests.cs b/Tests/Common/Data/MarketHourAwareConsolidatorTests.cs index 78c40967ecfc..14dc97c84367 100644 --- a/Tests/Common/Data/MarketHourAwareConsolidatorTests.cs +++ b/Tests/Common/Data/MarketHourAwareConsolidatorTests.cs @@ -18,11 +18,14 @@ using NUnit.Framework; using QuantConnect.Data.Market; using QuantConnect.Data.Common; +using QuantConnect.Data.Consolidators; +using System.Collections.Generic; +using QuantConnect.Data; namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class MarketHourAwareConsolidatorTests + public class MarketHourAwareConsolidatorTests: BaseConsolidatorTests { [Test] public void MarketAlwaysOpen() @@ -201,6 +204,30 @@ public void MarketHoursRespected() Assert.AreEqual(1, latestBar.Low); } + protected override IDataConsolidator CreateConsolidator() + { + return new MarketHourAwareConsolidator(true, Resolution.Hour, typeof(TradeBar), TickType.Trade, false); + } + + protected override IEnumerable GetTestValues() + { + var time = new DateTime(2015, 04, 13, 8, 31, 0); + return new List() + { + new TradeBar(){ Time = time, Period = Time.OneMinute, Symbol = Symbols.SPY, High = 10 }, + new TradeBar(){ Time = time.AddMinutes(1), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 12 }, + new TradeBar(){ Time = time.AddMinutes(2), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 10 }, + new TradeBar(){ Time = time.AddMinutes(3), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 5 }, + new TradeBar(){ Time = time.AddMinutes(4), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 15 }, + new TradeBar(){ Time = time.AddMinutes(5), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 20 }, + new TradeBar(){ Time = time.AddMinutes(6), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 18 }, + new TradeBar(){ Time = time.AddMinutes(7), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 12 }, + new TradeBar(){ Time = time.AddMinutes(8), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 25 }, + new TradeBar(){ Time = time.AddMinutes(9), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 30 }, + new TradeBar(){ Time = time.AddMinutes(10), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 26 }, + }; + } + private class MarketHourAwareConsolidatorTest : MarketHourAwareConsolidator { public MarketHourAwareConsolidatorTest(Resolution resolution, Type dataType, TickType tickType, bool extendedMarketHours) diff --git a/Tests/Common/Data/QuoteBarConsolidatorTests.cs b/Tests/Common/Data/QuoteBarConsolidatorTests.cs index def1b5607e6b..e19821250d8b 100644 --- a/Tests/Common/Data/QuoteBarConsolidatorTests.cs +++ b/Tests/Common/Data/QuoteBarConsolidatorTests.cs @@ -14,14 +14,16 @@ */ using System; +using System.Collections.Generic; using NUnit.Framework; using QuantConnect.Data.Market; using QuantConnect.Data.Consolidators; +using QuantConnect.Data; namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class QuoteBarConsolidatorTests + public class QuoteBarConsolidatorTests: BaseConsolidatorTests { [Test] public void ThrowsWhenPeriodIsSmallerThanDataPeriod() @@ -452,5 +454,25 @@ public void LastCloseAndCurrentOpenPriceShouldBeSameConsolidatedOnTimeSpan() // Ask Assert.AreEqual(quoteBar.Ask.Open, bar2.Ask.Close); } + + protected override IDataConsolidator CreateConsolidator() + { + return new QuoteBarConsolidator(2); + } + + protected override IEnumerable GetTestValues() + { + var time = DateTime.Today; + return new List() + { + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(1, 2, 0.5m, 1.75m), Ask = new Bar(2.2m, 4.4m, 3.3m, 3.3m), LastBidSize = 10, LastAskSize = 0 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(0, 4, 0.4m, 3.75m), Ask = new Bar(2.3m, 9.4m, 2.3m, 4.5m), LastBidSize = 5, LastAskSize = 4 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(2, 2, 0.9m, 1.45m), Ask = new Bar(2.7m, 8.4m, 3.6m, 3.6m), LastBidSize = 8, LastAskSize = 4 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(2, 6, 2.5m, 5.55m), Ask = new Bar(3.2m, 6.4m, 2.3m, 5.3m), LastBidSize = 9, LastAskSize = 4 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(1, 2, 1.5m, 0.34m), Ask = new Bar(3.6m, 9.4m, 3.7m, 3.8m), LastBidSize = 5, LastAskSize = 8 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(1, 2, 1.1m, 0.75m), Ask = new Bar(3.8m, 8.4m, 7.3m, 5.3m), LastBidSize = 9, LastAskSize = 5 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(3, 3, 2.2m, 1.12m), Ask = new Bar(4.5m, 7.2m, 7.1m, 6.1m), LastBidSize = 6, LastAskSize = 3 }, + }; + } } } diff --git a/Tests/Common/Data/RangeConsolidatorTests.cs b/Tests/Common/Data/RangeConsolidatorTests.cs index 12a87777eb72..1e92e0a7de74 100644 --- a/Tests/Common/Data/RangeConsolidatorTests.cs +++ b/Tests/Common/Data/RangeConsolidatorTests.cs @@ -20,16 +20,17 @@ using System; using System.Collections.Generic; using System.Linq; +using QuantConnect.Data; namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class RangeConsolidatorTests + public class RangeConsolidatorTests: BaseConsolidatorTests { [Test] public void RangeConsolidatorReturnsExpectedValues() { - using var consolidator = CreateConsolidator(100); + using var consolidator = CreateRangeConsolidator(100); var testValues = new List() { 90m, 94.5m, 94m, 89.5m, 89m, 90.5m, 90m, 91.5m, 90m, 90.5m, 92.5m }; #pragma warning disable CS0618 var returnedBars = UpdateConsolidator(consolidator, testValues, "IBM"); @@ -68,7 +69,7 @@ public void RangeConsolidatorReturnsExpectedValues() [TestCaseSource(nameof(PriceGapBehaviorIsTheExpectedOneTestCases))] public virtual void PriceGapBehaviorIsTheExpectedOne(Symbol symbol, double minimumPriceVariation, double range) { - using var consolidator = CreateConsolidator((int)range); + using var consolidator = CreateRangeConsolidator((int)range); var testValues = new List() { 90m, 94.5m, 94m, 89.5m, 89m, 90.5m, 90m, 91.5m, 90m, 90.5m, 92.5m }; var returnedBars = UpdateConsolidator(consolidator, testValues, symbol); RangeBar lastRangeBar = null; @@ -86,7 +87,7 @@ public virtual void PriceGapBehaviorIsTheExpectedOne(Symbol symbol, double minim [TestCaseSource(nameof(ConsolidatorCreatesExpectedBarsTestCases))] public virtual void ConsolidatorCreatesExpectedBarsInDifferentScenarios(List testValues, RangeBar[] expectedBars) { - using var consolidator = CreateConsolidator(100); + using var consolidator = CreateRangeConsolidator(100); var returnedBars = UpdateConsolidator(consolidator, testValues, Symbols.IBM); Assert.IsNotEmpty(returnedBars); @@ -107,7 +108,7 @@ public virtual void ConsolidatorCreatesExpectedBarsInDifferentScenarios(List(testValues.Select(x => (decimal)x)), Symbols.IBM); Assert.AreEqual(1, returnedBars.Count); @@ -118,7 +119,7 @@ public void ConsolidatorUpdatesTheVolumeOfTheBarsAsExpected(double[] testValues, Assert.AreEqual(expectedBar[4], returnedBars[0].Volume); } - protected virtual RangeConsolidator CreateConsolidator(int range) + protected virtual RangeConsolidator CreateRangeConsolidator(int range) { return new RangeConsolidator(range, x => x.Value, x => 10m); } @@ -211,5 +212,40 @@ protected virtual decimal[][] GetRangeConsolidatorExpectedValues() new decimal[]{ 91.01m, 91.01m, 92.01m, 92.01m, 0m } }; } + + protected override IDataConsolidator CreateConsolidator() + { + return new RangeConsolidator(100); + } + + protected override void AssertConsolidator(IDataConsolidator consolidator) + { + base.AssertConsolidator(consolidator); + Assert.AreEqual(0, ((RangeConsolidator)consolidator).RangeSize); + } + + protected override IEnumerable GetTestValues() + { + var testValues = new List() { 90m, 94.5m, 94m, 89.5m, 89m, 90.5m, 90m, 91.5m, 90m, 90.5m, 92.5m }; + var time = new DateTime(2016, 1, 1); + return new List() + { + new IndicatorDataPoint(time, 90m), + new IndicatorDataPoint(time.AddSeconds(1), 94.5m), + new IndicatorDataPoint(time.AddSeconds(2), 94m), + new IndicatorDataPoint(time.AddSeconds(3), 89.5m), + new IndicatorDataPoint(time.AddSeconds(4), 89m), + new IndicatorDataPoint(time.AddSeconds(5), 90.5m), + new IndicatorDataPoint(time.AddSeconds(6), 90m), + new IndicatorDataPoint(time.AddSeconds(7), 91.5m), + new IndicatorDataPoint(time.AddSeconds(8), 90m), + new IndicatorDataPoint(time.AddSeconds(9), 90.5m), + new IndicatorDataPoint(time.AddSeconds(10), 92.5m), + new IndicatorDataPoint(time.AddSeconds(11), 94.5m), + new IndicatorDataPoint(time.AddSeconds(12), 94m), + new IndicatorDataPoint(time.AddSeconds(13), 89.5m), + new IndicatorDataPoint(time.AddSeconds(14), 89m), + }; + } } } diff --git a/Tests/Common/Data/RenkoConsolidatorTests.cs b/Tests/Common/Data/RenkoConsolidatorTests.cs index 13b827a2718d..41f8c9920586 100644 --- a/Tests/Common/Data/RenkoConsolidatorTests.cs +++ b/Tests/Common/Data/RenkoConsolidatorTests.cs @@ -15,6 +15,7 @@ using System; using NUnit.Framework; +using QuantConnect.Data; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; using QuantConnect.Indicators; @@ -24,7 +25,7 @@ namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class RenkoConsolidatorTests + public class RenkoConsolidatorTests: BaseConsolidatorTests { [TestCase(0)] [TestCase(-1)] @@ -713,6 +714,46 @@ public void GetClosestMultipleFailsWhenBarSizeIsLessThanZero(double barSize) Assert.AreEqual("BarSize must be strictly greater than zero", message.Message); } + protected override IDataConsolidator CreateConsolidator() + { + return new TestRenkoConsolidator(1m); + } + + protected override void AssertConsolidator(IDataConsolidator consolidator) + { + base.AssertConsolidator(consolidator); + var renkoConsolidator = consolidator as TestRenkoConsolidator; + var renkoBar = renkoConsolidator.OpenRenko(); + + Assert.AreEqual(0, renkoBar.Open); + Assert.AreEqual(0, renkoBar.Close); + Assert.AreEqual(0, renkoBar.High); + Assert.AreEqual(0, renkoBar.Low); + Assert.AreEqual(default(DateTime), renkoBar.Start); + Assert.AreEqual(default(DateTime), renkoBar.End); + } + + protected override IEnumerable GetTestValues() + { + var time = new DateTime(2016, 3, 1); + return new List() + { + new IndicatorDataPoint(time, 10.0m), + new IndicatorDataPoint(time.AddSeconds(1), 9.6m), + new IndicatorDataPoint(time.AddSeconds(2), 10.5m), + new IndicatorDataPoint(time.AddSeconds(3), 11.1m), + new IndicatorDataPoint(time.AddSeconds(4), 11.0m), + new IndicatorDataPoint(time.AddSeconds(5), 10.7m), + new IndicatorDataPoint(time.AddSeconds(6), 11.6m), + new IndicatorDataPoint(time.AddSeconds(7), 12.3m), + new IndicatorDataPoint(time.AddSeconds(8), 12.3m), + new IndicatorDataPoint(time.AddSeconds(9), 12.4m), + new IndicatorDataPoint(time.AddSeconds(10), 11.5m), + new IndicatorDataPoint(time.AddSeconds(11), 7.9m), + new IndicatorDataPoint(time.AddSeconds(12), 7.9m) + }; + } + private class TestRenkoConsolidator : RenkoConsolidator { public TestRenkoConsolidator(decimal barSize) diff --git a/Tests/Common/Data/SequentialConsolidatorTests.cs b/Tests/Common/Data/SequentialConsolidatorTests.cs index 6d7e50763dce..eca35b0c3359 100644 --- a/Tests/Common/Data/SequentialConsolidatorTests.cs +++ b/Tests/Common/Data/SequentialConsolidatorTests.cs @@ -17,11 +17,12 @@ using QuantConnect.Data; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; +using QuantConnect.Indicators; namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class SequentialConsolidatorTests + public class SequentialConsolidatorTests: BaseConsolidatorTests { [Test] public void SequentialConsolidatorsFiresAllEvents() @@ -89,5 +90,20 @@ public void SequentialConsolidatorAcceptsSubTypesForSecondInputType() Assert.IsTrue(secondFired); Assert.IsTrue(sequentialFired); } + + protected override IDataConsolidator CreateConsolidator() + { + var first = new IdentityDataConsolidator(); + var second = new IdentityDataConsolidator(); + return new SequentialConsolidator(first, second); + } + + protected override void AssertConsolidator(IDataConsolidator consolidator) + { + base.AssertConsolidator(consolidator); + var sequentialConsolidator = consolidator as SequentialConsolidator; + Assert.IsNull(sequentialConsolidator.First.Consolidated); + Assert.IsNull(sequentialConsolidator.Second.Consolidated); + } } } diff --git a/Tests/Common/Data/SubscriptionManagerTests.cs b/Tests/Common/Data/SubscriptionManagerTests.cs index 6e901d9928e0..487c19ba7556 100644 --- a/Tests/Common/Data/SubscriptionManagerTests.cs +++ b/Tests/Common/Data/SubscriptionManagerTests.cs @@ -612,6 +612,10 @@ public TestConsolidator(Type inputType, Type outputType) InputType = inputType; OutputType = outputType; } + + public void Reset() + { + } } private static List> GetSubscriptionDataTypes(SecurityType securityType, Resolution resolution, bool isCanonical = false) diff --git a/Tests/Common/Data/TickConsolidatorTests.cs b/Tests/Common/Data/TickConsolidatorTests.cs index e9aba9dfe97a..2bf512407c31 100644 --- a/Tests/Common/Data/TickConsolidatorTests.cs +++ b/Tests/Common/Data/TickConsolidatorTests.cs @@ -14,14 +14,16 @@ */ using System; +using System.Collections.Generic; using NUnit.Framework; +using QuantConnect.Data; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class TickConsolidatorTests + public class TickConsolidatorTests: BaseConsolidatorTests { [Test] public void AggregatesNewTradeBarsProperly() @@ -332,5 +334,28 @@ public void ProcessesTradeTicksOnly() Assert.AreEqual(consolidated.Close, tick1.Value); } + protected override IDataConsolidator CreateConsolidator() + { + return new TickConsolidator(2); + } + + protected override IEnumerable GetTestValues() + { + var time = DateTime.Today; + return new List() + { + new Tick(){Symbol = Symbols.SPY, Time = time, Value = 10 }, + new Tick(){Symbol = Symbols.SPY, Time = time.AddSeconds(1), Value = 2 }, + new Tick(){Symbol = Symbols.SPY, Time = time.AddSeconds(2), Value = 8 }, + new Tick(){Symbol = Symbols.SPY, Time = time.AddSeconds(3), Value = 5 }, + new Tick(){Symbol = Symbols.SPY, Time = time.AddSeconds(4), Value = 13 }, + new Tick(){Symbol = Symbols.SPY, Time = time.AddSeconds(5), Value = 15 }, + new Tick(){Symbol = Symbols.SPY, Time = time.AddSeconds(6), Value = 10 }, + new Tick(){Symbol = Symbols.SPY, Time = time.AddSeconds(7), Value = 11 }, + new Tick(){Symbol = Symbols.SPY, Time = time.AddSeconds(8), Value = 11 }, + new Tick(){Symbol = Symbols.SPY, Time = time.AddSeconds(9), Value = 4 }, + new Tick(){Symbol = Symbols.SPY, Time = time.AddSeconds(10), Value = 7 }, + }; + } } } diff --git a/Tests/Common/Data/TickQuoteBarConsolidatorTests.cs b/Tests/Common/Data/TickQuoteBarConsolidatorTests.cs index 4285690fb69f..acd01ba3a5b0 100644 --- a/Tests/Common/Data/TickQuoteBarConsolidatorTests.cs +++ b/Tests/Common/Data/TickQuoteBarConsolidatorTests.cs @@ -14,14 +14,16 @@ */ using System; +using System.Collections.Generic; using NUnit.Framework; +using QuantConnect.Data; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class TickQuoteBarConsolidatorTests + public class TickQuoteBarConsolidatorTests: BaseConsolidatorTests { [Test] public void AggregatesNewQuoteBarProperly() @@ -261,5 +263,29 @@ public void LastCloseAndCurrentOpenPriceShouldBeSameConsolidatedOnTimeSpan() Assert.AreEqual(tick4.AskPrice, quoteBar.Ask.Close, "Ask Close incorrect"); Assert.AreEqual(tick4.BidPrice, quoteBar.Bid.Close, "Bid Close incorrect"); } + + protected override IDataConsolidator CreateConsolidator() + { + return new TickQuoteBarConsolidator(2); + } + + protected override IEnumerable GetTestValues() + { + var time = DateTime.Today; + return new List() + { + new Tick(){Symbol = Symbols.SPY, TickType = TickType.Quote, Time = time, Value = 10, AskPrice = 10, BidPrice = 5 }, + new Tick(){Symbol = Symbols.SPY, TickType = TickType.Quote, Time = time.AddSeconds(1), Value = 2, AskPrice = 10, BidPrice = 7 }, + new Tick(){Symbol = Symbols.SPY, TickType = TickType.Quote, Time = time.AddSeconds(2), Value = 8, AskPrice = 11, BidPrice = 9 }, + new Tick(){Symbol = Symbols.SPY, TickType = TickType.Quote, Time = time.AddSeconds(3), Value = 5, AskPrice = 15, BidPrice = 6 }, + new Tick(){Symbol = Symbols.SPY, TickType = TickType.Quote, Time = time.AddSeconds(4), Value = 13, AskPrice = 15, BidPrice = 7 }, + new Tick(){Symbol = Symbols.SPY, TickType = TickType.Quote, Time = time.AddSeconds(5), Value = 15 , AskPrice = 13, BidPrice = 8 }, + new Tick(){Symbol = Symbols.SPY, TickType = TickType.Quote, Time = time.AddSeconds(6), Value = 10 , AskPrice = 14, BidPrice = 7 }, + new Tick(){Symbol = Symbols.SPY, TickType = TickType.Quote, Time = time.AddSeconds(7), Value = 11 , AskPrice = 13, BidPrice = 8 }, + new Tick(){Symbol = Symbols.SPY, TickType = TickType.Quote, Time = time.AddSeconds(8), Value = 11 , AskPrice = 14, BidPrice = 6 }, + new Tick(){Symbol = Symbols.SPY, TickType = TickType.Quote, Time = time.AddSeconds(9), Value = 4 , AskPrice = 14, BidPrice = 9 }, + new Tick(){Symbol = Symbols.SPY, TickType = TickType.Quote, Time = time.AddSeconds(10), Value = 7 , AskPrice = 13, BidPrice = 5 }, + }; + } } } diff --git a/Tests/Common/Data/TradeBarConsolidatorTests.cs b/Tests/Common/Data/TradeBarConsolidatorTests.cs index 7b5052645e52..2bafb0bc6998 100644 --- a/Tests/Common/Data/TradeBarConsolidatorTests.cs +++ b/Tests/Common/Data/TradeBarConsolidatorTests.cs @@ -16,13 +16,14 @@ using System; using System.Collections.Generic; using NUnit.Framework; +using QuantConnect.Data; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class TradeBarConsolidatorTests + public class TradeBarConsolidatorTests: BaseConsolidatorTests { [Test] public void ZeroCountAlwaysFires() @@ -562,5 +563,29 @@ private IEnumerable StreamTradeBars(DateTime start, DateTime end, Time current = current + resolution; } } + + protected override IDataConsolidator CreateConsolidator() + { + return new TradeBarConsolidator(2); + } + + protected override IEnumerable GetTestValues() + { + var time = new DateTime(2015, 04, 13, 8, 31, 0); + return new List() + { + new TradeBar(){ Time = time, Period = Time.OneMinute, Symbol = Symbols.SPY, High = 10 }, + new TradeBar(){ Time = time.AddMinutes(1), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 12 }, + new TradeBar(){ Time = time.AddMinutes(2), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 10 }, + new TradeBar(){ Time = time.AddMinutes(3), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 5 }, + new TradeBar(){ Time = time.AddMinutes(4), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 15 }, + new TradeBar(){ Time = time.AddMinutes(5), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 20 }, + new TradeBar(){ Time = time.AddMinutes(6), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 18 }, + new TradeBar(){ Time = time.AddMinutes(7), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 12 }, + new TradeBar(){ Time = time.AddMinutes(8), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 25 }, + new TradeBar(){ Time = time.AddMinutes(9), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 30 }, + new TradeBar(){ Time = time.AddMinutes(10), Period = Time.OneMinute, Symbol = Symbols.SPY, High = 26 }, + }; + } } } diff --git a/Tests/Common/Data/VolumeRenkoConsolidatorTests.cs b/Tests/Common/Data/VolumeRenkoConsolidatorTests.cs index cf404a560a47..02e9e9ce034a 100644 --- a/Tests/Common/Data/VolumeRenkoConsolidatorTests.cs +++ b/Tests/Common/Data/VolumeRenkoConsolidatorTests.cs @@ -17,13 +17,14 @@ using System.Collections.Generic; using NUnit.Framework; using Python.Runtime; +using QuantConnect.Data; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; namespace QuantConnect.Tests.Common.Data { [TestFixture] - public class VolumeRenkoConsolidatorTests + public class VolumeRenkoConsolidatorTests: BaseConsolidatorTests { [Test] public void OutputTypeIsVolumeRenkoBar() @@ -226,5 +227,31 @@ public void MultipleConsoldation() Assert.AreEqual(reference.AddHours(6), bar.EndTime); Assert.IsTrue(bar.IsClosed); } + + protected override IEnumerable GetTestValues() + { + var time = new DateTime(2016, 3, 1); + return new List() + { + new Tick(time, Symbol.Empty, String.Empty, String.Empty, 5m, 5m), + new Tick(time.AddSeconds(1), Symbol.Empty, String.Empty, String.Empty, 5m, 3m), + new Tick(time.AddSeconds(2), Symbol.Empty, String.Empty, String.Empty, 5m, 7m), + new Tick(time.AddSeconds(3), Symbol.Empty, String.Empty, String.Empty, 5m, 6m), + new Tick(time.AddSeconds(4), Symbol.Empty, String.Empty, String.Empty, 5m, 5m), + new Tick(time.AddSeconds(5), Symbol.Empty, String.Empty, String.Empty, 5m, 3m), + new Tick(time.AddSeconds(6), Symbol.Empty, String.Empty, String.Empty, 5m, 7m), + new Tick(time.AddSeconds(7), Symbol.Empty, String.Empty, String.Empty, 5m, 6m), + new Tick(time.AddSeconds(8), Symbol.Empty, String.Empty, String.Empty, 5m, 5m), + new Tick(time.AddSeconds(9), Symbol.Empty, String.Empty, String.Empty, 5m, 6m), + new Tick(time.AddSeconds(10), Symbol.Empty, String.Empty, String.Empty, 5m, 7m), + new Tick(time.AddSeconds(11), Symbol.Empty, String.Empty, String.Empty, 5m, 8m), + new Tick(time.AddSeconds(12), Symbol.Empty, String.Empty, String.Empty, 5m, 9m) + }; + } + + protected override IDataConsolidator CreateConsolidator() + { + return new VolumeRenkoConsolidator(10m); + } } } diff --git a/Tests/Common/Util/ConcurrentSetTests.cs b/Tests/Common/Util/ConcurrentSetTests.cs index 650ddefa735b..d3a2fbe8a10a 100644 --- a/Tests/Common/Util/ConcurrentSetTests.cs +++ b/Tests/Common/Util/ConcurrentSetTests.cs @@ -282,6 +282,10 @@ public TestConsolidator(int maxCount) : base(maxCount) Id = maxCount; } + public override void Reset() + { + } + protected override void AggregateBar(ref QuoteBar workingBar, QuoteBar data) { throw new NotImplementedException(); diff --git a/Tests/Python/DataConsolidatorPythonWrapperTests.cs b/Tests/Python/DataConsolidatorPythonWrapperTests.cs index bbb4e91623f6..91789712d556 100644 --- a/Tests/Python/DataConsolidatorPythonWrapperTests.cs +++ b/Tests/Python/DataConsolidatorPythonWrapperTests.cs @@ -18,17 +18,19 @@ using Python.Runtime; using System.Collections.Generic; using System.Linq; +using QuantConnect.Data; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; using QuantConnect.Python; using QuantConnect.Algorithm; using QuantConnect.Tests.Engine.DataFeeds; using QuantConnect.Statistics; +using QuantConnect.Tests.Common.Data; namespace QuantConnect.Tests.Python { [TestFixture] - public class DataConsolidatorPythonWrapperTests + public class DataConsolidatorPythonWrapperTests: BaseConsolidatorTests { [Test] public void UpdatePyConsolidator() @@ -217,7 +219,7 @@ public void AttachAndTriggerEvent() "class CustomConsolidator(QuoteBarConsolidator):\n" + " def __init__(self,span):\n" + " super().__init__(span)\n" + - " self.Span = span"); + " self.Span = span\n"); var implementingClass = module.GetAttr("ImplementingClass").Invoke(); var customConsolidator = implementingClass.GetAttr("Consolidator"); @@ -280,5 +282,64 @@ public void SubscriptionManagedDoesNotWrapCSharpConsolidators() } + protected override IEnumerable GetTestValues() + { + var time = DateTime.Today; + return new List() + { + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(1, 2, 0.5m, 1.75m), Ask = new Bar(2.2m, 4.4m, 3.3m, 3.3m), LastBidSize = 10, LastAskSize = 0 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(0, 4, 0.4m, 3.75m), Ask = new Bar(2.3m, 9.4m, 2.3m, 4.5m), LastBidSize = 5, LastAskSize = 4 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(2, 2, 0.9m, 1.45m), Ask = new Bar(2.7m, 8.4m, 3.6m, 3.6m), LastBidSize = 8, LastAskSize = 4 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(2, 6, 2.5m, 5.55m), Ask = new Bar(3.2m, 6.4m, 2.3m, 5.3m), LastBidSize = 9, LastAskSize = 4 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(1, 2, 1.5m, 0.34m), Ask = new Bar(3.6m, 9.4m, 3.7m, 3.8m), LastBidSize = 5, LastAskSize = 8 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(1, 2, 1.1m, 0.75m), Ask = new Bar(3.8m, 8.4m, 7.3m, 5.3m), LastBidSize = 9, LastAskSize = 5 }, + new QuoteBar(){Time = time, Symbol = Symbols.SPY, Bid = new Bar(3, 3, 2.2m, 1.12m), Ask = new Bar(4.5m, 7.2m, 7.1m, 6.1m), LastBidSize = 6, LastAskSize = 3 }, + }; + } + + protected override void AssertConsolidator(IDataConsolidator consolidator) + { + base.AssertConsolidator(consolidator); + using (Py.GIL()) + { + var pythonConsolidator = consolidator as TestDataConsolidatorPythonWrapper; + pythonConsolidator.RawIndicator.GetAttr("update_was_called").TryConvert(out bool pythonConsolidatorUpdateWasCalled); + Assert.IsFalse(pythonConsolidatorUpdateWasCalled); + } + } + + protected override IDataConsolidator CreateConsolidator() + { + using (Py.GIL()) + { + var module = PyModule.FromString(Guid.NewGuid().ToString(), + "from AlgorithmImports import *\n" + + "class CustomConsolidator(PythonConsolidator):\n" + + " def __init__(self):\n" + + " self.update_was_called = False\n" + + " self.input_type = QuoteBar\n" + + " self.output_type = QuoteBar\n" + + " self.consolidated = None\n" + + " self.working_data = None\n" + + " def update(self, data):\n" + + " self.update_was_called = True\n" + + " def scan(self, time):\n" + + " pass\n" + + " def reset(self):\n" + + " self.update_was_called = False\n"); + + var customConsolidator = module.GetAttr("CustomConsolidator").Invoke(); + return new TestDataConsolidatorPythonWrapper(customConsolidator); + } + } + + public class TestDataConsolidatorPythonWrapper : DataConsolidatorPythonWrapper + { + public PyObject RawIndicator { get; set; } + public TestDataConsolidatorPythonWrapper(PyObject consolidator) : base(consolidator) + { + RawIndicator = consolidator; + } + } } }