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

This commit is contained in:
Miha Kralj
2026-03-09 13:45:46 -07:00
parent 8e43d62cbb
commit 031f1b5fe6
491 changed files with 6156 additions and 5590 deletions
+28
View File
@@ -418,5 +418,33 @@ public class EacpValidationTests
Assert.True(diff > 5, $"Should detect different cycles: {eacp1.DominantCycle} vs {eacp2.DominantCycle}");
}
[Fact]
public void Eacp_Correction_Recomputes()
{
var ind = new Eacp(8, 48, 3, true);
var t0 = new DateTime(946_684_800_000_000_0L, DateTimeKind.Utc);
// Build state well past warmup
for (int i = 0; i < 100; i++)
{
ind.Update(new TValue(t0.AddMinutes(i),
100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20.0)), isNew: true);
}
// Anchor bar
var anchorTime = t0.AddMinutes(100);
const double anchorPrice = 105.5;
ind.Update(new TValue(anchorTime, anchorPrice), isNew: true);
double anchorResult = ind.Last.Value;
// Correction with a dramatically different price — recompute must yield different result
ind.Update(new TValue(anchorTime, anchorPrice * 10.0), isNew: false);
Assert.NotEqual(anchorResult, ind.Last.Value);
// Correction back to original price — must exactly restore original result
ind.Update(new TValue(anchorTime, anchorPrice), isNew: false);
Assert.Equal(anchorResult, ind.Last.Value, Tolerance);
}
#endregion
}
+7 -2
View File
@@ -48,6 +48,7 @@ public sealed class Eacp : AbstractBase
private readonly double[] _corr;
private readonly double[] _power;
private readonly double[] _smooth;
private readonly double[] _p_smooth;
// State for filters and output
[StructLayout(LayoutKind.Auto)]
@@ -122,6 +123,7 @@ public sealed class Eacp : AbstractBase
_corr = new double[size];
_power = new double[size];
_smooth = new double[size];
_p_smooth = new double[size];
_filtHistory = new RingBuffer(size + maxPeriod);
Name = $"Eacp({minPeriod},{maxPeriod})";
@@ -156,11 +158,13 @@ public sealed class Eacp : AbstractBase
{
_ps = _s;
_filtHistory.Snapshot();
Array.Copy(_smooth, _p_smooth, _smooth.Length);
}
else
{
_s = _ps;
_filtHistory.Restore();
Array.Copy(_p_smooth, _smooth, _smooth.Length);
}
var s = _s;
@@ -407,6 +411,7 @@ public sealed class Eacp : AbstractBase
Array.Clear(_corr);
Array.Clear(_power);
Array.Clear(_smooth);
Array.Clear(_p_smooth);
Last = default;
}
@@ -414,7 +419,7 @@ public sealed class Eacp : AbstractBase
{
foreach (double value in source)
{
Update(new TValue(DateTime.UtcNow, value));
Update(new TValue(DateTime.MinValue, value));
}
}
@@ -459,7 +464,7 @@ public sealed class Eacp : AbstractBase
var eacp = new Eacp(minPeriod, maxPeriod, avgLength, enhance);
for (int i = 0; i < len; i++)
{
var result = eacp.Update(new TValue(DateTime.UtcNow, source[i]));
var result = eacp.Update(new TValue(DateTime.MinValue, source[i]));
output[i] = result.Value;
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
// The MIT License (MIT)
// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Ehlers Autocorrelation Periodogram (EACP)","EACP",overlay=false)