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]