mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-22 04:28:04 +00:00
normalization of methods
This commit is contained in:
@@ -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]}");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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++)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user