normalization of methods

This commit is contained in:
Miha Kralj
2026-02-10 21:33:16 -08:00
parent 915d7a007b
commit 6d6259a47d
527 changed files with 10525 additions and 2123 deletions
+10 -10
View File
@@ -44,7 +44,7 @@ public class DemaTests
}
// Act
var demaSeries = Dema.Calculate(source, period);
var demaSeries = Dema.Batch(source, period);
var demaObj = new Dema(period);
// Assert
@@ -71,7 +71,7 @@ public class DemaTests
}
// Act
Dema.Calculate(source, output, period);
Dema.Batch(source, output, period);
var demaObj = new Dema(period);
// Assert
@@ -130,7 +130,7 @@ public class DemaTests
}
// Act
var demaSeries = Dema.Calculate(source, alpha);
var demaSeries = Dema.Batch(source, alpha);
var demaObj = new Dema(alpha);
// Assert
@@ -157,7 +157,7 @@ public class DemaTests
}
// Act
Dema.Calculate(source, output, alpha);
Dema.Batch(source, output, alpha);
var demaObj = new Dema(alpha);
// Assert
@@ -250,8 +250,8 @@ public class DemaTests
double[] output = new double[5];
double[] wrongSizeOutput = new double[3];
Assert.Throws<ArgumentException>(() => Dema.Calculate(source.AsSpan(), output.AsSpan(), 0));
Assert.Throws<ArgumentException>(() => Dema.Calculate(source.AsSpan(), wrongSizeOutput.AsSpan(), 3));
Assert.Throws<ArgumentException>(() => Dema.Batch(source.AsSpan(), output.AsSpan(), 0));
Assert.Throws<ArgumentException>(() => Dema.Batch(source.AsSpan(), wrongSizeOutput.AsSpan(), 3));
}
[Fact]
@@ -260,7 +260,7 @@ public class DemaTests
double[] source = [100, 110, double.NaN, 120, 130];
double[] output = new double[5];
Dema.Calculate(source.AsSpan(), output.AsSpan(), 3);
Dema.Batch(source.AsSpan(), output.AsSpan(), 3);
foreach (var val in output)
{
@@ -278,14 +278,14 @@ public class DemaTests
var series = bars.Close;
// 1. Batch Mode
var batchSeries = Dema.Calculate(series, period);
var batchSeries = Dema.Batch(series, period);
double expected = batchSeries.Last.Value;
// 2. Span Mode
var tValues = series.Values.ToArray();
var spanInput = new ReadOnlySpan<double>(tValues);
var spanOutput = new double[tValues.Length];
Dema.Calculate(spanInput, spanOutput, period);
Dema.Batch(spanInput, spanOutput, period);
double spanResult = spanOutput[^1];
// 3. Streaming Mode
@@ -317,7 +317,7 @@ public class DemaTests
double[] source = { double.NaN, double.NaN, 10.0, 11.0, 12.0 };
double[] output = new double[source.Length];
Dema.Calculate(source, output, 3);
Dema.Batch(source, output, 3);
// We expect the first two outputs to be NaN because the input was NaN
Assert.True(double.IsNaN(output[0]), $"Output[0] should be NaN, but was {output[0]}");
+1 -1
View File
@@ -140,7 +140,7 @@ public sealed class DemaValidationTests : IDisposable
{
// Calculate QuanTAlib DEMA (Span API)
double[] qOutput = new double[sourceData.Length];
global::QuanTAlib.Dema.Calculate(sourceData.AsSpan(), qOutput.AsSpan(), period);
global::QuanTAlib.Dema.Batch(sourceData.AsSpan(), qOutput.AsSpan(), period);
// Calculate TA-Lib DEMA
var retCode = TALib.Functions.Dema<double>(sourceData, 0..^0, talibOutput, out var outRange, period);
+13 -6
View File
@@ -230,19 +230,19 @@ public sealed class Dema : AbstractBase
return result;
}
public static TSeries Calculate(TSeries source, int period)
public static TSeries Batch(TSeries source, int period)
{
var dema = new Dema(period);
return dema.Update(source);
}
public static TSeries Calculate(TSeries source, double alpha)
public static TSeries Batch(TSeries source, double alpha)
{
var dema = new Dema(alpha);
return dema.Update(source);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, int period)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period)
{
if (period <= 0)
{
@@ -250,10 +250,10 @@ public sealed class Dema : AbstractBase
}
double alpha = 2.0 / (period + 1);
Calculate(source, output, alpha);
Batch(source, output, alpha);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, double alpha)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, double alpha)
{
if (source.Length != output.Length)
{
@@ -348,6 +348,13 @@ public sealed class Dema : AbstractBase
}
}
public static (TSeries Results, Dema Indicator) Calculate(TSeries source, int period)
{
var indicator = new Dema(period);
TSeries results = indicator.Update(source);
return (results, indicator);
}
public override void Reset()
{
_state1 = EmaState.New();
@@ -369,4 +376,4 @@ public sealed class Dema : AbstractBase
}
private void Handle(object? sender, in TValueEventArgs e) => Update(e.Value, e.IsNew);
}
}
+6 -6
View File
@@ -352,7 +352,7 @@ public class DsmaTests
// Act - Span
var spanOutput = new double[values.Length];
Dsma.Calculate(values, spanOutput, period, scale);
Dsma.Batch(values, spanOutput, period, scale);
// Assert
for (int i = 0; i < values.Length; i++)
@@ -386,7 +386,7 @@ public class DsmaTests
// Act - Span
var spanOutput = new double[values.Length];
Dsma.Calculate(values, spanOutput, period, scale);
Dsma.Batch(values, spanOutput, period, scale);
// Assert
for (int i = 0; i < values.Length; i++)
@@ -439,7 +439,7 @@ public class DsmaTests
// Act & Assert
var ex = Assert.Throws<ArgumentException>(() =>
Dsma.Calculate(source, shortOutput, period: 10));
Dsma.Batch(source, shortOutput, period: 10));
Assert.Equal("output", ex.ParamName);
}
@@ -457,7 +457,7 @@ public class DsmaTests
var output = new double[50];
// Act
Dsma.Calculate(values, output, period: 10, scaleFactor: 0.5);
Dsma.Batch(values, output, period: 10, scaleFactor: 0.5);
// Assert
Assert.All(output, val => Assert.True(double.IsFinite(val)));
@@ -477,7 +477,7 @@ public class DsmaTests
var output = new double[100];
// Act
Dsma.Calculate(values, output, period: 10, scaleFactor: 0.5);
Dsma.Batch(values, output, period: 10, scaleFactor: 0.5);
// Assert
Assert.All(output.Take(50), val => Assert.True(double.IsFinite(val)));
@@ -493,7 +493,7 @@ public class DsmaTests
var output = new double[20];
// Act
Dsma.Calculate(values, output, period: 5, scaleFactor: 0.5);
Dsma.Batch(values, output, period: 5, scaleFactor: 0.5);
// Assert
Assert.All(output, val => Assert.True(double.IsFinite(val)));
+9 -2
View File
@@ -316,7 +316,7 @@ public sealed class Dsma : AbstractBase
/// <param name="period">Lookback period (≥2)</param>
/// <param name="scaleFactor">Scaling factor (0.01-0.9)</param>
/// <exception cref="ArgumentException">If output span is shorter than source</exception>
public static void Calculate(ReadOnlySpan<double> source,
public static void Batch(ReadOnlySpan<double> source,
Span<double> output,
int period,
double scaleFactor = 0.5)
@@ -332,4 +332,11 @@ public sealed class Dsma : AbstractBase
output[i] = dsma.Step(source[i], isNew: true);
}
}
}
public static (TSeries Results, Dsma Indicator) Calculate(TSeries source, int period, double scaleFactor = 0.5)
{
var indicator = new Dsma(period, scaleFactor);
TSeries results = indicator.Update(source);
return (results, indicator);
}
}
+7 -7
View File
@@ -487,12 +487,6 @@ public sealed class Ema : AbstractBase
/// <param name="source">Historical time series</param>
/// <param name="period">EMA Period</param>
/// <returns>A tuple containing the full calculation results and the hot indicator instance</returns>
public static (TSeries Results, Ema Indicator) Calculate(TSeries source, int period)
{
var ema = new Ema(period);
TSeries results = ema.Update(source);
return (results, ema);
}
/// <summary>
/// Calculates EMA for the entire series using a new instance.
@@ -580,6 +574,12 @@ public sealed class Ema : AbstractBase
CalculateCore(source, output, alpha, ref state, ref lastValid);
}
public static (TSeries Results, Ema Indicator) Calculate(TSeries source, int period)
{
var ema = new Ema(period);
TSeries results = ema.Update(source);
return (results, ema);
}
/// <summary>
/// Resets the EMA state.
@@ -592,4 +592,4 @@ public sealed class Ema : AbstractBase
_p_lastValidValue = 0;
Last = default;
}
}
}
+1 -1
View File
@@ -101,7 +101,7 @@ public class FramaTests
var series = BuildSeries(60, seed: 21);
double[] output = new double[series.Count];
Frama.Calculate(series.High.Values, series.Low.Values, period, output);
Frama.Batch(series.High.Values, series.Low.Values, period, output);
TSeries batch = FramaBatch(series, period);
for (int i = 0; i < series.Count; i++)
@@ -46,7 +46,7 @@ public class FramaValidationTests
double[] reference = new double[series.Count];
ReferenceFrama(series.High.Values, series.Low.Values, period, reference);
Frama.Calculate(series.High.Values, series.Low.Values, period, output);
Frama.Batch(series.High.Values, series.Low.Values, period, output);
for (int i = 0; i < series.Count; i++)
{
+11 -4
View File
@@ -193,7 +193,7 @@ public sealed class Frama : ITValuePublisher, IDisposable
int len = source.Count;
var v = new double[len];
Calculate(source.High.Values, source.Low.Values, _periodEven, v);
Batch(source.High.Values, source.Low.Values, _periodEven, v);
var tList = new List<long>(len);
var times = source.Open.Times;
@@ -242,7 +242,7 @@ public sealed class Frama : ITValuePublisher, IDisposable
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Handle(object? sender, in TValueEventArgs args) => Update(args.Value, args.IsNew);
public static void Calculate(ReadOnlySpan<double> high, ReadOnlySpan<double> low, int period, Span<double> output)
public static void Batch(ReadOnlySpan<double> high, ReadOnlySpan<double> low, int period, Span<double> output)
{
if (high.Length != low.Length || high.Length != output.Length)
{
@@ -260,7 +260,7 @@ public sealed class Frama : ITValuePublisher, IDisposable
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, int period)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period)
{
if (source.Length != output.Length)
{
@@ -286,7 +286,7 @@ public sealed class Frama : ITValuePublisher, IDisposable
int len = source.Count;
var v = new double[len];
Calculate(source.High.Values, source.Low.Values, period, v);
Batch(source.High.Values, source.Low.Values, period, v);
var tList = new List<long>(len);
var times = source.Open.Times;
@@ -298,6 +298,13 @@ public sealed class Frama : ITValuePublisher, IDisposable
return new TSeries(tList, [.. v]);
}
public static (TSeries Results, Frama Indicator) Calculate(TBarSeries source, int period)
{
var indicator = new Frama(period);
TSeries results = indicator.Update(source);
return (results, indicator);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static double GetMax(RingBuffer buffer, int length, int startOffset = -1)
{
+4 -4
View File
@@ -91,7 +91,7 @@ public class HemaTests
int period = 12;
TSeries series = BuildSeries(120, seed: 11);
TSeries batch = Hema.Calculate(series, period);
TSeries batch = Hema.Batch(series, period);
var hema = new Hema(period);
var streamValues = new List<double>(series.Count);
@@ -114,8 +114,8 @@ public class HemaTests
double[] values = series.Values.ToArray();
var output = new double[values.Length];
Hema.Calculate(values, output, period);
TSeries batch = Hema.Calculate(series, period);
Hema.Batch(values, output, period);
TSeries batch = Hema.Batch(series, period);
for (int i = 0; i < values.Length; i++)
{
@@ -153,7 +153,7 @@ public class HemaTests
double[] source = [1, 2, 3, 4, 5];
double[] output = new double[3];
var ex = Assert.Throws<ArgumentException>(() => Hema.Calculate(source, output, 10));
var ex = Assert.Throws<ArgumentException>(() => Hema.Batch(source, output, 10));
Assert.Equal("output", ex.ParamName);
}
+2 -2
View File
@@ -29,7 +29,7 @@ public class HemaValidationTests
double[] reference = new double[series.Count];
ReferenceHema(series.Values, reference, period);
TSeries batch = Hema.Calculate(series, period);
TSeries batch = Hema.Batch(series, period);
for (int i = 0; i < series.Count; i++)
{
@@ -47,7 +47,7 @@ public class HemaValidationTests
var reference = new double[values.Length];
ReferenceHema(values, reference, period);
Hema.Calculate(values, output, period);
Hema.Batch(values, output, period);
for (int i = 0; i < values.Length; i++)
{
+10 -3
View File
@@ -276,13 +276,13 @@ public sealed class Hema : AbstractBase
return fastResult;
}
public static TSeries Calculate(TSeries source, int period)
public static TSeries Batch(TSeries source, int period)
{
var hema = new Hema(period);
return hema.Update(source);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, int period)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period)
{
if (source.Length != output.Length)
{
@@ -406,6 +406,13 @@ public sealed class Hema : AbstractBase
}
}
public static (TSeries Results, Hema Indicator) Calculate(TSeries source, int period)
{
var indicator = new Hema(period);
TSeries results = indicator.Update(source);
return (results, indicator);
}
public override void Reset()
{
_state = State.New();
@@ -473,4 +480,4 @@ public sealed class Hema : AbstractBase
return (int)Math.Ceiling(steps);
}
}
}
+4 -4
View File
@@ -57,7 +57,7 @@ public class HtitTests
var spanInput = data.Values.ToArray();
var spanOutput = new double[spanInput.Length];
Htit.Calculate(spanInput, spanOutput);
Htit.Batch(spanInput, spanOutput);
for (int i = 0; i < resultSeries.Count; i++)
{
@@ -134,7 +134,7 @@ public class HtitTests
double[] source = [1, 2, 3, 4, 5];
double[] wrongSizeOutput = new double[3];
Assert.Throws<ArgumentException>(() => Htit.Calculate(source.AsSpan(), wrongSizeOutput.AsSpan()));
Assert.Throws<ArgumentException>(() => Htit.Batch(source.AsSpan(), wrongSizeOutput.AsSpan()));
}
[Fact]
@@ -143,7 +143,7 @@ public class HtitTests
double[] source = [100, 110, double.NaN, 120, 130];
double[] output = new double[5];
Htit.Calculate(source.AsSpan(), output.AsSpan());
Htit.Batch(source.AsSpan(), output.AsSpan());
foreach (var val in output)
{
@@ -167,7 +167,7 @@ public class HtitTests
var tValues = series.Values.ToArray();
var spanInput = new ReadOnlySpan<double>(tValues);
var spanOutput = new double[tValues.Length];
Htit.Calculate(spanInput, spanOutput);
Htit.Batch(spanInput, spanOutput);
double spanResult = spanOutput[^1];
// 3. Streaming Mode
+9 -2
View File
@@ -308,7 +308,7 @@ public sealed class Htit : AbstractBase
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Calculate(ReadOnlySpan<double> source, Span<double> output)
public static void Batch(ReadOnlySpan<double> source, Span<double> output)
{
if (source.Length != output.Length)
{
@@ -512,4 +512,11 @@ public sealed class Htit : AbstractBase
}
}
}
}
public static (TSeries Results, Htit Indicator) Calculate(TSeries source)
{
var indicator = new Htit();
TSeries results = indicator.Update(source);
return (results, indicator);
}
}
+6 -6
View File
@@ -32,11 +32,11 @@ public class JmaTests
double[] wrongSizeOutput = new double[3];
// Period must be > 0
Assert.Throws<ArgumentOutOfRangeException>(() => Jma.Calculate(source.AsSpan(), output.AsSpan(), 0, 0, 1.0));
Assert.Throws<ArgumentOutOfRangeException>(() => Jma.Calculate(source.AsSpan(), output.AsSpan(), -1, 0, 1.0));
Assert.Throws<ArgumentOutOfRangeException>(() => Jma.Batch(source.AsSpan(), output.AsSpan(), 0, 0, 1.0));
Assert.Throws<ArgumentOutOfRangeException>(() => Jma.Batch(source.AsSpan(), output.AsSpan(), -1, 0, 1.0));
// Output must be same length as source
Assert.Throws<ArgumentException>(() => Jma.Calculate(source.AsSpan(), wrongSizeOutput.AsSpan(), 3, 0, 1.0));
Assert.Throws<ArgumentException>(() => Jma.Batch(source.AsSpan(), wrongSizeOutput.AsSpan(), 3, 0, 1.0));
}
[Fact]
@@ -163,7 +163,7 @@ public class JmaTests
var tseriesResult = Jma.Batch(series, 10);
// Calculate with Span API
Jma.Calculate(source.AsSpan(), output.AsSpan(), 10);
Jma.Batch(source.AsSpan(), output.AsSpan(), 10);
// Compare results
for (int i = 0; i < 100; i++)
@@ -189,7 +189,7 @@ public class JmaTests
var tValues = series.Values.ToArray();
var spanInput = new ReadOnlySpan<double>(tValues);
var spanOutput = new double[tValues.Length];
Jma.Calculate(spanInput, spanOutput, period);
Jma.Batch(spanInput, spanOutput, period);
double spanResult = spanOutput[^1];
// 3. Streaming Mode
@@ -261,7 +261,7 @@ public class JmaTests
double[] source = [100, 110, double.NaN, 120, 130];
double[] output = new double[5];
Jma.Calculate(source.AsSpan(), output.AsSpan(), 3);
Jma.Batch(source.AsSpan(), output.AsSpan(), 3);
foreach (var val in output)
{
+21 -9
View File
@@ -36,6 +36,7 @@ public sealed class Jma : AbstractBase
private readonly RingBuffer _volBuffer;
private readonly TValuePublishedHandler _handler;
private readonly ITValuePublisher? _source;
private bool _disposed;
// Streaming state (current + previous snapshot for isNew=false)
private State _state;
@@ -203,11 +204,11 @@ public sealed class Jma : AbstractBase
private double CalculateJma(double value)
{
// 1. Local deviation: |price - {UpperBand, LowerBand}|
double diffA = value - _state.UpperBand;
double diffB = value - _state.LowerBand;
double absA = Math.Abs(diffA);
double absB = Math.Abs(diffB);
double absValue = absA > absB ? absA : absB;
double uBand = value - _state.UpperBand;
double lBand = value - _state.LowerBand;
double absUBand = Math.Abs(uBand);
double absLBand = Math.Abs(lBand);
double absValue = absUBand > absLBand ? absUBand : absLBand;
double deviation = absValue + 1e-10;
// 2. 10-bar SMA of local deviation -> "volatility"
@@ -338,9 +339,13 @@ public sealed class Jma : AbstractBase
protected override void Dispose(bool disposing)
{
if (disposing && _source != null)
if (!_disposed)
{
_source.Pub -= _handler;
if (disposing && _source != null)
{
_source.Pub -= _handler;
}
_disposed = true;
}
base.Dispose(disposing);
}
@@ -362,7 +367,7 @@ public sealed class Jma : AbstractBase
/// <summary>
/// Static helper compatible with your existing signature.
/// </summary>
public static void Calculate(ReadOnlySpan<double> source,
public static void Batch(ReadOnlySpan<double> source,
Span<double> output,
int period,
int phase = 0,
@@ -385,6 +390,13 @@ public sealed class Jma : AbstractBase
}
}
public static (TSeries Results, Jma Indicator) Calculate(TSeries source, int period, int phase = 0, double power = 0.45)
{
var indicator = new Jma(period, phase, power);
TSeries results = indicator.Update(source);
return (results, indicator);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private double CalculateTrimmedMean(double fallback)
{
@@ -431,4 +443,4 @@ public sealed class Jma : AbstractBase
int len = end - start + 1;
return sorted.Slice(start, len).SumSIMD() / len;
}
}
}
+5 -5
View File
@@ -86,7 +86,7 @@ public class KamaTests
var instanceResults = new Kama(10).Update(series);
var staticResults = new double[series.Count];
Kama.Calculate(series.Values.ToArray().AsSpan(), staticResults.AsSpan(), 10);
Kama.Batch(series.Values.ToArray().AsSpan(), staticResults.AsSpan(), 10);
for (int i = 0; i < instanceResults.Count; i++)
{
@@ -214,8 +214,8 @@ public class KamaTests
double[] output = new double[5];
double[] wrongSizeOutput = new double[3];
Assert.Throws<ArgumentException>(() => Kama.Calculate(source.AsSpan(), output.AsSpan(), 0));
Assert.Throws<ArgumentException>(() => Kama.Calculate(source.AsSpan(), wrongSizeOutput.AsSpan(), 3));
Assert.Throws<ArgumentException>(() => Kama.Batch(source.AsSpan(), output.AsSpan(), 0));
Assert.Throws<ArgumentException>(() => Kama.Batch(source.AsSpan(), wrongSizeOutput.AsSpan(), 3));
}
[Fact]
@@ -224,7 +224,7 @@ public class KamaTests
double[] source = [100, 110, double.NaN, 120, 130];
double[] output = new double[5];
Kama.Calculate(source.AsSpan(), output.AsSpan(), 3);
Kama.Batch(source.AsSpan(), output.AsSpan(), 3);
foreach (var val in output)
{
@@ -249,7 +249,7 @@ public class KamaTests
var tValues = series.Values.ToArray();
var spanInput = new ReadOnlySpan<double>(tValues);
var spanOutput = new double[tValues.Length];
Kama.Calculate(spanInput, spanOutput, period);
Kama.Batch(spanInput, spanOutput, period);
double spanResult = spanOutput[^1];
// 3. Streaming Mode
+1 -1
View File
@@ -97,7 +97,7 @@ public sealed class KamaValidationTests : IDisposable
{
// Calculate QuanTAlib KAMA (Span API)
double[] qOutput = new double[_testData.RawData.Length];
global::QuanTAlib.Kama.Calculate(_testData.RawData.Span, qOutput.AsSpan(), period, fastPeriod, slowPeriod);
global::QuanTAlib.Kama.Batch(_testData.RawData.Span, qOutput.AsSpan(), period, fastPeriod, slowPeriod);
// Calculate Skender KAMA
var sResult = _testData.SkenderQuotes.GetKama(period, fastPeriod, slowPeriod).ToList();
+9 -2
View File
@@ -239,7 +239,7 @@ public sealed class Kama : AbstractBase
return kama.Update(source);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, int period, int fastPeriod = 2, int slowPeriod = 30)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period, int fastPeriod = 2, int slowPeriod = 30)
{
if (period <= 0)
{
@@ -363,6 +363,13 @@ public sealed class Kama : AbstractBase
}
}
public static (TSeries Results, Kama Indicator) Calculate(TSeries source, int period, int fastPeriod = 2, int slowPeriod = 30)
{
var indicator = new Kama(period, fastPeriod, slowPeriod);
TSeries results = indicator.Update(source);
return (results, indicator);
}
public override void Reset()
{
_buffer.Clear();
@@ -372,4 +379,4 @@ public sealed class Kama : AbstractBase
_p_state = _state;
Last = default;
}
}
}
+17 -17
View File
@@ -81,7 +81,7 @@ public class MamaTests
var famaOutput = new double[100];
// This should complete without hanging
Mama.Calculate(data, output, famaOutput: famaOutput);
Mama.Batch(data, output, famaOutput: famaOutput);
// Verify all outputs are finite (no NaN or Infinity propagation)
for (int i = 0; i < 100; i++)
@@ -252,7 +252,7 @@ public class MamaTests
}
var output = new double[count];
Mama.Calculate(data, output);
Mama.Batch(data, output);
var mama = new Mama();
for (int i = 0; i < count; i++)
@@ -267,7 +267,7 @@ public class MamaTests
{
var data = new double[10];
var output = new double[5];
Assert.Throws<ArgumentOutOfRangeException>(() => Mama.Calculate(data, output));
Assert.Throws<ArgumentOutOfRangeException>(() => Mama.Batch(data, output));
}
[Fact]
@@ -278,39 +278,39 @@ public class MamaTests
// fastLimit <= 0
var ex1 = Assert.Throws<ArgumentOutOfRangeException>(() =>
Mama.Calculate(data, output, fastLimit: 0.0));
Mama.Batch(data, output, fastLimit: 0.0));
Assert.Equal("fastLimit", ex1.ParamName);
var ex2 = Assert.Throws<ArgumentOutOfRangeException>(() =>
Mama.Calculate(data, output, fastLimit: -0.1));
Mama.Batch(data, output, fastLimit: -0.1));
Assert.Equal("fastLimit", ex2.ParamName);
// slowLimit <= 0
var ex3 = Assert.Throws<ArgumentOutOfRangeException>(() =>
Mama.Calculate(data, output, slowLimit: 0.0));
Mama.Batch(data, output, slowLimit: 0.0));
Assert.Equal("slowLimit", ex3.ParamName);
var ex4 = Assert.Throws<ArgumentOutOfRangeException>(() =>
Mama.Calculate(data, output, slowLimit: -0.1));
Mama.Batch(data, output, slowLimit: -0.1));
Assert.Equal("slowLimit", ex4.ParamName);
// fastLimit > 1
var ex5 = Assert.Throws<ArgumentOutOfRangeException>(() =>
Mama.Calculate(data, output, fastLimit: 1.1));
Mama.Batch(data, output, fastLimit: 1.1));
Assert.Equal("fastLimit", ex5.ParamName);
// slowLimit > 1
var ex6 = Assert.Throws<ArgumentOutOfRangeException>(() =>
Mama.Calculate(data, output, slowLimit: 1.1));
Mama.Batch(data, output, slowLimit: 1.1));
Assert.Equal("slowLimit", ex6.ParamName);
// fastLimit <= slowLimit
var ex7 = Assert.Throws<ArgumentOutOfRangeException>(() =>
Mama.Calculate(data, output, fastLimit: 0.05, slowLimit: 0.5));
Mama.Batch(data, output, fastLimit: 0.05, slowLimit: 0.5));
Assert.Equal("fastLimit", ex7.ParamName);
var ex8 = Assert.Throws<ArgumentOutOfRangeException>(() =>
Mama.Calculate(data, output, fastLimit: 0.5, slowLimit: 0.5));
Mama.Batch(data, output, fastLimit: 0.5, slowLimit: 0.5));
Assert.Equal("fastLimit", ex8.ParamName);
}
@@ -356,7 +356,7 @@ public class MamaTests
var mamaOutput = new double[count];
var famaOutput = new double[count];
Mama.Calculate(data, mamaOutput, famaOutput: famaOutput);
Mama.Batch(data, mamaOutput, famaOutput: famaOutput);
var mama = new Mama();
for (int i = 0; i < count; i++)
@@ -382,10 +382,10 @@ public class MamaTests
var output2 = new double[count];
// Call without famaOutput parameter (backwards compatibility)
Mama.Calculate(data, output1);
Mama.Batch(data, output1);
// Call with empty famaOutput span
Mama.Calculate(data, output2, famaOutput: Span<double>.Empty);
Mama.Batch(data, output2, famaOutput: Span<double>.Empty);
// Both should produce identical MAMA results
for (int i = 0; i < count; i++)
@@ -402,7 +402,7 @@ public class MamaTests
var famaOutput = new double[5];
var ex = Assert.Throws<ArgumentOutOfRangeException>(() =>
Mama.Calculate(data, mamaOutput, famaOutput: famaOutput));
Mama.Batch(data, mamaOutput, famaOutput: famaOutput));
Assert.Equal("famaOutput", ex.ParamName);
}
@@ -421,7 +421,7 @@ public class MamaTests
// Get values from span calculation
var mamaOutput = new double[count];
var famaOutput = new double[count];
Mama.Calculate(data, mamaOutput, famaOutput: famaOutput);
Mama.Batch(data, mamaOutput, famaOutput: famaOutput);
// Get values from instance method
var mama = new Mama();
@@ -459,7 +459,7 @@ public class MamaTests
// 2. Span Mode (static method with FAMA)
var spanMama = new double[count];
var spanFama = new double[count];
Mama.Calculate(data, spanMama, famaOutput: spanFama);
Mama.Batch(data, spanMama, famaOutput: spanFama);
// 3. Verify MAMA matches
for (int i = 0; i < count; i++)
+9 -2
View File
@@ -316,7 +316,7 @@ public sealed class Mama : AbstractBase
return mama.Update(source);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, double fastLimit = 0.5, double slowLimit = 0.05, Span<double> famaOutput = default)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, double fastLimit = 0.5, double slowLimit = 0.05, Span<double> famaOutput = default)
{
if (fastLimit <= 0)
{
@@ -540,4 +540,11 @@ public sealed class Mama : AbstractBase
}
}
}
}
public static (TSeries Results, Mama Indicator) Calculate(TSeries source, double fastLimit = 0.5, double slowLimit = 0.05)
{
var indicator = new Mama(fastLimit, slowLimit);
TSeries results = indicator.Update(source);
return (results, indicator);
}
}
+5 -5
View File
@@ -48,10 +48,10 @@ public class MgdiTests
var source = new double[10];
var output = new double[10];
Assert.Throws<ArgumentOutOfRangeException>(() => Mgdi.Calculate(source, output, 14, double.NaN));
Assert.Throws<ArgumentOutOfRangeException>(() => Mgdi.Calculate(source, output, 14, double.PositiveInfinity));
Assert.Throws<ArgumentOutOfRangeException>(() => Mgdi.Calculate(source, output, 14, double.NegativeInfinity));
Assert.Throws<ArgumentOutOfRangeException>(() => Mgdi.Calculate(source, output, 14, 0));
Assert.Throws<ArgumentOutOfRangeException>(() => Mgdi.Calculate(source, output, 14, -1));
Assert.Throws<ArgumentOutOfRangeException>(() => Mgdi.Batch(source, output, 14, double.NaN));
Assert.Throws<ArgumentOutOfRangeException>(() => Mgdi.Batch(source, output, 14, double.PositiveInfinity));
Assert.Throws<ArgumentOutOfRangeException>(() => Mgdi.Batch(source, output, 14, double.NegativeInfinity));
Assert.Throws<ArgumentOutOfRangeException>(() => Mgdi.Batch(source, output, 14, 0));
Assert.Throws<ArgumentOutOfRangeException>(() => Mgdi.Batch(source, output, 14, -1));
}
}
+9 -2
View File
@@ -134,7 +134,7 @@ public sealed class Mgdi : AbstractBase
var tSpan = CollectionsMarshal.AsSpan(t);
var vSpan = CollectionsMarshal.AsSpan(v);
Calculate(source.Values, vSpan, _period, _k);
Batch(source.Values, vSpan, _period, _k);
source.Times.CopyTo(tSpan);
// Restore state
@@ -164,7 +164,7 @@ public sealed class Mgdi : AbstractBase
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, int period = 14, double k = 0.6)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period = 14, double k = 0.6)
{
ArgumentOutOfRangeException.ThrowIfLessThan(period, 1);
if (double.IsNaN(k) || double.IsInfinity(k) || k <= 0)
@@ -229,6 +229,13 @@ public sealed class Mgdi : AbstractBase
}
}
public static (TSeries Results, Mgdi Indicator) Calculate(TSeries source, int period = 14, double k = 0.6)
{
var indicator = new Mgdi(period, k);
TSeries results = indicator.Update(source);
return (results, indicator);
}
public override void Reset()
{
Init();
+4 -4
View File
@@ -91,7 +91,7 @@ public class MmaTests
int period = 12;
TSeries series = BuildSeries(120, seed: 11);
TSeries batch = Mma.Calculate(series, period);
TSeries batch = Mma.Batch(series, period);
var mma = new Mma(period);
var streamValues = new List<double>(series.Count);
@@ -114,8 +114,8 @@ public class MmaTests
double[] values = series.Values.ToArray();
var output = new double[values.Length];
Mma.Calculate(values, output, period);
TSeries batch = Mma.Calculate(series, period);
Mma.Batch(values, output, period);
TSeries batch = Mma.Batch(series, period);
for (int i = 0; i < values.Length; i++)
{
@@ -153,7 +153,7 @@ public class MmaTests
double[] source = [1, 2, 3, 4, 5];
double[] output = new double[3];
var ex = Assert.Throws<ArgumentException>(() => Mma.Calculate(source, output, 10));
var ex = Assert.Throws<ArgumentException>(() => Mma.Batch(source, output, 10));
Assert.Equal("output", ex.ParamName);
}
+2 -2
View File
@@ -29,7 +29,7 @@ public class MmaValidationTests
double[] reference = new double[series.Count];
ReferenceMma(series.Values, reference, period);
TSeries batch = Mma.Calculate(series, period);
TSeries batch = Mma.Batch(series, period);
for (int i = 0; i < series.Count; i++)
{
@@ -47,7 +47,7 @@ public class MmaValidationTests
var reference = new double[values.Length];
ReferenceMma(values, reference, period);
Mma.Calculate(values, output, period);
Mma.Batch(values, output, period);
for (int i = 0; i < values.Length; i++)
{
+10 -3
View File
@@ -177,13 +177,13 @@ public sealed class Mma : AbstractBase
}
}
public static TSeries Calculate(TSeries source, int period)
public static TSeries Batch(TSeries source, int period)
{
var mma = new Mma(period);
return mma.Update(source);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, int period)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period)
{
if (source.Length != output.Length)
{
@@ -252,6 +252,13 @@ public sealed class Mma : AbstractBase
}
}
public static (TSeries Results, Mma Indicator) Calculate(TSeries source, int period)
{
var indicator = new Mma(period);
TSeries results = indicator.Update(source);
return (results, indicator);
}
public override void Reset()
{
_state = State.New();
@@ -349,4 +356,4 @@ public sealed class Mma : AbstractBase
return weightedSum;
}
}
}
+8 -1
View File
@@ -561,6 +561,13 @@ public sealed class Qema : AbstractBase
}
}
public static (TSeries Results, Qema Indicator) Calculate(TSeries source, int period)
{
var indicator = new Qema(period);
TSeries results = indicator.Update(source);
return (results, indicator);
}
/// <summary>
/// Resets the QEMA state.
/// </summary>
@@ -578,4 +585,4 @@ public sealed class Qema : AbstractBase
_p_lastValidValue = 0;
Last = default;
}
}
}
+7 -7
View File
@@ -383,12 +383,6 @@ public sealed class Rema : AbstractBase
/// <summary>
/// Runs a high-performance batch calculation and returns a hot REMA instance.
/// </summary>
public static (TSeries Results, Rema Indicator) Calculate(TSeries source, int period, double lambda = 0.5)
{
var rema = new Rema(period, lambda);
TSeries results = rema.Update(source);
return (results, rema);
}
/// <summary>
/// Calculates REMA for the entire series using a new instance.
@@ -450,6 +444,12 @@ public sealed class Rema : AbstractBase
CalculateCore(source, output, alpha, lambda, ref state, ref lastValid);
}
public static (TSeries Results, Rema Indicator) Calculate(TSeries source, int period, double lambda = 0.5)
{
var rema = new Rema(period, lambda);
TSeries results = rema.Update(source);
return (results, rema);
}
/// <inheritdoc/>
public override void Reset()
@@ -460,4 +460,4 @@ public sealed class Rema : AbstractBase
_p_lastValidValue = 0;
Last = default;
}
}
}
+7 -7
View File
@@ -379,12 +379,6 @@ public sealed class Rgma : AbstractBase
/// <summary>
/// Runs a high-performance batch calculation and returns a hot RGMA instance.
/// </summary>
public static (TSeries Results, Rgma Indicator) Calculate(TSeries source, int period, int passes = 3)
{
var rgma = new Rgma(period, passes);
TSeries results = rgma.Update(source);
return (results, rgma);
}
/// <summary>
/// Calculates RGMA for the entire series using a new instance.
@@ -463,6 +457,12 @@ public sealed class Rgma : AbstractBase
}
}
}
public static (TSeries Results, Rgma Indicator) Calculate(TSeries source, int period, int passes = 3)
{
var rgma = new Rgma(period, passes);
TSeries results = rgma.Update(source);
return (results, rgma);
}
/// <inheritdoc/>
public override void Reset()
@@ -490,4 +490,4 @@ public sealed class Rgma : AbstractBase
}
base.Dispose(disposing);
}
}
}
+8 -1
View File
@@ -368,6 +368,13 @@ public sealed class T3 : AbstractBase
CalculateCore(source, output, p, ref state, ref lastValidValue);
}
public static (TSeries Results, T3 Indicator) Calculate(TSeries source, int period, double vfactor = 0.7)
{
var indicator = new T3(period, vfactor);
TSeries results = indicator.Update(source);
return (results, indicator);
}
/// <summary>
/// Resets the T3 state.
/// </summary>
@@ -390,4 +397,4 @@ public sealed class T3 : AbstractBase
}
base.Dispose(disposing);
}
}
}
+8 -1
View File
@@ -470,6 +470,13 @@ public sealed class Tema : AbstractBase
}
}
public static (TSeries Results, Tema Indicator) Calculate(TSeries source, int period)
{
var indicator = new Tema(period);
TSeries results = indicator.Update(source);
return (results, indicator);
}
public override void Reset()
{
_state1 = EmaState.New();
@@ -482,4 +489,4 @@ public sealed class Tema : AbstractBase
_p_lastValidValue = 0;
Last = default;
}
}
}
+8
View File
@@ -377,6 +377,14 @@ public sealed class Vama : AbstractBase
return vama.Update(source);
}
public static (TSeries Results, Vama Indicator) Calculate(TBarSeries source, int baseLength = 20, int shortAtrPeriod = 10, int longAtrPeriod = 50, int minLength = 5, int maxLength = 100)
{
var indicator = new Vama(baseLength, shortAtrPeriod, longAtrPeriod, minLength, maxLength);
TSeries results = indicator.Update(source);
return (results, indicator);
}
/// <summary>
/// Resets the VAMA state.
/// </summary>
+15 -3
View File
@@ -24,6 +24,7 @@ public sealed class Vidya : AbstractBase
private readonly ITValuePublisher? _source;
private readonly TValuePublishedHandler? _pubHandler;
private bool _isNew = true;
private bool _disposed;
[StructLayout(LayoutKind.Auto)]
private record struct State(
@@ -59,9 +60,13 @@ public sealed class Vidya : AbstractBase
protected override void Dispose(bool disposing)
{
if (disposing && _source != null && _pubHandler != null)
if (!_disposed)
{
_source.Pub -= _pubHandler;
if (disposing && _source != null && _pubHandler != null)
{
_source.Pub -= _pubHandler;
}
_disposed = true;
}
base.Dispose(disposing);
}
@@ -388,4 +393,11 @@ public sealed class Vidya : AbstractBase
System.Buffers.ArrayPool<double>.Shared.Return(downs);
}
}
}
public static (TSeries Results, Vidya Indicator) Calculate(TSeries source, int period)
{
var indicator = new Vidya(period);
TSeries results = indicator.Update(source);
return (results, indicator);
}
}
+8
View File
@@ -545,6 +545,14 @@ public sealed class Yzvama : AbstractBase
return yzvama.Update(source);
}
public static (TSeries Results, Yzvama Indicator) Calculate(TBarSeries source, int yzvShortPeriod = 3, int yzvLongPeriod = 50, int percentileLookback = 100, int minLength = 5, int maxLength = 100)
{
var indicator = new Yzvama(yzvShortPeriod, yzvLongPeriod, percentileLookback, minLength, maxLength);
TSeries results = indicator.Update(source);
return (results, indicator);
}
/// <summary>
/// Resets the YZVAMA state.
/// </summary>
+4 -4
View File
@@ -91,7 +91,7 @@ public class ZldemaTests
int period = 12;
TSeries series = BuildSeries(120, seed: 11);
TSeries batch = Zldema.Calculate(series, period);
TSeries batch = Zldema.Batch(series, period);
var zldema = new Zldema(period);
var streamValues = new List<double>(series.Count);
@@ -114,8 +114,8 @@ public class ZldemaTests
double[] values = series.Values.ToArray();
var output = new double[values.Length];
Zldema.Calculate(values, output, period);
TSeries batch = Zldema.Calculate(series, period);
Zldema.Batch(values, output, period);
TSeries batch = Zldema.Batch(series, period);
for (int i = 0; i < values.Length; i++)
{
@@ -153,7 +153,7 @@ public class ZldemaTests
double[] source = [1, 2, 3, 4, 5];
double[] output = new double[3];
var ex = Assert.Throws<ArgumentException>(() => Zldema.Calculate(source, output, 10));
var ex = Assert.Throws<ArgumentException>(() => Zldema.Batch(source, output, 10));
Assert.Equal("output", ex.ParamName);
}
@@ -29,7 +29,7 @@ public class ZldemaValidationTests
double[] reference = new double[series.Count];
ReferenceZldema(series.Values, reference, period);
TSeries batch = Zldema.Calculate(series, period);
TSeries batch = Zldema.Batch(series, period);
for (int i = 0; i < series.Count; i++)
{
@@ -47,7 +47,7 @@ public class ZldemaValidationTests
var reference = new double[values.Length];
ReferenceZldema(values, reference, period);
Zldema.Calculate(values, output, period);
Zldema.Batch(values, output, period);
for (int i = 0; i < values.Length; i++)
{
+13 -6
View File
@@ -201,13 +201,13 @@ public sealed class Zldema : AbstractBase
}
}
public static TSeries Calculate(TSeries source, int period)
public static TSeries Batch(TSeries source, int period)
{
var zldema = new Zldema(period);
return zldema.Update(source);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, int period)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period)
{
if (source.Length != output.Length)
{
@@ -222,10 +222,10 @@ public sealed class Zldema : AbstractBase
}
double alpha = 2.0 / (period + 1);
Calculate(source, output, alpha, period);
BatchCore(source, output, alpha, period);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, double alpha)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, double alpha)
{
if (source.Length != output.Length)
{
@@ -243,7 +243,14 @@ public sealed class Zldema : AbstractBase
}
double period = (2.0 / alpha) - 1.0;
Calculate(source, output, alpha, period);
BatchCore(source, output, alpha, period);
}
public static (TSeries Results, Zldema Indicator) Calculate(TSeries source, int period)
{
var indicator = new Zldema(period);
TSeries results = indicator.Update(source);
return (results, indicator);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -344,7 +351,7 @@ public sealed class Zldema : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Handle(object? sender, in TValueEventArgs e) => Update(e.Value, e.IsNew);
private static void Calculate(ReadOnlySpan<double> source, Span<double> output, double alpha, double period)
private static void BatchCore(ReadOnlySpan<double> source, Span<double> output, double alpha, double period)
{
int lag = ComputeLag(period);
int bufferSize = lag + 1;
+4 -4
View File
@@ -91,7 +91,7 @@ public class ZlemaTests
int period = 12;
TSeries series = BuildSeries(120, seed: 11);
TSeries batch = Zlema.Calculate(series, period);
TSeries batch = Zlema.Batch(series, period);
var zlema = new Zlema(period);
var streamValues = new List<double>(series.Count);
@@ -114,8 +114,8 @@ public class ZlemaTests
double[] values = series.Values.ToArray();
var output = new double[values.Length];
Zlema.Calculate(values, output, period);
TSeries batch = Zlema.Calculate(series, period);
Zlema.Batch(values, output, period);
TSeries batch = Zlema.Batch(series, period);
for (int i = 0; i < values.Length; i++)
{
@@ -153,7 +153,7 @@ public class ZlemaTests
double[] source = [1, 2, 3, 4, 5];
double[] output = new double[3];
var ex = Assert.Throws<ArgumentException>(() => Zlema.Calculate(source, output, 10));
var ex = Assert.Throws<ArgumentException>(() => Zlema.Batch(source, output, 10));
Assert.Equal("output", ex.ParamName);
}
@@ -29,7 +29,7 @@ public class ZlemaValidationTests
double[] reference = new double[series.Count];
ReferenceZlema(series.Values, reference, period);
TSeries batch = Zlema.Calculate(series, period);
TSeries batch = Zlema.Batch(series, period);
for (int i = 0; i < series.Count; i++)
{
@@ -47,7 +47,7 @@ public class ZlemaValidationTests
var reference = new double[values.Length];
ReferenceZlema(values, reference, period);
Zlema.Calculate(values, output, period);
Zlema.Batch(values, output, period);
for (int i = 0; i < values.Length; i++)
{
+14 -7
View File
@@ -197,13 +197,13 @@ public sealed class Zlema : AbstractBase
}
}
public static TSeries Calculate(TSeries source, int period)
public static TSeries Batch(TSeries source, int period)
{
var zlema = new Zlema(period);
return zlema.Update(source);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, int period)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period)
{
if (source.Length != output.Length)
{
@@ -218,10 +218,10 @@ public sealed class Zlema : AbstractBase
}
double alpha = 2.0 / (period + 1);
Calculate(source, output, alpha, period);
BatchCore(source, output, alpha, period);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, double alpha)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, double alpha)
{
if (source.Length != output.Length)
{
@@ -239,7 +239,14 @@ public sealed class Zlema : AbstractBase
}
double period = (2.0 / alpha) - 1.0;
Calculate(source, output, alpha, period);
BatchCore(source, output, alpha, period);
}
public static (TSeries Results, Zlema Indicator) Calculate(TSeries source, int period)
{
var indicator = new Zlema(period);
TSeries results = indicator.Update(source);
return (results, indicator);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -334,7 +341,7 @@ public sealed class Zlema : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Handle(object? sender, in TValueEventArgs e) => Update(e.Value, e.IsNew);
private static void Calculate(ReadOnlySpan<double> source, Span<double> output, double alpha, double period)
private static void BatchCore(ReadOnlySpan<double> source, Span<double> output, double alpha, double period)
{
int lag = ComputeLag(period);
int bufferSize = lag + 1;
@@ -402,4 +409,4 @@ public sealed class Zlema : AbstractBase
}
}
}
}
}
+4 -4
View File
@@ -91,7 +91,7 @@ public class ZltemaTests
int period = 12;
TSeries series = BuildSeries(120, seed: 11);
TSeries batch = Zltema.Calculate(series, period);
TSeries batch = Zltema.Batch(series, period);
var zltema = new Zltema(period);
var streamValues = new List<double>(series.Count);
@@ -114,8 +114,8 @@ public class ZltemaTests
double[] values = series.Values.ToArray();
var output = new double[values.Length];
Zltema.Calculate(values, output, period);
TSeries batch = Zltema.Calculate(series, period);
Zltema.Batch(values, output, period);
TSeries batch = Zltema.Batch(series, period);
for (int i = 0; i < values.Length; i++)
{
@@ -153,7 +153,7 @@ public class ZltemaTests
double[] source = [1, 2, 3, 4, 5];
double[] output = new double[3];
var ex = Assert.Throws<ArgumentException>(() => Zltema.Calculate(source, output, 10));
var ex = Assert.Throws<ArgumentException>(() => Zltema.Batch(source, output, 10));
Assert.Equal("output", ex.ParamName);
}
@@ -29,7 +29,7 @@ public class ZltemaValidationTests
double[] reference = new double[series.Count];
ReferenceZltema(series.Values, reference, period);
TSeries batch = Zltema.Calculate(series, period);
TSeries batch = Zltema.Batch(series, period);
for (int i = 0; i < series.Count; i++)
{
@@ -47,7 +47,7 @@ public class ZltemaValidationTests
var reference = new double[values.Length];
ReferenceZltema(values, reference, period);
Zltema.Calculate(values, output, period);
Zltema.Batch(values, output, period);
for (int i = 0; i < values.Length; i++)
{
+13 -6
View File
@@ -201,13 +201,13 @@ public sealed class Zltema : AbstractBase
}
}
public static TSeries Calculate(TSeries source, int period)
public static TSeries Batch(TSeries source, int period)
{
var zltema = new Zltema(period);
return zltema.Update(source);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, int period)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period)
{
if (source.Length != output.Length)
{
@@ -222,10 +222,10 @@ public sealed class Zltema : AbstractBase
}
double alpha = 2.0 / (period + 1);
Calculate(source, output, alpha, period);
BatchCore(source, output, alpha, period);
}
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, double alpha)
public static void Batch(ReadOnlySpan<double> source, Span<double> output, double alpha)
{
if (source.Length != output.Length)
{
@@ -243,7 +243,14 @@ public sealed class Zltema : AbstractBase
}
double period = (2.0 / alpha) - 1.0;
Calculate(source, output, alpha, period);
BatchCore(source, output, alpha, period);
}
public static (TSeries Results, Zltema Indicator) Calculate(TSeries source, int period)
{
var indicator = new Zltema(period);
TSeries results = indicator.Update(source);
return (results, indicator);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -351,7 +358,7 @@ public sealed class Zltema : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Handle(object? sender, in TValueEventArgs e) => Update(e.Value, e.IsNew);
private static void Calculate(ReadOnlySpan<double> source, Span<double> output, double alpha, double period)
private static void BatchCore(ReadOnlySpan<double> source, Span<double> output, double alpha, double period)
{
int lag = ComputeLag(period);
int bufferSize = lag + 1;