diff --git a/Common/Indicators/RollingWindow.cs b/Common/Indicators/RollingWindow.cs index d2f7ed526813..b1172752499f 100644 --- a/Common/Indicators/RollingWindow.cs +++ b/Common/Indicators/RollingWindow.cs @@ -16,6 +16,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Threading; namespace QuantConnect.Indicators @@ -174,7 +175,7 @@ public T this [int i] return default; } - return _list[(_list.Count + _tail - i - 1) % _list.Count]; + return _list[GetListIndex(i, _list.Count, _tail)]; } finally { @@ -206,7 +207,7 @@ public T this [int i] } } - _list[(_list.Count + _tail - i - 1) % _list.Count] = value; + _list[GetListIndex(i, _list.Count, _tail)] = value; } finally { @@ -244,18 +245,20 @@ public bool IsReady /// 1 public IEnumerator GetEnumerator() { - // we make a copy on purpose so the enumerator isn't tied - // to a mutable object, well it is still mutable but out of scope - var temp = new List(_list.Count); try { _listLock.EnterReadLock(); - for (int i = 0; i < _list.Count; i++) + // we make a copy on purpose so the enumerator isn't tied + // to a mutable object, well it is still mutable but out of scope + var count = _list.Count; + var temp = new T[count]; + for (int i = 0; i < count; i++) { - temp.Add(this[i]); + temp[i] = _list[GetListIndex(i, count, _tail)]; } - return temp.GetEnumerator(); + + return ((IEnumerable) temp).GetEnumerator(); } finally { @@ -325,6 +328,12 @@ public void Reset() } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int GetListIndex(int index, int listCount, int tail) + { + return (listCount + tail - index - 1) % listCount; + } + private void Resize(int size) { try diff --git a/Tests/Indicators/RollingWindowTests.cs b/Tests/Indicators/RollingWindowTests.cs index c451e8838b71..5c7001c50c6f 100644 --- a/Tests/Indicators/RollingWindowTests.cs +++ b/Tests/Indicators/RollingWindowTests.cs @@ -114,6 +114,12 @@ public void EnumeratesAsExpected() Assert.AreEqual(2, inOrder[0]); Assert.AreEqual(1, inOrder[1]); Assert.AreEqual(0, inOrder[2]); + + window.Add(3); + var inOrder2 = window.ToList(); + Assert.AreEqual(3, inOrder2[0]); + Assert.AreEqual(2, inOrder2[1]); + Assert.AreEqual(1, inOrder2[2]); } [Test]