diff --git a/Indicators/Variance.cs b/Indicators/Variance.cs index 41352631672f..b158563145f3 100644 --- a/Indicators/Variance.cs +++ b/Indicators/Variance.cs @@ -57,8 +57,20 @@ public Variance(string name, int period) /// A new value for this indicator protected override decimal ComputeNextValue(IReadOnlyWindow window, IndicatorDataPoint input) { - _rollingSum += input.Value; - _rollingSumOfSquares += input.Value * input.Value; + var previousRollingSum = _rollingSum; + var previousRollingSumOfSquares = _rollingSumOfSquares; + try + { + _rollingSum += input.Value; + _rollingSumOfSquares += input.Value * input.Value; + } + catch (OverflowException) + { + _rollingSum = previousRollingSum; + _rollingSumOfSquares = previousRollingSumOfSquares; + //Log.Error($"Variance.ComputeNextValue: Decimal overflow detected when adding value {input.Value}. The previous variance value will be returned."); + return Current.Value; + } if (Samples < 2) return 0m; diff --git a/Tests/Indicators/VarianceTests.cs b/Tests/Indicators/VarianceTests.cs index 5717f62a27c9..e5103ca07cea 100644 --- a/Tests/Indicators/VarianceTests.cs +++ b/Tests/Indicators/VarianceTests.cs @@ -13,6 +13,7 @@ * limitations under the License. */ +using System; using NUnit.Framework; using QuantConnect.Indicators; @@ -29,5 +30,22 @@ protected override IndicatorBase CreateIndicator() protected override string TestFileName => "spy_var.txt"; protected override string TestColumnName => "Var"; + + [Test] + public void DoesNotThrowOnDecimalOverflow() + { + var variance = new Variance(3); + var time = new DateTime(2020, 1, 1); + + variance.Update(time, 100m); + variance.Update(time.AddSeconds(1), 200m); + variance.Update(time.AddSeconds(2), 150m); + var previousValue = variance.Current.Value; + + var overflowValue = 300000000000000m; // 3e14 squared will exceed decimal.MaxValue + + Assert.DoesNotThrow(() => variance.Update(time.AddSeconds(3), overflowValue)); + Assert.AreEqual(previousValue, variance.Current.Value); + } } } \ No newline at end of file