feat: add new indicators (Decay, Edecay, MinusDi, MinusDm, PlusDi, PlusDm, Maxindex, Minindex, Sarext) and update pine scripts, core libs, validation tests, and python bindings

This commit is contained in:
Miha Kralj
2026-03-09 13:45:46 -07:00
parent 8e43d62cbb
commit 031f1b5fe6
491 changed files with 6156 additions and 5590 deletions
+2 -2
View File
@@ -367,7 +367,7 @@ public sealed class Acf : AbstractBase
for (int j = 0; j < bufferCount; j++)
{
double diff = buffer[j] - mean;
variance += diff * diff;
variance = Math.FusedMultiplyAdd(diff, diff, variance);
}
variance /= bufferCount;
@@ -388,7 +388,7 @@ public sealed class Acf : AbstractBase
int laggedIdx = (effectiveStart + t - lag) % period;
double xt = buffer[currentIdx];
double xtk = buffer[laggedIdx];
autocovariance += (xt - mean) * (xtk - mean);
autocovariance = Math.FusedMultiplyAdd(xt - mean, xtk - mean, autocovariance);
}
autocovariance /= bufferCount;
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Beta Function (BETA)", "BETA", overlay=false)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Cumulative Moving Average", "CMA", overlay=true)
+14 -1
View File
@@ -55,6 +55,7 @@ public sealed class Cointegration : AbstractBase
private const int ResyncInterval = 1000;
private const double Epsilon = 1e-10;
/// <inheritdoc />
public override bool IsHot => _bufferA.IsFull && _hasPrevResidual;
/// <summary>
@@ -109,16 +110,23 @@ public sealed class Cointegration : AbstractBase
/// <summary>
/// Updates with raw double values.
/// </summary>
/// <remarks>
/// Stamps both inputs with <c>DateTime.UtcNow</c> as their timestamp. For
/// deterministic or replay-safe sequences use
/// <see cref="Update(TValue, TValue, bool)"/> with explicit timestamps instead.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TValue Update(double seriesA, double seriesB, bool isNew = true)
{
return Update(new TValue(DateTime.MinValue, seriesA), new TValue(DateTime.MinValue, seriesB), isNew);
return Update(new TValue(DateTime.UtcNow, seriesA), new TValue(DateTime.UtcNow, seriesB), isNew);
}
/// <summary>Not supported. This indicator requires two inputs; use <see cref="Update(TValue, TValue, bool)"/> instead.</summary>
/// <remarks>Not supported for bi-input indicator. Use Update(seriesA, seriesB) instead.</remarks>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("Cointegration requires two inputs (seriesA and seriesB). Use Update(seriesA, seriesB).");
}
/// <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(seriesA, seriesB, period) instead.</remarks>
public override TSeries Update(TSeries source)
{
@@ -398,11 +406,13 @@ public sealed class Cointegration : AbstractBase
_sumDelta2 = FusedMultiplyAdd(delta, delta, _sumDelta2);
}
}
/// <summary>Not supported. This indicator requires two input spans.</summary>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("Cointegration requires two inputs.");
}
/// <inheritdoc />
public override void Reset()
{
_bufferA.Clear();
@@ -473,6 +483,9 @@ public sealed class Cointegration : AbstractBase
}
}
/// <summary>
/// Calculates the ADF cointegration statistic for two time series and returns both the result series and the live indicator instance.
/// </summary>
public static (TSeries Results, Cointegration Indicator) Calculate(TSeries seriesA, TSeries seriesB, int period = 20)
{
if (seriesA.Count != seriesB.Count)
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Cointegration (COINTEGRATION)", "COINTEGRATION", overlay=false)
+14 -1
View File
@@ -45,6 +45,7 @@ public sealed class Correlation : AbstractBase
private const int ResyncInterval = 1000;
private const double Epsilon = 1e-10;
/// <inheritdoc />
public override bool IsHot => _bufferX.Count >= WarmupPeriod;
/// <summary>
@@ -108,16 +109,23 @@ public sealed class Correlation : AbstractBase
/// <summary>
/// Updates with raw double values.
/// </summary>
/// <remarks>
/// Stamps both inputs with <c>DateTime.UtcNow</c> as their timestamp. For
/// deterministic or replay-safe sequences use
/// <see cref="Update(TValue, TValue, bool)"/> with explicit timestamps instead.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TValue Update(double seriesX, double seriesY, bool isNew = true)
{
return Update(new TValue(DateTime.MinValue, seriesX), new TValue(DateTime.MinValue, seriesY), isNew);
return Update(new TValue(DateTime.UtcNow, seriesX), new TValue(DateTime.UtcNow, seriesY), isNew);
}
/// <summary>Not supported. This indicator requires two inputs; use <see cref="Update(TValue, TValue, bool)"/> instead.</summary>
/// <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).");
}
/// <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)
{
@@ -259,11 +267,13 @@ public sealed class Correlation : AbstractBase
_sumXY = FusedMultiplyAdd(x, y, _sumXY);
}
}
/// <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.");
}
/// <inheritdoc />
public override void Reset()
{
_bufferX.Clear();
@@ -323,6 +333,9 @@ 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)
{
if (seriesX.Count != seriesY.Count)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Pearson's Correlation (CORRELATION)", "CORRELATION", overlay=false)
+4 -4
View File
@@ -309,7 +309,7 @@ public sealed class Covariance : AbstractBase
sumX = sumX - oldX + x;
sumY = sumY - oldY + y;
sumXY = sumXY - (oldX * oldY) + (x * y);
sumXY = sumXY - oldX * oldY + x * y;
bufferX[bufferIndex] = x;
bufferY[bufferIndex] = y;
@@ -337,7 +337,7 @@ public sealed class Covariance : AbstractBase
double by = bufferY[k];
recalcSumX += bx;
recalcSumY += by;
recalcSumXY += bx * by;
recalcSumXY = Math.FusedMultiplyAdd(bx, by, recalcSumXY);
}
sumX = recalcSumX;
sumY = recalcSumY;
@@ -477,7 +477,7 @@ public sealed class Covariance : AbstractBase
double y = Unsafe.Add(ref srcYRef, startIdx + k);
recalcSumX += x;
recalcSumY += y;
recalcSumXY += x * y;
recalcSumXY = Math.FusedMultiplyAdd(x, y, recalcSumXY);
}
sumX = recalcSumX;
sumY = recalcSumY;
@@ -513,7 +513,7 @@ public sealed class Covariance : AbstractBase
sumX = sumX - oldX + x;
sumY = sumY - oldY + y;
sumXY = sumXY - (oldX * oldY) + (x * y);
sumXY = sumXY - oldX * oldY + x * y;
double numerator = sumXY - sumX * sumY * invN;
Unsafe.Add(ref outRef, i) = numerator * invDenom;
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Covariance (COVARIANCE)", "COVARIANCE", overlay=false)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Entropy (ENTROPY)", "ENTROPY", overlay=false)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Geometric Mean (GEOMEAN)", "GEOMEAN", overlay=true)
+13
View File
@@ -48,6 +48,7 @@ public sealed class Granger : AbstractBase
private const int ResyncInterval = 1000;
private const double Epsilon = 1e-10;
/// <inheritdoc />
public override bool IsHot => _windowY.IsFull;
/// <summary>
@@ -103,16 +104,23 @@ public sealed class Granger : AbstractBase
/// <summary>
/// Updates with raw double values.
/// </summary>
/// <remarks>
/// Stamps both inputs with <c>DateTime.UtcNow</c> as their timestamp. For
/// deterministic or replay-safe sequences use
/// <see cref="Update(TValue, TValue, bool)"/> with explicit timestamps instead.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TValue Update(double seriesY, double seriesX, bool isNew = true)
{
return Update(new TValue(DateTime.UtcNow, seriesY), new TValue(DateTime.UtcNow, seriesX), isNew);
}
/// <summary>Not supported. This indicator requires two inputs; use <see cref="Update(TValue, TValue, bool)"/> instead.</summary>
/// <remarks>Not supported for dual-input indicator. Use Update(seriesY, seriesX) instead.</remarks>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("Granger requires two inputs (seriesY and seriesX). Use Update(seriesY, seriesX).");
}
/// <summary>Not supported. This indicator requires two inputs; use <see cref="Batch(TSeries, TSeries, int)"/> instead.</summary>
/// <remarks>Not supported for dual-input indicator. Use Batch(seriesY, seriesX, period) instead.</remarks>
public override TSeries Update(TSeries source)
{
@@ -366,11 +374,13 @@ public sealed class Granger : AbstractBase
_sumYLagXLag = FusedMultiplyAdd(yLag, xLag, _sumYLagXLag);
}
}
/// <summary>Not supported. This indicator requires two input spans.</summary>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("Granger requires two inputs.");
}
/// <inheritdoc />
public override void Reset()
{
_bufferY.Clear();
@@ -465,6 +475,9 @@ public sealed class Granger : AbstractBase
}
}
/// <summary>
/// Calculates the Granger Causality F-statistic for two time series and returns both the result series and the live indicator instance.
/// </summary>
public static (TSeries Results, Granger Indicator) Calculate(TSeries seriesY, TSeries seriesX, int period = 20)
{
if (seriesY.Count != seriesX.Count)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Granger Causality Test (GRANGER)", "GRANGER", overlay=false, precision=4)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Harmonic Mean (HARMEAN)", "HARMEAN", overlay=false, precision=6)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Hurst Exponent (HURST)", "HURST", overlay=false, precision=4)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Interquartile Range (IQR)", "IQR", overlay=false, precision=4)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Jarque-Bera Test (JB)", "JB", overlay=false, precision=4)
+13
View File
@@ -34,6 +34,7 @@ public sealed class Kendall : AbstractBase
private const double Epsilon = 1e-10;
/// <inheritdoc />
public override bool IsHot => _bufferX.Count >= 2;
/// <summary>
@@ -88,16 +89,23 @@ public sealed class Kendall : AbstractBase
/// <summary>
/// Updates with raw double values.
/// </summary>
/// <remarks>
/// Stamps both inputs with <c>DateTime.UtcNow</c> as their timestamp. For
/// deterministic or replay-safe sequences use
/// <see cref="Update(TValue, TValue, bool)"/> with explicit timestamps instead.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TValue Update(double seriesX, double seriesY, bool isNew = true)
{
return Update(new TValue(DateTime.UtcNow, seriesX), new TValue(DateTime.UtcNow, seriesY), isNew);
}
/// <summary>Not supported. This indicator requires two inputs; use <see cref="Update(TValue, TValue, bool)"/> instead.</summary>
/// <remarks>Not supported for dual-input indicator. Use Update(seriesX, seriesY) instead.</remarks>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("Kendall 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 dual-input indicator. Use Batch(seriesX, seriesY, period) instead.</remarks>
public override TSeries Update(TSeries source)
{
@@ -169,11 +177,13 @@ public sealed class Kendall : AbstractBase
return (concordant - discordant) / denominator;
}
/// <summary>Not supported. This indicator requires two input spans.</summary>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("Kendall requires two inputs.");
}
/// <inheritdoc />
public override void Reset()
{
_bufferX.Clear();
@@ -268,6 +278,9 @@ public sealed class Kendall : AbstractBase
}
}
/// <summary>
/// Calculates Kendall Tau-a for two time series and returns both the result series and the live indicator instance.
/// </summary>
public static (TSeries Results, Kendall Indicator) Calculate(TSeries seriesX, TSeries seriesY, int period = 20)
{
var indicator = new Kendall(period);
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Kendall Rank Correlation (KENDALL)", "KENDALL", overlay=false, precision=4)
+10 -10
View File
@@ -256,8 +256,8 @@ public sealed class Kurtosis : AbstractBase
double valSq = val * val;
sum += val;
sumSq += valSq;
sumCu += valSq * val;
sumQu += valSq * valSq;
sumCu = Math.FusedMultiplyAdd(valSq, val, sumCu);
sumQu = Math.FusedMultiplyAdd(valSq, valSq, sumQu);
}
_sum = sum;
_sumSq = sumSq;
@@ -415,8 +415,8 @@ public sealed class Kurtosis : AbstractBase
double oldSq = oldVal * oldVal;
sum = sum - oldVal + val;
sumSq = sumSq - oldSq + valSq;
sumCu = sumCu - (oldSq * oldVal) + (valSq * val);
sumQu = sumQu - (oldSq * oldSq) + (valSq * valSq);
sumCu = sumCu - oldSq * oldVal + valSq * val;
sumQu = sumQu - oldSq * oldSq + valSq * valSq;
output[i] = CalculateKurtosisFromSums(sum, sumSq, sumCu, sumQu, period, isPopulation);
@@ -440,8 +440,8 @@ public sealed class Kurtosis : AbstractBase
double vSq = v * v;
recalcSum += v;
recalcSumSq += vSq;
recalcSumCu += vSq * v;
recalcSumQu += vSq * vSq;
recalcSumCu = Math.FusedMultiplyAdd(vSq, v, recalcSumCu);
recalcSumQu = Math.FusedMultiplyAdd(vSq, vSq, recalcSumQu);
}
sum = recalcSum;
sumSq = recalcSumSq;
@@ -633,8 +633,8 @@ public sealed class Kurtosis : AbstractBase
double vSq = v * v;
recalcSum += v;
recalcSumSq += vSq;
recalcSumCu += vSq * v;
recalcSumQu += vSq * vSq;
recalcSumCu = Math.FusedMultiplyAdd(vSq, v, recalcSumCu);
recalcSumQu = Math.FusedMultiplyAdd(vSq, vSq, recalcSumQu);
}
sum = recalcSum;
sumSq = recalcSumSq;
@@ -652,8 +652,8 @@ public sealed class Kurtosis : AbstractBase
double oldSq = oldVal * oldVal;
sum = sum - oldVal + val;
sumSq = sumSq - oldSq + valSq;
sumCu = sumCu - (oldSq * oldVal) + (valSq * val);
sumQu = sumQu - (oldSq * oldSq) + (valSq * valSq);
sumCu = Math.FusedMultiplyAdd(valSq, val, Math.FusedMultiplyAdd(-oldSq, oldVal, sumCu));
sumQu = Math.FusedMultiplyAdd(valSq, valSq, Math.FusedMultiplyAdd(-oldSq, oldSq, sumQu));
Unsafe.Add(ref outRef, i) = CalculateKurtosisFromSums(sum, sumSq, sumCu, sumQu, n, isPopulation);
}
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Kurtosis, tailedness (KURTOSIS)", "KURTOSIS", overlay=false, precision=8)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Linear Regression (LINREG)", "LINREG", overlay=false, precision=8)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Mean Deviation (MEANDEV)", "MEANDEV", overlay=false, precision=8)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Median", "MEDIAN", overlay=false, precision=8)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Mode", "MODE", overlay=false)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Percentile", "PERCENTILE", overlay=true, precision=8)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Polynomial Fitting (POLYFIT)", "POLYFIT", overlay=true, precision=8)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Quantile (QUANTILE)", shorttitle="QUANTILE", overlay=true, precision=8)
+10 -10
View File
@@ -201,8 +201,8 @@ public sealed class Skew : AbstractBase
{
double val = span[i];
sum += val;
sumSq += val * val;
sumCu += val * val * val;
sumSq = Math.FusedMultiplyAdd(val, val, sumSq);
sumCu = Math.FusedMultiplyAdd(val * val, val, sumCu);
}
_sum = sum;
_sumSq = sumSq;
@@ -312,8 +312,8 @@ public sealed class Skew : AbstractBase
}
sum = sum - oldVal + val;
sumSq = sumSq - (oldVal * oldVal) + (val * val);
sumCu = sumCu - (oldVal * oldVal * oldVal) + (val * val * val);
sumSq = sumSq - oldVal * oldVal + val * val;
sumCu = sumCu - oldVal * oldVal * oldVal + val * val * val;
output[i] = CalculateSkewFromSums(sum, sumSq, sumCu, period, isPopulation);
@@ -334,8 +334,8 @@ public sealed class Skew : AbstractBase
}
recalcSum += v;
recalcSumSq += v * v;
recalcSumCu += v * v * v;
recalcSumSq = Math.FusedMultiplyAdd(v, v, recalcSumSq);
recalcSumCu = Math.FusedMultiplyAdd(v * v, v, recalcSumCu);
}
sum = recalcSum;
sumSq = recalcSumSq;
@@ -533,8 +533,8 @@ public sealed class Skew : AbstractBase
{
double v = Unsafe.Add(ref srcRef, startIdx + k);
recalcSum += v;
recalcSumSq += v * v;
recalcSumCu += v * v * v;
recalcSumSq = Math.FusedMultiplyAdd(v, v, recalcSumSq);
recalcSumCu = Math.FusedMultiplyAdd(v * v, v, recalcSumCu);
}
sum = recalcSum;
sumSq = recalcSumSq;
@@ -548,8 +548,8 @@ public sealed class Skew : AbstractBase
double oldVal = Unsafe.Add(ref srcRef, i - period);
sum = sum - oldVal + val;
sumSq = sumSq - (oldVal * oldVal) + (val * val);
sumCu = sumCu - (oldVal * oldVal * oldVal) + (val * val * val);
sumSq = Math.FusedMultiplyAdd(val, val, Math.FusedMultiplyAdd(-oldVal, oldVal, sumSq));
sumCu = Math.FusedMultiplyAdd(val * val, val, Math.FusedMultiplyAdd(-(oldVal * oldVal), oldVal, sumCu));
Unsafe.Add(ref outRef, i) = CalculateSkewFromSums(sum, sumSq, sumCu, n, isPopulation);
}
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Skewness (SKEW)", "SKEW", overlay=false, precision=6)
+13
View File
@@ -39,6 +39,7 @@ public sealed class Spearman : AbstractBase
private const double Epsilon = 1e-10;
private const int StackallocThreshold = 256;
/// <inheritdoc />
public override bool IsHot => _bufferX.Count >= 2;
/// <summary>
@@ -93,16 +94,23 @@ public sealed class Spearman : AbstractBase
/// <summary>
/// Updates with raw double values.
/// </summary>
/// <remarks>
/// Stamps both inputs with <c>DateTime.UtcNow</c> as their timestamp. For
/// deterministic or replay-safe sequences use
/// <see cref="Update(TValue, TValue, bool)"/> with explicit timestamps instead.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TValue Update(double seriesX, double seriesY, bool isNew = true)
{
return Update(new TValue(DateTime.UtcNow, seriesX), new TValue(DateTime.UtcNow, seriesY), isNew);
}
/// <summary>Not supported. This indicator requires two inputs; use <see cref="Update(TValue, TValue, bool)"/> instead.</summary>
/// <remarks>Not supported for dual-input indicator. Use Update(seriesX, seriesY) instead.</remarks>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("Spearman 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 dual-input indicator. Use Batch(seriesX, seriesY, period) instead.</remarks>
public override TSeries Update(TSeries source)
{
@@ -232,11 +240,13 @@ public sealed class Spearman : AbstractBase
ranks[i] = countSmaller + (countEqual - 1) * 0.5 + 1.0;
}
}
/// <summary>Not supported. This indicator requires two input spans.</summary>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("Spearman requires two inputs.");
}
/// <inheritdoc />
public override void Reset()
{
_bufferX.Clear();
@@ -331,6 +341,9 @@ public sealed class Spearman : AbstractBase
}
}
/// <summary>
/// Calculates Spearman's ρ for two time series and returns both the result series and the live indicator instance.
/// </summary>
public static (TSeries Results, Spearman Indicator) Calculate(TSeries seriesX, TSeries seriesY, int period = 20)
{
var indicator = new Spearman(period);
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Spearman Rank Correlation (SPEARMAN)", "SPEARMAN", overlay=false, precision=4)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Standard Deviation (STDDEV)", "STDDEV", overlay=false)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Standard Error of Regression (STDERR)", "STDERR", overlay=false, precision=8)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Rolling Sum", "SUM", overlay=false)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Theil Index (THEIL)", "THEIL", overlay=false, precision=6)
+3 -3
View File
@@ -449,7 +449,7 @@ public sealed class Variance : AbstractBase
{
double v = Unsafe.Add(ref srcRef, startIdx + k);
recalcSum += v;
recalcSumSq += v * v;
recalcSumSq = Math.FusedMultiplyAdd(v, v, recalcSumSq);
}
sum = recalcSum;
sumSq = recalcSumSq;
@@ -553,7 +553,7 @@ public sealed class Variance : AbstractBase
{
double v = Unsafe.Add(ref srcRef, startIdx + k);
recalcSum += v;
recalcSumSq += v * v;
recalcSumSq = Math.FusedMultiplyAdd(v, v, recalcSumSq);
}
sum = recalcSum;
sumSq = recalcSumSq;
@@ -676,7 +676,7 @@ public sealed class Variance : AbstractBase
{
double v = Unsafe.Add(ref srcRef, startIdx + k);
recalcSum += v;
recalcSumSq += v * v;
recalcSumSq = Math.FusedMultiplyAdd(v, v, recalcSumSq);
}
sum = recalcSum;
sumSq = recalcSumSq;
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Variance, Dispersion or Spread (VARIANCE)", "VARIANCE", overlay=false)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Weighted Average (WAVG)", "WAVG", overlay=true)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Z-Score (ZSCORE)", "ZSCORE", overlay=false)
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("One-Sample t-Test (ZTEST)", "t-TEST", overlay=false)