Merge branch 'dev' into main

This commit is contained in:
Miha Kralj
2026-03-16 12:46:19 -07:00
131 changed files with 1582 additions and 1583 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ Statistical tools applied to price and returns. These indicators quantify relati
| [BETA](beta/Beta.md) | Beta Coefficient | Asset volatility relative to market. β=1 means market-matched risk. |
| [CMA](cma/Cma.md) | Cumulative Moving Average | Running average of all values. Welford's algorithm. No window. |
| [COINTEGRATION](cointegration/Cointegration.md) | Cointegration | Tests if series share long-term equilibrium. Pairs trading foundation. |
| [CORRELATION](correlation/Correlation.md) | Correlation | Linear relationship between two variables. Range: -1 to +1. |
| [CORREL](correl/Correl.md) | Correlation | Linear relationship between two variables. Range: -1 to +1. |
| [COVARIANCE](covariance/Covariance.md) | Covariance | Joint variability of two random variables. Building block for β. |
| [ENTROPY](entropy/Entropy.md) | Shannon Entropy | Measures uncertainty/randomness. Higher entropy = less predictable. |
| [GEOMEAN](geomean/Geomean.md) | Geometric Mean | nth root of product. Use for growth rates and ratios. |
+1 -1
View File
@@ -13,7 +13,7 @@
| **PineScript** | [acf.pine](acf.pine) |
- The Autocorrelation Function (ACF) measures the correlation of a time series with a lagged copy of itself.
- **Similar:** [PACF](../pacf/Pacf.md), [Correlation](../correlation/Correlation.md) | **Trading note:** Autocorrelation function; detects mean-reversion (negative ACF) vs momentum (positive ACF) in returns.
- **Similar:** [PACF](../pacf/Pacf.md), [Correl](../correl/Correl.md) | **Trading note:** Autocorrelation function; detects mean-reversion (negative ACF) vs momentum (positive ACF) in returns.
- Validated against mathematical properties and theoretical AR-process expectations.
The Autocorrelation Function (ACF) measures the correlation of a time series with a lagged copy of itself. It is fundamental for identifying repeating patterns, seasonal effects, and determining the order of time series models like ARMA/ARIMA.
+3 -1
View File
@@ -13,7 +13,9 @@
| **PineScript** | [adf.pine](adf.pine) |
- Tests the null hypothesis that a time series contains a unit root (non-stationary). Output near **0** → stationary; output near **1** → unit root.
- **Similar:** [Hurst](../hurst/Hurst.md), [Cointegration](../cointegration/Cointegration.md) | **Complementary:** Z-Score, Variance | **Trading note:** ADF < 0.05 confirms mean-reversion suitability.
- **Similar indicators:** [Hurst](../hurst/Hurst.md), [Cointegration](../cointegration/Cointegration.md)
- **Complementary indicators:** [Z-Score](../zscore/Zscore.md), [Variance](../variance/Variance.md)
- **Trading note:** ADF < 0.05 confirms mean-reversion suitability.
- Validated against Python `statsmodels.tsa.stattools.adfuller` reference implementation.
The Augmented Dickey-Fuller test is the gold standard for detecting whether a financial time series is stationary or contains a unit root. Unlike the original Dickey-Fuller test, the augmented version includes lagged difference terms $\Delta y_{t-i}$ to absorb serial correlation, ensuring the test statistic follows the correct distribution. The p-value output uses MacKinnon (1994, 2010) polynomial interpolation with a standard normal CDF approximation, providing machine-precision results without lookup tables.
+1 -1
View File
@@ -13,7 +13,7 @@
| **PineScript** | [beta.pine](beta.pine) |
- Beta measures the volatility of an asset in relation to the overall market.
- **Similar:** [Correlation](../correlation/Correlation.md), [Covariance](../covariance/Covariance.md) | **Trading note:** Beta coefficient; measures systematic risk vs benchmark. β>1 = amplifies market moves.
- **Similar:** [Correl](../correl/Correl.md), [Covariance](../covariance/Covariance.md) | **Trading note:** Beta coefficient; measures systematic risk vs benchmark. β>1 = amplifies market moves.
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
Beta measures the volatility of an asset in relation to the overall market. It's the slope of the regression line between the asset's returns and the market's returns. A beta of 1.0 means the asset moves in lockstep with the market. A beta of 2.0 means the asset is twice as volatile as the market.
@@ -13,7 +13,7 @@
| **PineScript** | [cointegration.pine](cointegration.pine) |
- The Cointegration indicator measures the long-run equilibrium relationship between two price series using the Engle-Granger two-step method with an...
- **Similar:** [Correlation](../correlation/Correlation.md), [Granger](../granger/Granger.md) | **Trading note:** Tests if two series share a long-run equilibrium. Foundation of statistical arbitrage (pairs trading).
- **Similar:** [Correl](../correl/Correl.md), [Granger](../granger/Granger.md) | **Trading note:** Tests if two series share a long-run equilibrium. Foundation of statistical arbitrage (pairs trading).
- Validated against TradingView PineScript reference and statistical property tests.
The Cointegration indicator measures the long-run equilibrium relationship between two price series using the Engle-Granger two-step method with an Augmented Dickey-Fuller (ADF) test. Unlike correlation, which measures short-term co-movement, cointegration tests whether two non-stationary series share a common stochastic trend—meaning they may diverge temporarily but are statistically bound to revert to their equilibrium relationship.
@@ -28,7 +28,7 @@ namespace QuanTAlib;
/// - |r| < 0.3: Weak correlation
/// </remarks>
[SkipLocalsInit]
public sealed class Correlation : AbstractBase
public sealed class Correl : AbstractBase
{
private readonly RingBuffer _bufferX;
private readonly RingBuffer _bufferY;
@@ -58,10 +58,10 @@ public sealed class Correlation : AbstractBase
public override bool IsHot => _bufferX.Count >= WarmupPeriod;
/// <summary>
/// Creates a new Correlation indicator.
/// Creates a new Correl indicator.
/// </summary>
/// <param name="period">Lookback period for calculation (must be > 1)</param>
public Correlation(int period = 20)
public Correl(int period = 20)
{
if (period <= 1)
{
@@ -71,7 +71,7 @@ public sealed class Correlation : AbstractBase
_bufferX = new RingBuffer(period);
_bufferY = new RingBuffer(period);
Name = $"Correlation({period})";
Name = $"Correl({period})";
WarmupPeriod = period;
}
@@ -118,7 +118,7 @@ public sealed class Correlation : AbstractBase
ProcessBarCorrection(x, y);
}
double correlation = CalculateCorrelation();
double correlation = CalculateCorrel();
Last = new TValue(seriesX.Time, correlation);
PubEvent(Last);
@@ -143,13 +143,13 @@ public sealed class Correlation : AbstractBase
/// <remarks>Not supported for bi-input indicator. Use Update(seriesX, seriesY) instead.</remarks>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("Correlation requires two inputs (seriesX and seriesY). Use Update(seriesX, seriesY).");
throw new NotSupportedException("Correl requires two inputs (seriesX and seriesY). Use Update(seriesX, seriesY).");
}
/// <summary>Not supported. This indicator requires two inputs; use <see cref="Batch(TSeries, TSeries, int)"/> instead.</summary>
/// <remarks>Not supported for bi-input indicator. Use Calculate(seriesX, seriesY, period) instead.</remarks>
public override TSeries Update(TSeries source)
{
throw new NotSupportedException("Correlation requires two inputs. Use Batch(seriesX, seriesY, period).");
throw new NotSupportedException("Correl requires two inputs. Use Batch(seriesX, seriesY, period).");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -316,7 +316,7 @@ public sealed class Correlation : AbstractBase
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private double CalculateCorrelation()
private double CalculateCorrel()
{
int n = _bufferX.Count;
if (n < 2)
@@ -355,7 +355,7 @@ public sealed class Correlation : AbstractBase
/// <summary>Not supported. This indicator requires two input spans.</summary>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("Correlation requires two inputs.");
throw new NotSupportedException("Correl requires two inputs.");
}
/// <inheritdoc />
@@ -414,7 +414,7 @@ public sealed class Correlation : AbstractBase
throw new ArgumentException("Period must be greater than 1", nameof(period));
}
var indicator = new Correlation(period);
var indicator = new Correl(period);
for (int i = 0; i < seriesX.Length; i++)
{
@@ -426,14 +426,14 @@ public sealed class Correlation : AbstractBase
/// <summary>
/// Calculates Pearson correlation for two time series and returns both the result series and the live indicator instance.
/// </summary>
public static (TSeries Results, Correlation Indicator) Calculate(TSeries seriesX, TSeries seriesY, int period = 20)
public static (TSeries Results, Correl Indicator) Calculate(TSeries seriesX, TSeries seriesY, int period = 20)
{
if (seriesX.Count != seriesY.Count)
{
throw new ArgumentException("Series must have the same length", nameof(seriesY));
}
var indicator = new Correlation(period);
var indicator = new Correl(period);
var result = new TSeries(seriesX.Count);
var timesX = seriesX.Times;
@@ -10,7 +10,7 @@
| **Outputs** | Single series (Pearson r) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
| **PineScript** | [correlation.pine](correlation.pine) |
| **PineScript** | [correl.pine](correl.pine) |
- The Pearson Correlation Coefficient measures the linear relationship between two variables, returning a value from -1 (perfect negative correlation...
- **Similar:** [Spearman](../spearman/Spearman.md), [Kendall](../kendall/Kendall.md) | **Trading note:** Pearson correlation; measures linear relationship strength. Used for portfolio diversification and pairs trading.
@@ -189,7 +189,7 @@ Monitor correlation stability:
### Streaming Mode (Bi-Input)
```csharp
var corr = new Correlation(period: 20);
var corr = new Correl(period: 20);
foreach (var (priceA, priceB) in pricePairs)
{
var result = corr.Update(priceA, priceB);
@@ -206,7 +206,7 @@ foreach (var (priceA, priceB) in pricePairs)
var seriesA = new TSeries();
var seriesB = new TSeries();
// ... populate series ...
var results = Correlation.Calculate(seriesA, seriesB, period: 20);
var results = Correl.Calculate(seriesA, seriesB, period: 20);
```
### Span Mode (Zero Allocation)
@@ -216,13 +216,13 @@ double[] pricesA = new double[1000];
double[] pricesB = new double[1000];
double[] output = new double[1000];
// ... populate inputs ...
Correlation.Batch(pricesA.AsSpan(), pricesB.AsSpan(), output.AsSpan(), period: 20);
Correl.Batch(pricesA.AsSpan(), pricesB.AsSpan(), output.AsSpan(), period: 20);
```
### Bar Correction Support
```csharp
var corr = new Correlation(20);
var corr = new Correl(20);
// New bar
corr.Update(100.0, 50.0, isNew: true); // r = 0.85
@@ -1,7 +1,7 @@
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Pearson's Correlation (CORRELATION)", "CORRELATION", overlay=false)
indicator("Pearson's Correlation (CORREL)", "CORREL", overlay=false)
//@function Calculates Pearson correlation coefficient using single pass with circular buffer
//@param src1 series float First series to analyze
@@ -1,42 +1,42 @@
namespace QuanTAlib.Tests;
public class CorrelationTests
public class CorrelTests
{
[Fact]
public void Constructor_ValidPeriod_CreatesIndicator()
{
var indicator = new Correlation(20);
Assert.Equal("Correlation(20)", indicator.Name);
var indicator = new Correl(20);
Assert.Equal("Correl(20)", indicator.Name);
Assert.Equal(20, indicator.WarmupPeriod);
}
[Fact]
public void Constructor_MinimumValidPeriod_CreatesIndicator()
{
var indicator = new Correlation(2);
Assert.Equal("Correlation(2)", indicator.Name);
var indicator = new Correl(2);
Assert.Equal("Correl(2)", indicator.Name);
}
[Fact]
public void Constructor_InvalidPeriod_ThrowsArgumentException()
{
Assert.Throws<ArgumentException>(() => new Correlation(1));
Assert.Throws<ArgumentException>(() => new Correlation(0));
Assert.Throws<ArgumentException>(() => new Correlation(-5));
Assert.Throws<ArgumentException>(() => new Correl(1));
Assert.Throws<ArgumentException>(() => new Correl(0));
Assert.Throws<ArgumentException>(() => new Correl(-5));
}
[Fact]
public void Update_SingleValue_ReturnsNaN()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
var result = indicator.Update(100.0, 200.0, true);
Assert.True(double.IsNaN(result.Value));
}
[Fact]
public void Update_TwoValues_ReturnsValidCorrelation()
public void Update_TwoValues_ReturnsValidCorrel()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
indicator.Update(100.0, 200.0, true);
var result = indicator.Update(102.0, 204.0, true);
Assert.True(double.IsFinite(result.Value));
@@ -45,7 +45,7 @@ public class CorrelationTests
[Fact]
public void Update_PerfectPositiveCorrelation_ReturnsOne()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
// Same values scaled by constant should give correlation = 1
for (int i = 0; i < 10; i++)
@@ -62,7 +62,7 @@ public class CorrelationTests
[Fact]
public void Update_PerfectNegativeCorrelation_ReturnsMinusOne()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
// Opposite movements should give correlation = -1
for (int i = 0; i < 10; i++)
@@ -79,7 +79,7 @@ public class CorrelationTests
[Fact]
public void Update_ConstantValues_ReturnsNaN()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
// Constant values have zero variance, so correlation is undefined
for (int i = 0; i < 10; i++)
@@ -93,8 +93,8 @@ public class CorrelationTests
[Fact]
public void Update_BarCorrection_RestoresState()
{
var indicator1 = new Correlation(5);
var indicator2 = new Correlation(5);
var indicator1 = new Correl(5);
var indicator2 = new Correl(5);
// Feed same initial data
for (int i = 0; i < 10; i++)
@@ -119,8 +119,8 @@ public class CorrelationTests
[Fact]
public void Update_IterativeCorrections_Restore()
{
var corrected = new Correlation(5);
var direct = new Correlation(5);
var corrected = new Correl(5);
var direct = new Correl(5);
// Feed identical initial state
for (int i = 0; i < 8; i++)
@@ -151,7 +151,7 @@ public class CorrelationTests
[Fact]
public void Update_NaNInput_UsesLastValidValue()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
// Add valid data
for (int i = 0; i < 5; i++)
@@ -169,7 +169,7 @@ public class CorrelationTests
[Fact]
public void Update_InfinityInput_UsesLastValidValue()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
// Add valid data
for (int i = 0; i < 5; i++)
@@ -185,7 +185,7 @@ public class CorrelationTests
[Fact]
public void IsHot_BelowPeriod_ReturnsFalse()
{
var indicator = new Correlation(10);
var indicator = new Correl(10);
indicator.Update(100.0, 200.0, true);
Assert.False(indicator.IsHot);
}
@@ -193,7 +193,7 @@ public class CorrelationTests
[Fact]
public void IsHot_AtPeriod_ReturnsTrue()
{
var indicator = new Correlation(10);
var indicator = new Correl(10);
for (int i = 0; i < 10; i++)
{
indicator.Update(100.0 + i, 200.0 + i, true);
@@ -204,7 +204,7 @@ public class CorrelationTests
[Fact]
public void Reset_ClearsState()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
// Add data
for (int i = 0; i < 10; i++)
@@ -224,14 +224,14 @@ public class CorrelationTests
[Fact]
public void Update_TValue_ThrowsNotSupportedException()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
Assert.Throws<NotSupportedException>(() => indicator.Update(new TValue(DateTime.UtcNow, 100.0)));
}
[Fact]
public void Update_TSeries_ThrowsNotSupportedException()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
var series = new TSeries(10);
Assert.Throws<NotSupportedException>(() => indicator.Update(series));
}
@@ -239,7 +239,7 @@ public class CorrelationTests
[Fact]
public void Prime_ThrowsNotSupportedException()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
Assert.Throws<NotSupportedException>(() => indicator.Prime(new double[] { 1, 2, 3 }));
}
@@ -255,7 +255,7 @@ public class CorrelationTests
seriesY.Add(new TValue(DateTime.UtcNow.AddMinutes(i), 200.0 + (i * 2)));
}
var result = Correlation.Batch(seriesX, seriesY, 5);
var result = Correl.Batch(seriesX, seriesY, 5);
Assert.Equal(20, result.Count);
}
@@ -275,7 +275,7 @@ public class CorrelationTests
seriesY.Add(new TValue(DateTime.UtcNow.AddMinutes(i), 200.0 + i));
}
Assert.Throws<ArgumentException>(() => Correlation.Batch(seriesX, seriesY, 5));
Assert.Throws<ArgumentException>(() => Correl.Batch(seriesX, seriesY, 5));
}
[Fact]
@@ -291,7 +291,7 @@ public class CorrelationTests
seriesY[i] = 200.0 + (i * 2);
}
Correlation.Batch(seriesX, seriesY, output, 5);
Correl.Batch(seriesX, seriesY, output, 5);
// First value should be NaN (not enough data)
Assert.True(double.IsNaN(output[0]));
@@ -307,7 +307,7 @@ public class CorrelationTests
double[] seriesY = new double[15];
double[] output = new double[10];
Assert.Throws<ArgumentException>(() => Correlation.Batch(seriesX, seriesY, output, 5));
Assert.Throws<ArgumentException>(() => Correl.Batch(seriesX, seriesY, output, 5));
}
[Fact]
@@ -317,7 +317,7 @@ public class CorrelationTests
double[] seriesY = new double[20];
double[] output = new double[10];
Assert.Throws<ArgumentException>(() => Correlation.Batch(seriesX, seriesY, output, 5));
Assert.Throws<ArgumentException>(() => Correl.Batch(seriesX, seriesY, output, 5));
}
[Fact]
@@ -327,13 +327,13 @@ public class CorrelationTests
double[] seriesY = new double[20];
double[] output = new double[20];
Assert.Throws<ArgumentException>(() => Correlation.Batch(seriesX, seriesY, output, 1));
Assert.Throws<ArgumentException>(() => Correl.Batch(seriesX, seriesY, output, 1));
}
[Fact]
public void CorrelationRange_AlwaysBetweenMinusOneAndOne()
{
var indicator = new Correlation(10);
var indicator = new Correl(10);
var gbmX = new GBM(startPrice: 100, mu: 0.02, sigma: 0.3, seed: 12345);
var gbmY = new GBM(startPrice: 200, mu: 0.01, sigma: 0.5, seed: 54321);
@@ -369,7 +369,7 @@ public class CorrelationTests
}
// Streaming calculation
var indicator = new Correlation(period);
var indicator = new Correl(period);
double[] streamingResults = new double[length];
for (int i = 0; i < length; i++)
{
@@ -378,7 +378,7 @@ public class CorrelationTests
// Batch calculation
double[] batchResults = new double[length];
Correlation.Batch(seriesX, seriesY, batchResults, period);
Correl.Batch(seriesX, seriesY, batchResults, period);
// Compare last 50 values (after warmup)
for (int i = length - 50; i < length; i++)
@@ -8,13 +8,13 @@ namespace QuanTAlib.Tests;
/// Validation tests for Correlation (Pearson Correlation Coefficient) indicator.
/// Validates against Skender.Stock.Indicators.GetCorrelation and mathematical properties.
/// </summary>
public sealed class CorrelationValidationTests : IDisposable
public sealed class CorrelValidationTests : IDisposable
{
private const double Tolerance = 1e-10;
private readonly ValidationTestData _data;
private readonly ITestOutputHelper _output;
public CorrelationValidationTests(ITestOutputHelper output)
public CorrelValidationTests(ITestOutputHelper output)
{
_data = new ValidationTestData();
_output = output;
@@ -29,7 +29,7 @@ public sealed class CorrelationValidationTests : IDisposable
#region External Library Validation Skender
[Fact]
public void Validate_Skender_Correlation()
public void Validate_Skender_Correl()
{
// === DESCRIPTION ===
// Compares QuanTAlib Correlation against Skender.Stock.Indicators.GetCorrelation
@@ -65,7 +65,7 @@ public sealed class CorrelationValidationTests : IDisposable
var sResult = quotesA.GetCorrelation(quotesB, period).ToList();
// --- QuanTAlib: streaming API ---
var corr = new Correlation(period);
var corr = new Correl(period);
var qValues = new List<double>();
for (int i = 0; i < _data.Count; i++)
@@ -126,7 +126,7 @@ public sealed class CorrelationValidationTests : IDisposable
{
var sResult = _data.SkenderQuotes.GetCorrelation(quotesB, period).ToList();
var corr = new Correlation(period);
var corr = new Correl(period);
int matched = 0;
for (int i = 0; i < _data.Count; i++)
@@ -175,7 +175,7 @@ public sealed class CorrelationValidationTests : IDisposable
var sResult = quotesA.GetCorrelation(quotesB, period).ToList();
var corr = new Correlation(period);
var corr = new Correl(period);
int matched = 0;
for (int i = 0; i < _data.Count; i++)
@@ -207,7 +207,7 @@ public sealed class CorrelationValidationTests : IDisposable
public void Correlation_PerfectLinearPositive_ReturnsOne()
{
// y = a + b*x with b > 0 should give r = 1
var indicator = new Correlation(20);
var indicator = new Correl(20);
for (int i = 0; i < 50; i++)
{
@@ -223,7 +223,7 @@ public sealed class CorrelationValidationTests : IDisposable
public void Correlation_PerfectLinearNegative_ReturnsMinusOne()
{
// y = a + b*x with b < 0 should give r = -1
var indicator = new Correlation(20);
var indicator = new Correl(20);
for (int i = 0; i < 50; i++)
{
@@ -238,9 +238,9 @@ public sealed class CorrelationValidationTests : IDisposable
[Fact]
public void Correlation_SymmetryProperty_XY_Equals_YX()
{
// Correlation(X, Y) should equal Correlation(Y, X)
var indicatorXY = new Correlation(10);
var indicatorYX = new Correlation(10);
// Correl(X, Y) should equal Correl(Y, X)
var indicatorXY = new Correl(10);
var indicatorYX = new Correl(10);
var gbmX = new GBM(startPrice: 100, mu: 0.02, sigma: 0.2, seed: 12345);
var gbmY = new GBM(startPrice: 50, mu: 0.01, sigma: 0.15, seed: 54321);
@@ -260,8 +260,8 @@ public sealed class CorrelationValidationTests : IDisposable
{
// Correlation is invariant under positive linear transformations
// corr(X, Y) = corr(aX + b, cY + d) when a, c > 0
var indicator1 = new Correlation(10);
var indicator2 = new Correlation(10);
var indicator1 = new Correl(10);
var indicator2 = new Correl(10);
var gbmX = new GBM(startPrice: 100, mu: 0.02, sigma: 0.2, seed: 12345);
var gbmY = new GBM(startPrice: 50, mu: 0.01, sigma: 0.15, seed: 54321);
@@ -283,7 +283,7 @@ public sealed class CorrelationValidationTests : IDisposable
public void Correlation_BoundedProperty_AlwaysBetweenMinusOneAndOne()
{
// Correlation coefficient is always in [-1, 1]
var indicator = new Correlation(10);
var indicator = new Correl(10);
var gbmX = new GBM(startPrice: 100, mu: 0.1, sigma: 0.5, seed: 12345);
var gbmY = new GBM(startPrice: 50, mu: -0.05, sigma: 0.3, seed: 54321);
@@ -304,7 +304,7 @@ public sealed class CorrelationValidationTests : IDisposable
public void Correlation_ZeroVariance_ReturnsNaN()
{
// When one or both series have zero variance, correlation is undefined
var indicator = new Correlation(10);
var indicator = new Correl(10);
for (int i = 0; i < 20; i++)
{
@@ -332,7 +332,7 @@ public sealed class CorrelationValidationTests : IDisposable
// r = Cov(X,Y) / sqrt(Var(X) * Var(Y)) = 1.2 / sqrt(2 * 1.2) = 1.2 / sqrt(2.4)
// = 1.2 / 1.5492 ≈ 0.7746
var indicator = new Correlation(5);
var indicator = new Correl(5);
double[] x = [1, 2, 3, 4, 5];
double[] y = [2, 4, 5, 4, 5];
@@ -346,11 +346,11 @@ public sealed class CorrelationValidationTests : IDisposable
}
[Fact]
public void Correlation_KnownValues_NoCorrelation()
public void Correlation_KnownValues_NoCorrel()
{
// X = [1, 2, 3, 4, 5], Y = [3, 3, 3, 3, 3] (constant)
// Should be NaN (or 0 with special handling)
var indicator = new Correlation(5);
var indicator = new Correl(5);
double[] x = [1, 2, 3, 4, 5];
double[] y = [3, 3, 3, 3, 3];
@@ -383,10 +383,10 @@ public sealed class CorrelationValidationTests : IDisposable
}
// Batch calculation
var batchResult = Correlation.Batch(seriesX, seriesY, 20);
var batchResult = Correl.Batch(seriesX, seriesY, 20);
// Streaming calculation
var streamingIndicator = new Correlation(20);
var streamingIndicator = new Correl(20);
for (int i = 0; i < seriesX.Count; i++)
{
streamingIndicator.Update(seriesX[i].Value, seriesY[i].Value);
@@ -420,10 +420,10 @@ public sealed class CorrelationValidationTests : IDisposable
}
// Span calculation
Correlation.Batch(seriesX, seriesY, output, 20);
Correl.Batch(seriesX, seriesY, output, 20);
// Streaming calculation
var streamingIndicator = new Correlation(20);
var streamingIndicator = new Correl(20);
for (int i = 0; i < length; i++)
{
streamingIndicator.Update(seriesX[i], seriesY[i]);
@@ -443,7 +443,7 @@ public sealed class CorrelationValidationTests : IDisposable
[Fact]
public void Correlation_ResetProducesSameResults()
{
var indicator = new Correlation(20);
var indicator = new Correl(20);
var gbmX = new GBM(startPrice: 100, mu: 0.02, sigma: 0.2, seed: 12345);
var gbmY = new GBM(startPrice: 50, mu: 0.01, sigma: 0.15, seed: 54321);
@@ -475,7 +475,7 @@ public sealed class CorrelationValidationTests : IDisposable
[Fact]
public void Correlation_SlidingWindow_MovesCorrectly()
{
var indicator = new Correlation(5);
var indicator = new Correl(5);
// Build up with known values for period 5
// After 5 values, window should be full
@@ -501,7 +501,7 @@ public sealed class CorrelationValidationTests : IDisposable
[Fact]
public void Correlation_SlidingWindow_DropsOldValues()
{
var indicator = new Correlation(3);
var indicator = new Correl(3);
// First window: perfectly correlated
indicator.Update(1, 2);
@@ -522,7 +522,7 @@ public sealed class CorrelationValidationTests : IDisposable
[Fact]
public void Correlation_LargeValues_MaintainsStability()
{
var indicator = new Correlation(20);
var indicator = new Correl(20);
for (int i = 0; i < 50; i++)
{
@@ -538,7 +538,7 @@ public sealed class CorrelationValidationTests : IDisposable
[Fact]
public void Correlation_SmallValues_MaintainsStability()
{
var indicator = new Correlation(20);
var indicator = new Correl(20);
// Use values that are small but not so small they cause numerical issues
for (int i = 0; i < 50; i++)
@@ -555,7 +555,7 @@ public sealed class CorrelationValidationTests : IDisposable
[Fact]
public void Correlation_MixedMagnitudes_HandlesCorrectly()
{
var indicator = new Correlation(20);
var indicator = new Correl(20);
for (int i = 0; i < 50; i++)
{
@@ -576,7 +576,7 @@ public sealed class CorrelationValidationTests : IDisposable
public void Correlation_HighPositiveCorrelation_DetectedCorrectly()
{
// Create two series with high positive correlation (r ≈ 0.95+)
var indicator = new Correlation(20);
var indicator = new Correl(20);
// Use deterministic data that creates high correlation
for (int i = 0; i < 100; i++)
@@ -593,7 +593,7 @@ public sealed class CorrelationValidationTests : IDisposable
public void Correlation_NegativeCorrelation_DetectedCorrectly()
{
// Create two series with negative correlation
var indicator = new Correlation(20);
var indicator = new Correl(20);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 42);
for (int i = 0; i < 100; i++)
@@ -612,7 +612,7 @@ public sealed class CorrelationValidationTests : IDisposable
// Create two series with weak correlation: pure independent noise, no shared trend.
// Use two independent GBMs (different seeds) and feed their incremental log-returns directly.
// With period=20 and fully independent noise sequences, correlation should be near zero.
var indicator = new Correlation(20);
var indicator = new Correl(20);
var gbmX = new GBM(startPrice: 100.0, sigma: 0.2, seed: 43);
var gbmY = new GBM(startPrice: 100.0, sigma: 0.2, seed: 9871);
var barsX = gbmX.Fetch(101, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
@@ -637,9 +637,9 @@ public sealed class CorrelationValidationTests : IDisposable
[Fact]
public void Correlation_DifferentPeriods_ProduceDifferentResults()
{
var indicator5 = new Correlation(5);
var indicator20 = new Correlation(20);
var indicator50 = new Correlation(50);
var indicator5 = new Correl(5);
var indicator20 = new Correl(20);
var indicator50 = new Correl(50);
var gbmX = new GBM(startPrice: 100, mu: 0.02, sigma: 0.2, seed: 12345);
var gbmY = new GBM(startPrice: 50, mu: 0.01, sigma: 0.15, seed: 54321);
@@ -660,8 +660,8 @@ public sealed class CorrelationValidationTests : IDisposable
[Fact]
public void Correlation_SmallPeriod_MoreVolatile()
{
var indicator3 = new Correlation(3);
var indicator30 = new Correlation(30);
var indicator3 = new Correl(3);
var indicator30 = new Correl(30);
var gbmX = new GBM(startPrice: 100, mu: 0.02, sigma: 0.2, seed: 12345);
var gbmY = new GBM(startPrice: 50, mu: 0.01, sigma: 0.15, seed: 54321);
@@ -732,7 +732,7 @@ public sealed class CorrelationValidationTests : IDisposable
Assert.True(length > 100, $"TALib Correl produced only {length} values");
// QuanTAlib streaming
var corr = new Correlation(period);
var corr = new Correl(period);
var qlValues = new double[_data.Count];
for (int i = 0; i < _data.Count; i++)
{
@@ -770,7 +770,7 @@ public sealed class CorrelationValidationTests : IDisposable
(int offset, int length) = outRange.GetOffsetAndLength(taOut.Length);
var corr = new Correlation(period);
var corr = new Correl(period);
var qlValues = new double[_data.Count];
for (int i = 0; i < _data.Count; i++)
{
+1 -1
View File
@@ -13,7 +13,7 @@
| **PineScript** | [covariance.pine](covariance.pine) |
- Covariance measures the joint variability of two random variables.
- **Similar:** [Correlation](../correlation/Correlation.md), [Beta](../beta/Beta.md) | **Trading note:** Rolling covariance; measures how two assets move together. Foundation of portfolio theory.
- **Similar:** [Correl](../correl/Correl.md), [Beta](../beta/Beta.md) | **Trading note:** Rolling covariance; measures how two assets move together. Foundation of portfolio theory.
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
Covariance measures the joint variability of two random variables. It indicates the direction of the linear relationship between variables.
+1 -1
View File
@@ -13,7 +13,7 @@
| **PineScript** | [granger.pine](granger.pine) |
- The Granger Causality test asks a precise, falsifiable question: does knowing the history of series X improve your ability to predict series Y, bey...
- **Similar:** [Cointegration](../cointegration/Cointegration.md), [Correlation](../correlation/Correlation.md) | **Trading note:** Granger causality test; determines if one time series can forecast another. Lead-lag detection.
- **Similar:** [Cointegration](../cointegration/Cointegration.md), [Correl](../correl/Correl.md) | **Trading note:** Granger causality test; determines if one time series can forecast another. Lead-lag detection.
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
## Introduction
+1 -1
View File
@@ -13,7 +13,7 @@
| **PineScript** | [spearman.pine](spearman.pine) |
- Spearman's ρ (rho) measures the strength and direction of monotonic association between two variables.
- **Similar:** [Correlation](../correlation/Correlation.md), [Kendall](../kendall/Kendall.md) | **Trading note:** Spearman rank correlation; non-parametric, detects monotonic (not just linear) relationships.
- **Similar:** [Correl](../correl/Correl.md), [Kendall](../kendall/Kendall.md) | **Trading note:** Spearman rank correlation; non-parametric, detects monotonic (not just linear) relationships.
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
Spearman's ρ (rho) measures the strength and direction of monotonic association between two variables. Unlike Pearson's correlation, which measures linear relationship, Spearman captures any monotonic relationship. A portfolio of stocks whose returns move monotonically together has different risk than one whose components merely share a linear trend. Spearman detects both.
+1 -1
View File
@@ -13,7 +13,7 @@
| **PineScript** | [theil.pine](theil.pine) |
- The Theil T Index is an information-theoretic measure of inequality (or concentration) within a distribution of positive values.
- **Similar:** [Correlation](../correlation/Correlation.md), [LinReg](../linreg/LinReg.md) | **Trading note:** TheilSen estimator; robust slope calculation using medians of pairwise slopes. Resistant to outliers.
- **Similar:** [Correl](../correl/Correl.md), [LinReg](../linreg/LinReg.md) | **Trading note:** TheilSen estimator; robust slope calculation using medians of pairwise slopes. Resistant to outliers.
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
## Introduction