From 12b03be6ca961ac5740f2f8d597a64df1cd7e597 Mon Sep 17 00:00:00 2001 From: mkzung <103102868+mkzung@users.noreply.github.com> Date: Wed, 19 Aug 2026 20:48:46 +0500 Subject: [PATCH] Reject the two point window Beta, Correlation and Covariance describe All three carry the comment "assert the period is greater than two" and raise "must be greater than 2 but was {period}", and all three test period < 2, so a period of two reaches the calculation. Two points always correlate perfectly. Fed ten bars of two series that are not proportional, Correlation at period 2 returns 1 or -1 on every one of its nine readings, while at period 3 the same series gives values between -0.40 and 0.33. Beta and Covariance share the window. ValueAtRisk states the same bound and tests period < 3. --- Indicators/Beta.cs | 2 +- Indicators/Correlation.cs | 2 +- Indicators/Covariance.cs | 2 +- Tests/Indicators/BetaIndicatorTests.cs | 12 ++++++++++++ Tests/Indicators/CorrelationPearsonTests.cs | 12 ++++++++++++ Tests/Indicators/CovarianceTests.cs | 12 ++++++++++++ 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Indicators/Beta.cs b/Indicators/Beta.cs index b475bf543b65..f1260914364f 100644 --- a/Indicators/Beta.cs +++ b/Indicators/Beta.cs @@ -59,7 +59,7 @@ public Beta(string name, Symbol targetSymbol, Symbol referenceSymbol, int period : base(name, targetSymbol, referenceSymbol, 2) { // Assert the period is greater than two, otherwise the beta can not be computed - if (period < 2) + if (period < 3) { throw new ArgumentException($"Period parameter for Beta indicator must be greater than 2 but was {period}."); } diff --git a/Indicators/Correlation.cs b/Indicators/Correlation.cs index aab80112c13b..b2bdc9f09e2d 100644 --- a/Indicators/Correlation.cs +++ b/Indicators/Correlation.cs @@ -61,7 +61,7 @@ public Correlation(string name, Symbol targetSymbol, Symbol referenceSymbol, int : base(name, targetSymbol, referenceSymbol, period) { // Assert the period is greater than two, otherwise the correlation can not be computed - if (period < 2) + if (period < 3) { throw new ArgumentException($"Period parameter for Correlation indicator must be greater than 2 but was {period}"); } diff --git a/Indicators/Covariance.cs b/Indicators/Covariance.cs index ee3a85a003cf..5a630014f94c 100644 --- a/Indicators/Covariance.cs +++ b/Indicators/Covariance.cs @@ -52,7 +52,7 @@ public Covariance(string name, Symbol targetSymbol, Symbol referenceSymbol, int : base(name, targetSymbol, referenceSymbol, 2) { // Assert the period is greater than two, otherwise the covariance can not be computed - if (period < 2) + if (period < 3) { throw new ArgumentException($"Period parameter for Covariance indicator must be greater than 2 but was {period}."); } diff --git a/Tests/Indicators/BetaIndicatorTests.cs b/Tests/Indicators/BetaIndicatorTests.cs index 0068e1a01ac0..b0ce13ca8fd3 100644 --- a/Tests/Indicators/BetaIndicatorTests.cs +++ b/Tests/Indicators/BetaIndicatorTests.cs @@ -312,5 +312,17 @@ public override void IndicatorShouldHaveSymbolAfterUpdates() Assert.AreEqual(Symbols.AAPL, indicator.Current.Symbol); } } + + [Test] + public void PeriodBelowMinimumThrows() + { + // A two point window leaves no spread to measure: the correlation of two + // points is 1 or -1 whatever the data says, so three is the smallest period + // that carries information + var period = 2; + + var exception = Assert.Throws(() => new Beta(Symbols.SPY, Symbols.AAPL, period)); + Assert.That(exception.Message, Is.EqualTo($"Period parameter for Beta indicator must be greater than 2 but was {period}.")); + } } } diff --git a/Tests/Indicators/CorrelationPearsonTests.cs b/Tests/Indicators/CorrelationPearsonTests.cs index a98c882126df..c65d90441474 100644 --- a/Tests/Indicators/CorrelationPearsonTests.cs +++ b/Tests/Indicators/CorrelationPearsonTests.cs @@ -223,5 +223,17 @@ public void CorrelationWithDifferentTimeZones() } Assert.AreEqual(1, (double)indicator.Current.Value); } + + [Test] + public void PeriodBelowMinimumThrows() + { + // A two point window leaves no spread to measure: the correlation of two + // points is 1 or -1 whatever the data says, so three is the smallest period + // that carries information + var period = 2; + + var exception = Assert.Throws(() => new Correlation(Symbols.SPY, Symbols.AAPL, period)); + Assert.That(exception.Message, Is.EqualTo($"Period parameter for Correlation indicator must be greater than 2 but was {period}")); + } } } diff --git a/Tests/Indicators/CovarianceTests.cs b/Tests/Indicators/CovarianceTests.cs index 32981af7f30a..37d99c008b9b 100644 --- a/Tests/Indicators/CovarianceTests.cs +++ b/Tests/Indicators/CovarianceTests.cs @@ -287,5 +287,17 @@ public override void IndicatorShouldHaveSymbolAfterUpdates() Assert.AreEqual(Symbols.AAPL, indicator.Current.Symbol); } } + + [Test] + public void PeriodBelowMinimumThrows() + { + // A two point window leaves no spread to measure: the correlation of two + // points is 1 or -1 whatever the data says, so three is the smallest period + // that carries information + var period = 2; + + var exception = Assert.Throws(() => new Covariance(Symbols.SPY, Symbols.AAPL, period)); + Assert.That(exception.Message, Is.EqualTo($"Period parameter for Covariance indicator must be greater than 2 but was {period}.")); + } } }