diff --git a/_sidebar.md b/_sidebar.md index 634f8da4..bbf9e40c 100644 --- a/_sidebar.md +++ b/_sidebar.md @@ -313,7 +313,7 @@ * [CCYC - Ehlers Cyber Cycle](/lib/cycles/ccyc/Ccyc.md) * [CG - Ehlers Center of Gravity](/lib/cycles/cg/Cg.md) * [DSP - Ehlers Detrended Synthetic Price](/lib/cycles/dsp/Dsp.md) - * [EACP - Ehlers Autocorrelation Periodogram](/lib/cycles/eacp/Eacp.md) + * [ACP - Ehlers Autocorrelation Periodogram](/lib/cycles/acp/Acp.md) * [EBSW - Ehlers Even Better Sinewave](/lib/cycles/ebsw/Ebsw.md) * [HOMOD - Ehlers Homodyne Discriminator](/lib/cycles/homod/Homod.md) * [HT_DCPERIOD - Ehlers Hilbert Transform Dominant Cycle Period](/lib/cycles/ht_dcperiod/HtDcperiod.md) diff --git a/docs/indicators.md b/docs/indicators.md index 3f1a7ea6..2fc56cfa 100644 --- a/docs/indicators.md +++ b/docs/indicators.md @@ -431,7 +431,7 @@ Periodic pattern detection and dominant frequency extraction. Markets exhibit cy | [**CCYC**](../lib/cycles/ccyc/Ccyc.md) | Ehlers Cyber Cycle | 4-tap FIR + 2-pole high-pass IIR cycle extraction | | [**CG**](../lib/cycles/cg/Cg.md) | Ehlers Center of Gravity | Ehlers cycle measurement | | [**DSP**](../lib/cycles/dsp/Dsp.md) | Ehlers Detrended Synthetic Price | Cycle-isolated price component | -| [**EACP**](../lib/cycles/eacp/Eacp.md) | Ehlers Autocorrelation Periodogram | Ehlers dominant cycle detection | +| [**ACP**](../lib/cycles/acp/Acp.md) | Ehlers Autocorrelation Periodogram | Ehlers dominant cycle detection | | [**EBSW**](../lib/cycles/ebsw/Ebsw.md) | Ehlers Even Better Sinewave | Ehlers improved cycle indicator | | [**HOMOD**](../lib/cycles/homod/Homod.md) | Ehlers Homodyne Discriminator | Dominant cycle period tracking | | [**HT_DCPERIOD**](../lib/cycles/ht_dcperiod/HtDcperiod.md) | Ehlers HT Dominant Cycle Period | Hilbert Transform period estimation | diff --git a/docs/pinescript.md b/docs/pinescript.md index 68d733e6..40f8b1bf 100644 --- a/docs/pinescript.md +++ b/docs/pinescript.md @@ -419,7 +419,7 @@ Markets oscillate. These indicators try to measure the oscillation itself — th | CCYC | Ehlers Cyber Cycle | [ccyc.pine](../lib/cycles/ccyc/ccyc.pine) | | CG | Ehlers Center of Gravity | [cg.pine](../lib/cycles/cg/cg.pine) | | DSP | Ehlers Detrended Synthetic Price | [dsp.pine](../lib/cycles/dsp/dsp.pine) | -| EACP | Ehlers Autocorrelation Periodogram | [eacp.pine](../lib/cycles/eacp/eacp.pine) | +| ACP | Ehlers Autocorrelation Periodogram | [acp.pine](../lib/cycles/acp/acp.pine) | | EBSW | Ehlers Even Better Sinewave | [ebsw.pine](../lib/cycles/ebsw/ebsw.pine) | | HOMOD | Ehlers Homodyne Discriminator | [homod.pine](../lib/cycles/homod/homod.pine) | | HT_DCPERIOD | Ehlers Hilbert Transform Dominant Cycle Period | [ht_dcperiod.pine](../lib/cycles/ht_dcperiod/ht_dcperiod.pine) | diff --git a/docs/validation.md b/docs/validation.md index 8a7c7646..266f654a 100644 --- a/docs/validation.md +++ b/docs/validation.md @@ -145,7 +145,7 @@ Next parity targets (highest impact): | **Dynamic Momentum Index** | [Dymi](../lib/oscillators/dymi/Dymi.md) | - | - | - | [⚠️](../lib/oscillators/dymi/Dymi.md#validation "structural test only; Ooples uses different dynamic period logic") | - | | **Ease of Movement** | [Eom](../lib/volume/eom/Eom.md) | - | [✔️](../lib/volume/eom/Eom.md#validation) | - | - | ⚠️ | | **Efficiency Ratio** | [Er](../lib/oscillators/er/Er.md) | - | - | - | - | ⚠️ | -| **Ehlers Autocorrelation Periodogram** | [Eacp](../lib/cycles/eacp/eacp.md) | - | - | - | - | - | +| **Ehlers Autocorrelation Periodogram** | [Acp](../lib/cycles/acp/acp.md) | - | - | - | - | - | | **BandPass Filter** | [Bpf](../lib/filters/bpf/Bpf.md) | - | - | - | - | - | | **Ehlers Center of Gravity** | [Cg](../lib/cycles/cg/Cg.md) | - | - | - | [⚠️](../lib/cycles/cg/Cg.md#validation "structural test only; Ooples CG uses different weighting scheme") | ⚠️ | | **Ehlers Correlation Cycle** | [Ccor](../lib/cycles/ccor/Ccor.md) | - | - | - | - | - | diff --git a/lib/_index.md b/lib/_index.md index f897472c..0d605554 100644 --- a/lib/_index.md +++ b/lib/_index.md @@ -103,7 +103,7 @@ | [DWT](numerics/dwt/Dwt.md) | Discrete Wavelet Transform | Numerics | | [DX](dynamics/dx/Dx.md) | Directional Movement Index | Dynamics | | [DYMI](oscillators/dymi/Dymi.md) | Dynamic Momentum Index | Oscillators | -| [EACP](cycles/eacp/Eacp.md) | Ehlers Autocorrelation Periodogram | Cycles | +| [ACP](cycles/acp/Acp.md) | Ehlers Autocorrelation Periodogram | Cycles | | [EBSW](cycles/ebsw/Ebsw.md) | Ehlers Even Better Sinewave | Cycles | | [EDCF](filters/edcf/Edcf.md) | Ehlers Distance Coefficient Filter | Filters | | [EDECAY](numerics/edecay/Edecay.md) | Exponential Decay | Numerics | diff --git a/lib/cycles/_index.md b/lib/cycles/_index.md index d8b1b47b..8ebb0d91 100644 --- a/lib/cycles/_index.md +++ b/lib/cycles/_index.md @@ -10,7 +10,7 @@ Cycle analysis identifies repeating patterns in price data. John Ehlers pioneere | [CCYC](ccyc/Ccyc.md) | Ehlers Cyber Cycle | Ehlers. 4-tap FIR + 2-pole high-pass IIR. Isolates dominant cycle component. | | [CG](cg/Cg.md) | Ehlers Center of Gravity | Ehlers. Weighted sum position. Minimal lag cycle indicator. | | [DSP](dsp/Dsp.md) | Ehlers Detrended Synthetic Price | Removes trend to reveal underlying cycles. | -| [EACP](eacp/Eacp.md) | Ehlers Autocorrelation Periodogram | Ehlers. Spectral analysis via autocorrelation. Detects dominant period. | +| [ACP](acp/Acp.md) | Ehlers Autocorrelation Periodogram | Ehlers. Spectral analysis via autocorrelation. Detects dominant period. | | [EBSW](ebsw/Ebsw.md) | Ehlers Even Better Sinewave | Ehlers. Improved sinewave extraction. Reduces false signals. | | [HOMOD](homod/Homod.md) | Ehlers Homodyne Discriminator | Dominant cycle detection via homodyne technique. | | [HT_DCPERIOD](ht_dcperiod/Htdcperiod.md) | Ehlers Hilbert Transform Dominant Cycle Period | Ehlers Hilbert Transform. Measures current cycle length. | diff --git a/lib/cycles/eacp/Eacp.Quantower.cs b/lib/cycles/acp/Acp.Quantower.cs similarity index 78% rename from lib/cycles/eacp/Eacp.Quantower.cs rename to lib/cycles/acp/Acp.Quantower.cs index ee244977..a4e3cbef 100644 --- a/lib/cycles/eacp/Eacp.Quantower.cs +++ b/lib/cycles/acp/Acp.Quantower.cs @@ -5,7 +5,7 @@ using TradingPlatform.BusinessLayer; namespace QuanTAlib; [SkipLocalsInit] -public sealed class EacpIndicator : Indicator, IWatchlistIndicator +public sealed class AcpIndicator : Indicator, IWatchlistIndicator { [InputParameter("Min Period", sortIndex: 1, 3, 100, 1, 0)] public int MinPeriod { get; set; } = 8; @@ -25,7 +25,7 @@ public sealed class EacpIndicator : Indicator, IWatchlistIndicator [InputParameter("Show cold values", sortIndex: 21)] public bool ShowColdValues { get; set; } = true; - private Eacp _eacp = null!; + private Acp _acp = null!; private readonly LineSeries _cycleSeries; private readonly LineSeries _powerSeries; private Func _priceSelector = null!; @@ -33,14 +33,14 @@ public sealed class EacpIndicator : Indicator, IWatchlistIndicator public static int MinHistoryDepths => 0; int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; - public override string ShortName => $"EACP ({MinPeriod},{MaxPeriod})"; - public override string SourceCodeLink => "https://github.com/mihakralj/QuanTAlib/blob/main/lib/cycles/eacp/Eacp.Quantower.cs"; + public override string ShortName => $"ACP ({MinPeriod},{MaxPeriod})"; + public override string SourceCodeLink => "https://github.com/mihakralj/QuanTAlib/blob/main/lib/cycles/acp/Acp.Quantower.cs"; - public EacpIndicator() + public AcpIndicator() { OnBackGround = true; SeparateWindow = true; - Name = "EACP - Ehlers Autocorrelation Periodogram"; + Name = "ACP - Ehlers Autocorrelation Periodogram"; Description = "Ehlers' Autocorrelation Periodogram estimates the dominant cycle period using autocorrelation and spectral analysis"; _cycleSeries = new LineSeries(name: "Cycle", color: IndicatorExtensions.Oscillators, width: 2, style: LineStyle.Solid); @@ -52,7 +52,7 @@ public sealed class EacpIndicator : Indicator, IWatchlistIndicator [MethodImpl(MethodImplOptions.AggressiveInlining)] protected override void OnInit() { - _eacp = new Eacp(MinPeriod, MaxPeriod, AvgLength, Enhance); + _acp = new Acp(MinPeriod, MaxPeriod, AvgLength, Enhance); _priceSelector = Source.GetPriceSelector(); base.OnInit(); } @@ -70,9 +70,9 @@ public sealed class EacpIndicator : Indicator, IWatchlistIndicator var time = this.HistoricalData.Time(); var input = new TValue(time, value); - TValue result = _eacp.Update(input, args.IsNewBar()); + TValue result = _acp.Update(input, args.IsNewBar()); - _cycleSeries.SetValue(result.Value, _eacp.IsHot, ShowColdValues); - _powerSeries.SetValue(_eacp.NormalizedPower * MaxPeriod, _eacp.IsHot, ShowColdValues); + _cycleSeries.SetValue(result.Value, _acp.IsHot, ShowColdValues); + _powerSeries.SetValue(_acp.NormalizedPower * MaxPeriod, _acp.IsHot, ShowColdValues); } } \ No newline at end of file diff --git a/lib/cycles/eacp/Eacp.cs b/lib/cycles/acp/Acp.cs similarity index 93% rename from lib/cycles/eacp/Eacp.cs rename to lib/cycles/acp/Acp.cs index e1b6a633..a6280836 100644 --- a/lib/cycles/eacp/Eacp.cs +++ b/lib/cycles/acp/Acp.cs @@ -4,7 +4,7 @@ using System.Runtime.InteropServices; namespace QuanTAlib; /// -/// EACP: Ehlers Autocorrelation Periodogram - Dominant cycle estimator using +/// ACP: Ehlers Autocorrelation Periodogram - Dominant cycle estimator using /// autocorrelation and spectral analysis via the Wiener-Khinchin theorem. /// /// @@ -32,7 +32,7 @@ namespace QuanTAlib; /// to spectral density, enabling frequency domain analysis. /// [SkipLocalsInit] -public sealed class Eacp : AbstractBase +public sealed class Acp : AbstractBase { private readonly int _minPeriod; private readonly int _maxPeriod; @@ -82,7 +82,7 @@ public sealed class Eacp : AbstractBase /// Maximum period to evaluate (must be > minPeriod). /// Averaging length for Pearson correlation (0 uses lag length). /// Apply cubic emphasis to highlight dominant peaks. - public Eacp(int minPeriod = 8, int maxPeriod = 48, int avgLength = 3, bool enhance = true) + public Acp(int minPeriod = 8, int maxPeriod = 48, int avgLength = 3, bool enhance = true) { if (minPeriod < 3) { @@ -126,7 +126,7 @@ public sealed class Eacp : AbstractBase _p_smooth = new double[size]; _filtHistory = new RingBuffer(size + maxPeriod); - Name = $"Eacp({minPeriod},{maxPeriod})"; + Name = $"Acp({minPeriod},{maxPeriod})"; WarmupPeriod = maxPeriod * 2; // Initialize state @@ -138,7 +138,7 @@ public sealed class Eacp : AbstractBase /// /// Creates a chained Ehlers Autocorrelation Periodogram indicator. /// - public Eacp(ITValuePublisher source, int minPeriod = 8, int maxPeriod = 48, int avgLength = 3, bool enhance = true) + public Acp(ITValuePublisher source, int minPeriod = 8, int maxPeriod = 48, int avgLength = 3, bool enhance = true) : this(minPeriod, maxPeriod, avgLength, enhance) { ArgumentNullException.ThrowIfNull(source); @@ -424,17 +424,17 @@ public sealed class Eacp : AbstractBase } /// - /// Calculates EACP for a time series. + /// Calculates ACP for a time series. /// public static TSeries Batch(TSeries source, int minPeriod = 8, int maxPeriod = 48, int avgLength = 3, bool enhance = true) { - var eacp = new Eacp(minPeriod, maxPeriod, avgLength, enhance); - return eacp.Update(source); + var acp = new Acp(minPeriod, maxPeriod, avgLength, enhance); + return acp.Update(source); } /// - /// Calculates EACP in-place using a pre-allocated output span. + /// Calculates ACP in-place using a pre-allocated output span. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Batch(ReadOnlySpan source, Span output, @@ -461,17 +461,17 @@ public sealed class Eacp : AbstractBase } // Use streaming implementation for batch (complex state management) - var eacp = new Eacp(minPeriod, maxPeriod, avgLength, enhance); + var acp = new Acp(minPeriod, maxPeriod, avgLength, enhance); for (int i = 0; i < len; i++) { - var result = eacp.Update(new TValue(DateTime.MinValue, source[i])); + var result = acp.Update(new TValue(DateTime.MinValue, source[i])); output[i] = result.Value; } } - public static (TSeries Results, Eacp Indicator) Calculate(TSeries source, int minPeriod = 8, int maxPeriod = 48, int avgLength = 3, bool enhance = true) + public static (TSeries Results, Acp Indicator) Calculate(TSeries source, int minPeriod = 8, int maxPeriod = 48, int avgLength = 3, bool enhance = true) { - var indicator = new Eacp(minPeriod, maxPeriod, avgLength, enhance); + var indicator = new Acp(minPeriod, maxPeriod, avgLength, enhance); TSeries results = indicator.Update(source); return (results, indicator); } diff --git a/lib/cycles/eacp/eacp.md b/lib/cycles/acp/acp.md similarity index 88% rename from lib/cycles/eacp/eacp.md rename to lib/cycles/acp/acp.md index 6675dc4b..b4afc8f5 100644 --- a/lib/cycles/eacp/eacp.md +++ b/lib/cycles/acp/acp.md @@ -1,4 +1,4 @@ -# EACP: Ehlers Autocorrelation Periodogram +# ACP: Ehlers Autocorrelation Periodogram > *Autocorrelation periodogram scans every possible cycle length and ranks them by strength — a spectral fingerprint of the market.* @@ -7,16 +7,16 @@ | **Category** | Cycle | | **Inputs** | Source (close) | | **Parameters** | `minPeriod` (default 8), `maxPeriod` (default 48), `avgLength` (default 3), `enhance` (default true) | -| **Outputs** | Single series (Eacp) | +| **Outputs** | Single series (Acp) | | **Output range** | Varies (see docs) | | **Warmup** | `maxPeriod * 2` bars | -| **PineScript** | [eacp.pine](eacp.pine) | +| **PineScript** | [acp.pine](acp.pine) | -- EACP estimates the dominant cycle period of a financial time series by computing autocorrelation across multiple lags and transforming the result i... +- ACP estimates the dominant cycle period of a financial time series by computing autocorrelation across multiple lags and transforming the result into a power spectrum via the Wiener-Khinchin theorem. - **Similar:** [CG](../cg/cg.md), [HT_DCPeriod](../ht_dcperiod/ht_dcperiod.md) | **Complementary:** EBSW for trend/cycle classification | **Trading note:** Ehlers Autocorrelation Periodogram; identifies dominant cycle length adaptively. - Validated against TA-Lib, Skender, and Tulip reference implementations where available. -EACP estimates the dominant cycle period of a financial time series by computing autocorrelation across multiple lags and transforming the result into a power spectrum via the Wiener-Khinchin theorem. The output is a continuously updating cycle period measurement (in bars) that can adaptively tune other indicators to the market's current rhythm, making fixed-period assumptions unnecessary. +ACP estimates the dominant cycle period of a financial time series by computing autocorrelation across multiple lags and transforming the result into a power spectrum via the Wiener-Khinchin theorem. The output is a continuously updating cycle period measurement (in bars) that can adaptively tune other indicators to the market's current rhythm, making fixed-period assumptions unnecessary. ## Historical Context diff --git a/lib/cycles/eacp/eacp.pine b/lib/cycles/acp/acp.pine similarity index 95% rename from lib/cycles/eacp/eacp.pine rename to lib/cycles/acp/acp.pine index def587bc..7ac465ac 100644 --- a/lib/cycles/eacp/eacp.pine +++ b/lib/cycles/acp/acp.pine @@ -1,7 +1,7 @@ // Licensed under the Apache License, Version 2.0 // © mihakralj //@version=6 -indicator("Ehlers Autocorrelation Periodogram (EACP)","EACP",overlay=false) +indicator("Ehlers Autocorrelation Periodogram (ACP)","ACP",overlay=false) //@function Autocorrelation periodogram dominant cycle estimator //@param source Price input series //@param minPeriod Minimum period to evaluate @@ -11,7 +11,7 @@ indicator("Ehlers Autocorrelation Periodogram (EACP)","EACP",overlay=false) //@returns Smoothed dominant cycle estimate //@optimized Removed buffer complexity, uses native PineScript historical operator for O(n) correlation //@validation wolfram:"Wiener-Khinchin theorem","Pearson correlation coefficient" external:"TradingView TASC 2025.02 Autocorrelation","ImmortalFreedom Ehlers ACP","QuantStrat autocorrPeriodogram" -eacp(series float source,simple int minPeriod,simple int maxPeriod,simple int avgLength,simple bool enhance)=> +acp(series float source,simple int minPeriod,simple int maxPeriod,simple int avgLength,simple bool enhance)=> if minPeriod<3 runtime.error("Min period must be at least 3") if maxPeriod<=minPeriod @@ -140,6 +140,6 @@ i_minPeriod=input.int(8,"Min Period",minval=3,maxval=500) i_maxPeriod=input.int(48,"Max Period",minval=4,maxval=500) i_avgLength=input.int(3,"Autocorrelation Length",minval=0,maxval=500) i_enhance=input.bool(true,"Enhance Resolution") -[dominantCycle,normalizedPower]=eacp(i_source,i_minPeriod,i_maxPeriod,i_avgLength,i_enhance) +[dominantCycle,normalizedPower]=acp(i_source,i_minPeriod,i_maxPeriod,i_avgLength,i_enhance) plot(dominantCycle,"Dominant Cycle",color=color.yellow,linewidth=2) plot(normalizedPower,"Normalized Power",color=color.orange,linewidth=2) diff --git a/lib/cycles/eacp/tests/Eacp.Quantower.Tests.cs b/lib/cycles/acp/tests/Acp.Quantower.Tests.cs similarity index 71% rename from lib/cycles/eacp/tests/Eacp.Quantower.Tests.cs rename to lib/cycles/acp/tests/Acp.Quantower.Tests.cs index a20ce4d0..c78a2ad8 100644 --- a/lib/cycles/eacp/tests/Eacp.Quantower.Tests.cs +++ b/lib/cycles/acp/tests/Acp.Quantower.Tests.cs @@ -2,12 +2,12 @@ using TradingPlatform.BusinessLayer; namespace QuanTAlib.Quantower.Tests; -public class EacpIndicatorTests +public class AcpIndicatorTests { [Fact] - public void EacpIndicator_Constructor_SetsDefaults() + public void AcpIndicator_Constructor_SetsDefaults() { - var indicator = new EacpIndicator(); + var indicator = new AcpIndicator(); Assert.Equal(8, indicator.MinPeriod); Assert.Equal(48, indicator.MaxPeriod); @@ -15,34 +15,34 @@ public class EacpIndicatorTests Assert.True(indicator.Enhance); Assert.Equal(SourceType.Close, indicator.Source); Assert.True(indicator.ShowColdValues); - Assert.Equal("EACP - Ehlers Autocorrelation Periodogram", indicator.Name); + Assert.Equal("ACP - Ehlers Autocorrelation Periodogram", indicator.Name); Assert.True(indicator.SeparateWindow); Assert.True(indicator.OnBackGround); } [Fact] - public void EacpIndicator_MinHistoryDepths_EqualsZero() + public void AcpIndicator_MinHistoryDepths_EqualsZero() { - var indicator = new EacpIndicator(); + var indicator = new AcpIndicator(); - Assert.Equal(0, EacpIndicator.MinHistoryDepths); + Assert.Equal(0, AcpIndicator.MinHistoryDepths); Assert.Equal(0, ((IWatchlistIndicator)indicator).MinHistoryDepths); } [Fact] - public void EacpIndicator_ShortName_IncludesPeriods() + public void AcpIndicator_ShortName_IncludesPeriods() { - var indicator = new EacpIndicator { MinPeriod = 10, MaxPeriod = 60 }; + var indicator = new AcpIndicator { MinPeriod = 10, MaxPeriod = 60 }; - Assert.True(indicator.ShortName.Contains("EACP", StringComparison.Ordinal)); + Assert.True(indicator.ShortName.Contains("ACP", StringComparison.Ordinal)); Assert.True(indicator.ShortName.Contains("10", StringComparison.Ordinal)); Assert.True(indicator.ShortName.Contains("60", StringComparison.Ordinal)); } [Fact] - public void EacpIndicator_Initialize_CreatesInternalEacp() + public void AcpIndicator_Initialize_CreatesInternalAcp() { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48 }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48 }; // Initialize should not throw indicator.Initialize(); @@ -52,9 +52,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_ProcessUpdate_HistoricalBar_ComputesValue() + public void AcpIndicator_ProcessUpdate_HistoricalBar_ComputesValue() { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48 }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48 }; indicator.Initialize(); // Add historical data @@ -71,9 +71,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_ProcessUpdate_NewBar_ComputesValue() + public void AcpIndicator_ProcessUpdate_NewBar_ComputesValue() { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48 }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48 }; indicator.Initialize(); var now = DateTime.UtcNow; @@ -87,9 +87,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_ProcessUpdate_NewTick_ProcessesWithoutError() + public void AcpIndicator_ProcessUpdate_NewTick_ProcessesWithoutError() { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48 }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48 }; indicator.Initialize(); // Should not throw an exception @@ -100,9 +100,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_MultipleUpdates_ProducesCorrectSequence() + public void AcpIndicator_MultipleUpdates_ProducesCorrectSequence() { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48 }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48 }; indicator.Initialize(); var now = DateTime.UtcNow; @@ -123,13 +123,13 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_DifferentSourceTypes_Work() + public void AcpIndicator_DifferentSourceTypes_Work() { var sources = new[] { SourceType.Open, SourceType.High, SourceType.Low, SourceType.Close, SourceType.HL2, SourceType.HLC3 }; foreach (var source in sources) { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48, Source = source }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48, Source = source }; indicator.Initialize(); var now = DateTime.UtcNow; @@ -142,9 +142,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_MinPeriod_CanBeChanged() + public void AcpIndicator_MinPeriod_CanBeChanged() { - var indicator = new EacpIndicator { MinPeriod = 8 }; + var indicator = new AcpIndicator { MinPeriod = 8 }; Assert.Equal(8, indicator.MinPeriod); @@ -153,9 +153,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_MaxPeriod_CanBeChanged() + public void AcpIndicator_MaxPeriod_CanBeChanged() { - var indicator = new EacpIndicator { MaxPeriod = 48 }; + var indicator = new AcpIndicator { MaxPeriod = 48 }; Assert.Equal(48, indicator.MaxPeriod); @@ -164,9 +164,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_AvgLength_CanBeChanged() + public void AcpIndicator_AvgLength_CanBeChanged() { - var indicator = new EacpIndicator { AvgLength = 3 }; + var indicator = new AcpIndicator { AvgLength = 3 }; Assert.Equal(3, indicator.AvgLength); @@ -175,9 +175,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_Enhance_CanBeChanged() + public void AcpIndicator_Enhance_CanBeChanged() { - var indicator = new EacpIndicator { Enhance = true }; + var indicator = new AcpIndicator { Enhance = true }; Assert.True(indicator.Enhance); @@ -186,9 +186,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_Source_CanBeChanged() + public void AcpIndicator_Source_CanBeChanged() { - var indicator = new EacpIndicator { Source = SourceType.Close }; + var indicator = new AcpIndicator { Source = SourceType.Close }; Assert.Equal(SourceType.Close, indicator.Source); @@ -197,9 +197,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_ShowColdValues_CanBeChanged() + public void AcpIndicator_ShowColdValues_CanBeChanged() { - var indicator = new EacpIndicator { ShowColdValues = true }; + var indicator = new AcpIndicator { ShowColdValues = true }; Assert.True(indicator.ShowColdValues); @@ -208,9 +208,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_ShortName_UpdatesWhenPeriodsChange() + public void AcpIndicator_ShortName_UpdatesWhenPeriodsChange() { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48 }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48 }; string initialName = indicator.ShortName; Assert.True(initialName.Contains("8", StringComparison.Ordinal)); @@ -225,9 +225,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_ProcessUpdate_IgnoresNonBarUpdates() + public void AcpIndicator_ProcessUpdate_IgnoresNonBarUpdates() { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48 }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48 }; indicator.Initialize(); var now = DateTime.UtcNow; @@ -243,9 +243,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_CycleSeries_HasCorrectProperties() + public void AcpIndicator_CycleSeries_HasCorrectProperties() { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48 }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48 }; indicator.Initialize(); var lineSeries = indicator.LinesSeries[0]; @@ -256,9 +256,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_PowerSeries_HasCorrectProperties() + public void AcpIndicator_PowerSeries_HasCorrectProperties() { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48 }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48 }; indicator.Initialize(); var powerSeries = indicator.LinesSeries[1]; @@ -269,13 +269,13 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_DifferentPeriodRanges_Work() + public void AcpIndicator_DifferentPeriodRanges_Work() { var periodRanges = new[] { (8, 48), (10, 60), (6, 30), (12, 100) }; foreach (var (minPeriod, maxPeriod) in periodRanges) { - var indicator = new EacpIndicator { MinPeriod = minPeriod, MaxPeriod = maxPeriod }; + var indicator = new AcpIndicator { MinPeriod = minPeriod, MaxPeriod = maxPeriod }; indicator.Initialize(); var now = DateTime.UtcNow; @@ -294,9 +294,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_SineWave_DetectsCycle() + public void AcpIndicator_SineWave_DetectsCycle() { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48 }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48 }; indicator.Initialize(); var now = DateTime.UtcNow; @@ -316,9 +316,9 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_PowerOutput_ScaledCorrectly() + public void AcpIndicator_PowerOutput_ScaledCorrectly() { - var indicator = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48 }; + var indicator = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48 }; indicator.Initialize(); var now = DateTime.UtcNow; @@ -336,10 +336,10 @@ public class EacpIndicatorTests } [Fact] - public void EacpIndicator_EnhanceMode_AffectsOutput() + public void AcpIndicator_EnhanceMode_AffectsOutput() { - var indicatorEnhanced = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48, Enhance = true }; - var indicatorNormal = new EacpIndicator { MinPeriod = 8, MaxPeriod = 48, Enhance = false }; + var indicatorEnhanced = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48, Enhance = true }; + var indicatorNormal = new AcpIndicator { MinPeriod = 8, MaxPeriod = 48, Enhance = false }; indicatorEnhanced.Initialize(); indicatorNormal.Initialize(); diff --git a/lib/cycles/eacp/tests/Eacp.Tests.cs b/lib/cycles/acp/tests/Acp.Tests.cs similarity index 62% rename from lib/cycles/eacp/tests/Eacp.Tests.cs rename to lib/cycles/acp/tests/Acp.Tests.cs index 5b6beb04..92cbdbdf 100644 --- a/lib/cycles/eacp/tests/Eacp.Tests.cs +++ b/lib/cycles/acp/tests/Acp.Tests.cs @@ -2,7 +2,7 @@ using Xunit; namespace QuanTAlib.Tests; -public class EacpTests +public class AcpTests { private const double Tolerance = 1e-9; @@ -11,18 +11,18 @@ public class EacpTests [Fact] public void Constructor_DefaultParameters_SetsProperties() { - var eacp = new Eacp(); + var acp = new Acp(); - Assert.Equal("Eacp(8,48)", eacp.Name); - Assert.False(eacp.IsHot); + Assert.Equal("Acp(8,48)", acp.Name); + Assert.False(acp.IsHot); } [Fact] public void Constructor_CustomParameters_SetsProperties() { - var eacp = new Eacp(minPeriod: 10, maxPeriod: 60, avgLength: 5, enhance: false); + var acp = new Acp(minPeriod: 10, maxPeriod: 60, avgLength: 5, enhance: false); - Assert.Equal("Eacp(10,60)", eacp.Name); + Assert.Equal("Acp(10,60)", acp.Name); } [Theory] @@ -31,7 +31,7 @@ public class EacpTests [InlineData(-1)] public void Constructor_InvalidMinPeriod_ThrowsArgumentOutOfRange(int minPeriod) { - var ex = Assert.Throws(() => new Eacp(minPeriod, 48)); + var ex = Assert.Throws(() => new Acp(minPeriod, 48)); Assert.Equal("minPeriod", ex.ParamName); } @@ -41,31 +41,31 @@ public class EacpTests [InlineData(10, 10)] public void Constructor_MaxPeriodNotGreaterThanMin_ThrowsArgumentOutOfRange(int minPeriod, int maxPeriod) { - var ex = Assert.Throws(() => new Eacp(minPeriod, maxPeriod)); + var ex = Assert.Throws(() => new Acp(minPeriod, maxPeriod)); Assert.Equal("maxPeriod", ex.ParamName); } [Fact] public void Constructor_NegativeAvgLength_ThrowsArgumentOutOfRange() { - var ex = Assert.Throws(() => new Eacp(8, 48, avgLength: -1)); + var ex = Assert.Throws(() => new Acp(8, 48, avgLength: -1)); Assert.Equal("avgLength", ex.ParamName); } [Fact] public void Constructor_WithNullSource_ThrowsArgumentNullException() { - Assert.Throws(() => new Eacp(null!, 8, 48)); + Assert.Throws(() => new Acp(null!, 8, 48)); } [Fact] public void Constructor_WithValidSource_Subscribes() { var source = new TSeries(); - var eacp = new Eacp(source, 8, 48); + var acp = new Acp(source, 8, 48); source.Add(new TValue(DateTime.UtcNow, 100.0)); - Assert.NotEqual(default, eacp.Last); + Assert.NotEqual(default, acp.Last); } #endregion @@ -75,8 +75,8 @@ public class EacpTests [Fact] public void Update_ReturnsValidTValue() { - var eacp = new Eacp(8, 48); - var result = eacp.Update(new TValue(DateTime.UtcNow, 100.0)); + var acp = new Acp(8, 48); + var result = acp.Update(new TValue(DateTime.UtcNow, 100.0)); Assert.True(double.IsFinite(result.Value)); } @@ -84,59 +84,59 @@ public class EacpTests [Fact] public void Update_AfterWarmup_IsHotTrue() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); var gbm = new GBM(seed: 42); var bars = gbm.Fetch(200, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); foreach (var bar in bars) { - eacp.Update(new TValue(bar.Time, bar.Close)); + acp.Update(new TValue(bar.Time, bar.Close)); } - Assert.True(eacp.IsHot); + Assert.True(acp.IsHot); } [Fact] public void Update_DominantCycle_WithinRange() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); var gbm = new GBM(seed: 42); var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); foreach (var bar in bars) { - eacp.Update(new TValue(bar.Time, bar.Close)); + acp.Update(new TValue(bar.Time, bar.Close)); } // Dominant cycle should be within the specified range - Assert.InRange(eacp.DominantCycle, 8, 48); + Assert.InRange(acp.DominantCycle, 8, 48); } [Fact] public void Update_NormalizedPower_BetweenZeroAndOne() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); var gbm = new GBM(seed: 42); var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); foreach (var bar in bars) { - eacp.Update(new TValue(bar.Time, bar.Close)); + acp.Update(new TValue(bar.Time, bar.Close)); } - Assert.InRange(eacp.NormalizedPower, 0, 1); + Assert.InRange(acp.NormalizedPower, 0, 1); } [Fact] public void Update_InitialValue_NearMidpoint() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); // First update should return near midpoint of range - var result = eacp.Update(new TValue(DateTime.UtcNow, 100.0)); + var result = acp.Update(new TValue(DateTime.UtcNow, 100.0)); // Initial dominant cycle starts at (8+48)/2 = 28 Assert.True(result.Value >= 8 && result.Value <= 48); @@ -149,13 +149,13 @@ public class EacpTests [Fact] public void Update_IsNewTrue_AdvancesState() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); - eacp.Update(new TValue(DateTime.UtcNow, 100.0), isNew: true); - var first = eacp.Last.Value; + acp.Update(new TValue(DateTime.UtcNow, 100.0), isNew: true); + var first = acp.Last.Value; - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(1), 110.0), isNew: true); - var second = eacp.Last.Value; + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(1), 110.0), isNew: true); + var second = acp.Last.Value; // Values should potentially differ Assert.True(double.IsFinite(first) && double.IsFinite(second)); @@ -164,20 +164,20 @@ public class EacpTests [Fact] public void Update_IsNewFalse_ReplacesCurrentBar() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); // Build some history for (int i = 0; i < 100; i++) { - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10), isNew: true); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10), isNew: true); } - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 110.0), isNew: true); - var beforeCorrection = eacp.Last.Value; + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 110.0), isNew: true); + var beforeCorrection = acp.Last.Value; // Correct the bar with a different value - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 90.0), isNew: false); - var afterCorrection = eacp.Last.Value; + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 90.0), isNew: false); + var afterCorrection = acp.Last.Value; // Values should differ after correction Assert.True(double.IsFinite(beforeCorrection) && double.IsFinite(afterCorrection)); @@ -186,23 +186,23 @@ public class EacpTests [Fact] public void Update_MultipleCorrections_RestoresToSnapshot() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); // Build some history for (int i = 0; i < 100; i++) { - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + i), isNew: true); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + i), isNew: true); } // Add a new bar - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 150.0), isNew: true); - var originalValue = eacp.Last.Value; + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 150.0), isNew: true); + var originalValue = acp.Last.Value; // Correct multiple times - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 160.0), isNew: false); - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 140.0), isNew: false); - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 150.0), isNew: false); - var restoredValue = eacp.Last.Value; + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 160.0), isNew: false); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 140.0), isNew: false); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 150.0), isNew: false); + var restoredValue = acp.Last.Value; Assert.Equal(originalValue, restoredValue, Tolerance); } @@ -214,41 +214,41 @@ public class EacpTests [Fact] public void Reset_ClearsState() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); for (int i = 0; i < 200; i++) { - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + i)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + i)); } - Assert.True(eacp.IsHot); + Assert.True(acp.IsHot); - eacp.Reset(); + acp.Reset(); - Assert.False(eacp.IsHot); - Assert.Equal(default, eacp.Last); + Assert.False(acp.IsHot); + Assert.Equal(default, acp.Last); } [Fact] public void Reset_AllowsReuse() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); // First run for (int i = 0; i < 200; i++) { - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10)); } - var firstResult = eacp.Last.Value; + var firstResult = acp.Last.Value; - eacp.Reset(); + acp.Reset(); // Second run with same data for (int i = 0; i < 200; i++) { - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10)); } - var secondResult = eacp.Last.Value; + var secondResult = acp.Last.Value; Assert.Equal(firstResult, secondResult, Tolerance); } @@ -260,34 +260,34 @@ public class EacpTests [Fact] public void Update_NaN_UsesLastValidValue() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); - eacp.Update(new TValue(DateTime.UtcNow, 100.0)); - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(1), double.NaN)); + acp.Update(new TValue(DateTime.UtcNow, 100.0)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(1), double.NaN)); - Assert.True(double.IsFinite(eacp.Last.Value)); + Assert.True(double.IsFinite(acp.Last.Value)); } [Fact] public void Update_Infinity_UsesLastValidValue() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); - eacp.Update(new TValue(DateTime.UtcNow, 100.0)); - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(1), double.PositiveInfinity)); + acp.Update(new TValue(DateTime.UtcNow, 100.0)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(1), double.PositiveInfinity)); - Assert.True(double.IsFinite(eacp.Last.Value)); + Assert.True(double.IsFinite(acp.Last.Value)); } [Fact] public void Update_NegativeInfinity_UsesLastValidValue() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); - eacp.Update(new TValue(DateTime.UtcNow, 100.0)); - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(1), double.NegativeInfinity)); + acp.Update(new TValue(DateTime.UtcNow, 100.0)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(1), double.NegativeInfinity)); - Assert.True(double.IsFinite(eacp.Last.Value)); + Assert.True(double.IsFinite(acp.Last.Value)); } #endregion @@ -308,7 +308,7 @@ public class EacpTests var bars = gbm.Fetch(dataLen, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); // Streaming - var streaming = new Eacp(minPeriod, maxPeriod); + var streaming = new Acp(minPeriod, maxPeriod); foreach (var bar in bars) { streaming.Update(new TValue(bar.Time, bar.Close)); @@ -321,7 +321,7 @@ public class EacpTests tSeries.Add(new TValue(bar.Time, bar.Close)); } - var batch = Eacp.Batch(tSeries, minPeriod, maxPeriod); + var batch = Acp.Batch(tSeries, minPeriod, maxPeriod); // Compare last values Assert.Equal(batch[^1].Value, streaming.Last.Value, Tolerance); @@ -338,7 +338,7 @@ public class EacpTests var bars = gbm.Fetch(dataLen, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); // Streaming - var streaming = new Eacp(minPeriod, maxPeriod); + var streaming = new Acp(minPeriod, maxPeriod); var streamingResults = new double[dataLen]; for (int i = 0; i < dataLen; i++) { @@ -354,7 +354,7 @@ public class EacpTests source[i] = bars[i].Close; } - Eacp.Batch(source, batchResults, minPeriod, maxPeriod); + Acp.Batch(source, batchResults, minPeriod, maxPeriod); // Compare all values for (int i = 0; i < dataLen; i++) @@ -373,7 +373,7 @@ public class EacpTests double[] source = new double[100]; double[] output = new double[50]; - var ex = Assert.Throws(() => Eacp.Batch(source, output, 8, 48)); + var ex = Assert.Throws(() => Acp.Batch(source, output, 8, 48)); Assert.Equal("output", ex.ParamName); } @@ -383,7 +383,7 @@ public class EacpTests double[] source = new double[100]; double[] output = new double[100]; - Assert.Throws(() => Eacp.Batch(source, output, 2, 48)); + Assert.Throws(() => Acp.Batch(source, output, 2, 48)); } [Fact] @@ -392,7 +392,7 @@ public class EacpTests double[] source = new double[100]; double[] output = new double[100]; - Assert.Throws(() => Eacp.Batch(source, output, 8, 8)); + Assert.Throws(() => Acp.Batch(source, output, 8, 8)); } [Fact] @@ -401,7 +401,7 @@ public class EacpTests double[] source = []; double[] output = []; - var ex = Record.Exception(() => Eacp.Batch(source, output, 8, 48)); + var ex = Record.Exception(() => Acp.Batch(source, output, 8, 48)); Assert.Null(ex); } @@ -411,7 +411,7 @@ public class EacpTests double[] source = { 100, 101, double.NaN, 103, 104, 105, 106, 107, 108, 109 }; double[] output = new double[10]; - Eacp.Batch(source, output, 3, 8); + Acp.Batch(source, output, 3, 8); foreach (double v in output) { @@ -427,23 +427,23 @@ public class EacpTests public void Chaining_PropagatesUpdates() { var source = new TSeries(); - var eacp = new Eacp(source, 8, 48); + var acp = new Acp(source, 8, 48); for (int i = 0; i < 200; i++) { source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10)); } - Assert.True(eacp.IsHot); - Assert.True(double.IsFinite(eacp.Last.Value)); + Assert.True(acp.IsHot); + Assert.True(double.IsFinite(acp.Last.Value)); } [Fact] public void Chaining_MultipleIndicators() { var source = new TSeries(); - var eacp1 = new Eacp(source, 8, 48); - var eacp2 = new Eacp(source, 12, 60); + var acp1 = new Acp(source, 8, 48); + var acp2 = new Acp(source, 12, 60); for (int i = 0; i < 300; i++) { @@ -451,11 +451,11 @@ public class EacpTests } // Both should have values - Assert.True(double.IsFinite(eacp1.Last.Value)); - Assert.True(double.IsFinite(eacp2.Last.Value)); + Assert.True(double.IsFinite(acp1.Last.Value)); + Assert.True(double.IsFinite(acp2.Last.Value)); // Different ranges should produce different results - Assert.NotEqual(eacp1.Last.Value, eacp2.Last.Value); + Assert.NotEqual(acp1.Last.Value, acp2.Last.Value); } #endregion @@ -468,35 +468,35 @@ public class EacpTests [InlineData(12, 100)] public void Update_DifferentRanges_ProducesValidResults(int minPeriod, int maxPeriod) { - var eacp = new Eacp(minPeriod, maxPeriod); + var acp = new Acp(minPeriod, maxPeriod); var gbm = new GBM(seed: 42); var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); foreach (var bar in bars) { - eacp.Update(new TValue(bar.Time, bar.Close)); + acp.Update(new TValue(bar.Time, bar.Close)); } - Assert.True(eacp.IsHot); - Assert.InRange(eacp.DominantCycle, minPeriod, maxPeriod); + Assert.True(acp.IsHot); + Assert.InRange(acp.DominantCycle, minPeriod, maxPeriod); } [Fact] public void Update_EnhanceFalse_ProducesValidResults() { - var eacp = new Eacp(8, 48, avgLength: 3, enhance: false); + var acp = new Acp(8, 48, avgLength: 3, enhance: false); var gbm = new GBM(seed: 42); var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); foreach (var bar in bars) { - eacp.Update(new TValue(bar.Time, bar.Close)); + acp.Update(new TValue(bar.Time, bar.Close)); } - Assert.True(eacp.IsHot); - Assert.InRange(eacp.DominantCycle, 8, 48); + Assert.True(acp.IsHot); + Assert.InRange(acp.DominantCycle, 8, 48); } [Theory] @@ -506,18 +506,18 @@ public class EacpTests [InlineData(10)] public void Update_DifferentAvgLength_ProducesValidResults(int avgLength) { - var eacp = new Eacp(8, 48, avgLength: avgLength); + var acp = new Acp(8, 48, avgLength: avgLength); var gbm = new GBM(seed: 42); var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); foreach (var bar in bars) { - eacp.Update(new TValue(bar.Time, bar.Close)); + acp.Update(new TValue(bar.Time, bar.Close)); } - Assert.True(eacp.IsHot); - Assert.InRange(eacp.DominantCycle, 8, 48); + Assert.True(acp.IsHot); + Assert.InRange(acp.DominantCycle, 8, 48); } #endregion diff --git a/lib/cycles/eacp/tests/Eacp.Validation.Tests.cs b/lib/cycles/acp/tests/Acp.Validation.Tests.cs similarity index 72% rename from lib/cycles/eacp/tests/Eacp.Validation.Tests.cs rename to lib/cycles/acp/tests/Acp.Validation.Tests.cs index 65f83d0d..b61e6bad 100644 --- a/lib/cycles/eacp/tests/Eacp.Validation.Tests.cs +++ b/lib/cycles/acp/tests/Acp.Validation.Tests.cs @@ -3,12 +3,12 @@ using Xunit; namespace QuanTAlib.Tests; /// -/// Validation tests for EACP (Ehlers Autocorrelation Periodogram). -/// EACP is Ehlers' proprietary indicator not commonly implemented in trading libraries +/// Validation tests for ACP (Ehlers Autocorrelation Periodogram). +/// ACP is Ehlers' proprietary indicator not commonly implemented in trading libraries /// (TA-Lib, Skender, Tulip), so validation is done against mathematical properties /// and known theoretical results based on the original PineScript implementation. /// -public class EacpValidationTests +public class AcpValidationTests { private const double Tolerance = 1e-9; @@ -19,42 +19,42 @@ public class EacpValidationTests { // For constant input, autocorrelation is undefined but the algorithm // should still produce a value within the valid range - var eacp = new Eacp(8, 48, 3, true); + var acp = new Acp(8, 48, 3, true); for (int i = 0; i < 500; i++) { - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0)); } - Assert.InRange(eacp.DominantCycle, 8, 48); - Assert.InRange(eacp.NormalizedPower, 0.0, 1.0); + Assert.InRange(acp.DominantCycle, 8, 48); + Assert.InRange(acp.NormalizedPower, 0.0, 1.0); } [Fact] public void Validation_SineWave_DetectsPeriod() { - // EACP should detect the dominant period in a sine wave + // ACP should detect the dominant period in a sine wave const int knownPeriod = 20; - var eacp = new Eacp(8, 48, 3, true); + var acp = new Acp(8, 48, 3, true); // Generate sine wave with known period for (int i = 0; i < 500; i++) { double price = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / knownPeriod)); - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); } // Dominant cycle should be close to the known period // Allow 20% tolerance due to filter lag and warmup effects double tolerance = knownPeriod * 0.3; - Assert.InRange(eacp.DominantCycle, knownPeriod - tolerance, knownPeriod + tolerance); + Assert.InRange(acp.DominantCycle, knownPeriod - tolerance, knownPeriod + tolerance); } [Fact] public void Validation_MultipleCycles_DetectsDominant() { - // When multiple cycles are present, EACP should detect the dominant one - var eacp = new Eacp(8, 48, 3, true); + // When multiple cycles are present, ACP should detect the dominant one + var acp = new Acp(8, 48, 3, true); // Generate signal with dominant 16-period cycle and weaker 32-period cycle for (int i = 0; i < 500; i++) @@ -62,26 +62,26 @@ public class EacpValidationTests double cycle16 = 10.0 * Math.Sin(2.0 * Math.PI * i / 16.0); // Stronger double cycle32 = 5.0 * Math.Sin(2.0 * Math.PI * i / 32.0); // Weaker double price = 100.0 + cycle16 + cycle32; - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); } // Should detect the dominant cycle (16) rather than the weaker one - Assert.InRange(eacp.DominantCycle, 12, 24); + Assert.InRange(acp.DominantCycle, 12, 24); } [Fact] public void Validation_NormalizedPower_BoundedZeroToOne() { // Normalized power should always be between 0 and 1 - var eacp = new Eacp(8, 48, 3, true); + var acp = new Acp(8, 48, 3, true); var gbm = new GBM(seed: 42); var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); foreach (var bar in bars) { - eacp.Update(new TValue(bar.Time, bar.Close)); - Assert.InRange(eacp.NormalizedPower, 0.0, 1.0); + acp.Update(new TValue(bar.Time, bar.Close)); + Assert.InRange(acp.NormalizedPower, 0.0, 1.0); } } @@ -104,8 +104,8 @@ public class EacpValidationTests Assert.InRange(expectedAlphaHP, 0.0, 1.0); // The indicator should use this coefficient - var eacp = new Eacp(8, maxPeriod); - Assert.True(eacp.Name.Contains("48", StringComparison.Ordinal)); + var acp = new Acp(8, maxPeriod); + Assert.True(acp.Name.Contains("48", StringComparison.Ordinal)); } [Fact] @@ -149,20 +149,20 @@ public class EacpValidationTests // Enhance mode applies cubic emphasis (pwr^3) // This should make peaks more pronounced - var eacpEnhanced = new Eacp(8, 48, 3, enhance: true); - var eacpNormal = new Eacp(8, 48, 3, enhance: false); + var acpEnhanced = new Acp(8, 48, 3, enhance: true); + var acpNormal = new Acp(8, 48, 3, enhance: false); // Generate sine wave for (int i = 0; i < 300; i++) { double price = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0)); - eacpEnhanced.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); - eacpNormal.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); + acpEnhanced.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); + acpNormal.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); } // Both should produce valid results - Assert.InRange(eacpEnhanced.DominantCycle, 8, 48); - Assert.InRange(eacpNormal.DominantCycle, 8, 48); + Assert.InRange(acpEnhanced.DominantCycle, 8, 48); + Assert.InRange(acpNormal.DominantCycle, 8, 48); } #endregion @@ -183,7 +183,7 @@ public class EacpValidationTests var bars = gbm.Fetch(dataLen, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); // Streaming - var streaming = new Eacp(minPeriod, maxPeriod); + var streaming = new Acp(minPeriod, maxPeriod); foreach (var bar in bars) { streaming.Update(new TValue(bar.Time, bar.Close)); @@ -196,7 +196,7 @@ public class EacpValidationTests tSeries.Add(new TValue(bar.Time, bar.Close)); } - var batch = Eacp.Batch(tSeries, minPeriod, maxPeriod); + var batch = Acp.Batch(tSeries, minPeriod, maxPeriod); // Compare last values Assert.Equal(batch[^1].Value, streaming.Last.Value, Tolerance); @@ -219,7 +219,7 @@ public class EacpValidationTests tSeries.Add(new TValue(bar.Time, bar.Close)); } - var tSeriesResult = Eacp.Batch(tSeries, minPeriod, maxPeriod); + var tSeriesResult = Acp.Batch(tSeries, minPeriod, maxPeriod); // Span approach double[] source = new double[dataLen]; @@ -229,7 +229,7 @@ public class EacpValidationTests source[i] = bars[i].Close; } - Eacp.Batch(source, spanResult, minPeriod, maxPeriod); + Acp.Batch(source, spanResult, minPeriod, maxPeriod); // Compare all values for (int i = 0; i < dataLen; i++) @@ -252,15 +252,15 @@ public class EacpValidationTests var gbm = new GBM(seed: 42); var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); - var eacp = new Eacp(minPeriod, maxPeriod); + var acp = new Acp(minPeriod, maxPeriod); foreach (var bar in bars) { - eacp.Update(new TValue(bar.Time, bar.Close)); + acp.Update(new TValue(bar.Time, bar.Close)); } - Assert.True(eacp.IsHot); - Assert.InRange(eacp.DominantCycle, minPeriod, maxPeriod); - Assert.InRange(eacp.NormalizedPower, 0.0, 1.0); + Assert.True(acp.IsHot); + Assert.InRange(acp.DominantCycle, minPeriod, maxPeriod); + Assert.InRange(acp.NormalizedPower, 0.0, 1.0); } [Theory] @@ -272,14 +272,14 @@ public class EacpValidationTests var gbm = new GBM(seed: 42); var bars = gbm.Fetch(300, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); - var eacp = new Eacp(8, 48, avgLength); + var acp = new Acp(8, 48, avgLength); foreach (var bar in bars) { - eacp.Update(new TValue(bar.Time, bar.Close)); + acp.Update(new TValue(bar.Time, bar.Close)); } - Assert.True(eacp.IsHot); - Assert.InRange(eacp.DominantCycle, 8, 48); + Assert.True(acp.IsHot); + Assert.InRange(acp.DominantCycle, 8, 48); } #endregion @@ -289,46 +289,46 @@ public class EacpValidationTests [Fact] public void Validation_VerySmallPrices_HandledCorrectly() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); for (int i = 0; i < 200; i++) { double price = 0.0001 + (0.00001 * Math.Sin(2.0 * Math.PI * i / 20.0)); - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); } - Assert.True(eacp.IsHot); - Assert.InRange(eacp.DominantCycle, 8, 48); + Assert.True(acp.IsHot); + Assert.InRange(acp.DominantCycle, 8, 48); } [Fact] public void Validation_VeryLargePrices_HandledCorrectly() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); for (int i = 0; i < 200; i++) { double price = 1e10 + (1e9 * Math.Sin(2.0 * Math.PI * i / 20.0)); - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); } - Assert.True(eacp.IsHot); - Assert.InRange(eacp.DominantCycle, 8, 48); + Assert.True(acp.IsHot); + Assert.InRange(acp.DominantCycle, 8, 48); } [Fact] public void Validation_HighVolatility_StableResults() { - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); var gbm = new GBM(seed: 42, sigma: 0.5); // High volatility var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); foreach (var bar in bars) { - eacp.Update(new TValue(bar.Time, bar.Close)); - Assert.InRange(eacp.DominantCycle, 8, 48); - Assert.InRange(eacp.NormalizedPower, 0.0, 1.0); + acp.Update(new TValue(bar.Time, bar.Close)); + Assert.InRange(acp.DominantCycle, 8, 48); + Assert.InRange(acp.NormalizedPower, 0.0, 1.0); } } @@ -337,14 +337,14 @@ public class EacpValidationTests { // When all prices are identical, correlation is undefined // but the algorithm should still produce valid output - var eacp = new Eacp(8, 48); + var acp = new Acp(8, 48); for (int i = 0; i < 300; i++) { - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0)); } - Assert.InRange(eacp.DominantCycle, 8, 48); + Assert.InRange(acp.DominantCycle, 8, 48); } #endregion @@ -355,38 +355,38 @@ public class EacpValidationTests public void Validation_Autocorrelation_SineWaveHighCorrelation() { // A pure sine wave should have high autocorrelation at its period - var eacp = new Eacp(8, 48, 3, true); + var acp = new Acp(8, 48, 3, true); // Generate pure sine wave for (int i = 0; i < 300; i++) { double price = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0)); - eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); + acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); } // Should have relatively high normalized power for a pure sine - Assert.True(eacp.NormalizedPower > 0.1, - $"Pure sine should have detectable power, got {eacp.NormalizedPower}"); + Assert.True(acp.NormalizedPower > 0.1, + $"Pure sine should have detectable power, got {acp.NormalizedPower}"); } [Fact] public void Validation_RandomNoise_LowPower() { // Random noise should have low spectral power at any frequency - var eacp = new Eacp(8, 48, 3, true); + var acp = new Acp(8, 48, 3, true); var gbm = new GBM(seed: 42, mu: 0, sigma: 0.01); // Nearly pure noise var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1)); foreach (var bar in bars) { - eacp.Update(new TValue(bar.Time, bar.Close)); + acp.Update(new TValue(bar.Time, bar.Close)); } // For noise, dominant cycle detection is weak // Just verify it doesn't crash and produces valid output - Assert.InRange(eacp.DominantCycle, 8, 48); - Assert.InRange(eacp.NormalizedPower, 0.0, 1.0); + Assert.InRange(acp.DominantCycle, 8, 48); + Assert.InRange(acp.NormalizedPower, 0.0, 1.0); } #endregion @@ -400,8 +400,8 @@ public class EacpValidationTests const int period1 = 12; const int period2 = 36; - var eacp1 = new Eacp(8, 48); - var eacp2 = new Eacp(8, 48); + var acp1 = new Acp(8, 48); + var acp2 = new Acp(8, 48); // Generate two different sine waves for (int i = 0; i < 500; i++) @@ -409,19 +409,19 @@ public class EacpValidationTests double price1 = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / period1)); double price2 = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / period2)); - eacp1.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price1)); - eacp2.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price2)); + acp1.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price1)); + acp2.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price2)); } // They should detect different dominant cycles - double diff = Math.Abs(eacp1.DominantCycle - eacp2.DominantCycle); - Assert.True(diff > 5, $"Should detect different cycles: {eacp1.DominantCycle} vs {eacp2.DominantCycle}"); + double diff = Math.Abs(acp1.DominantCycle - acp2.DominantCycle); + Assert.True(diff > 5, $"Should detect different cycles: {acp1.DominantCycle} vs {acp2.DominantCycle}"); } [Fact] - public void Eacp_Correction_Recomputes() + public void Acp_Correction_Recomputes() { - var ind = new Eacp(8, 48, 3, true); + var ind = new Acp(8, 48, 3, true); var t0 = new DateTime(946_684_800_000_000_0L, DateTimeKind.Utc); // Build state well past warmup diff --git a/lib/cycles/cg/cg.md b/lib/cycles/cg/cg.md index f2f53116..6648145d 100644 --- a/lib/cycles/cg/cg.md +++ b/lib/cycles/cg/cg.md @@ -13,7 +13,7 @@ | **PineScript** | [cg.pine](cg.pine) | - CG identifies potential turning points using the physics concept of weighted center of mass applied to a price window. -- **Similar:** [Ccyc](../ccyc/Ccyc.md), [EACP](../eacp/eacp.md) | **Complementary:** RSI for momentum confirmation | **Trading note:** Center of Gravity oscillator by Ehlers; leads price turns with minimal lag. +- **Similar:** [Ccyc](../ccyc/Ccyc.md), [ACP](../acp/acp.md) | **Complementary:** RSI for momentum confirmation | **Trading note:** Center of Gravity oscillator by Ehlers; leads price turns with minimal lag. - Validated against TA-Lib, Skender, and Tulip reference implementations where available. CG identifies potential turning points using the physics concept of weighted center of mass applied to a price window. Developed by John Ehlers, the oscillator measures where the "weight" of prices is concentrated within a lookback period, producing a leading indicator that oscillates around zero with minimal lag compared to traditional moving average crossover systems. diff --git a/python/SPEC.md b/python/SPEC.md index d4ed9e0c..9c04a770 100644 --- a/python/SPEC.md +++ b/python/SPEC.md @@ -974,7 +974,7 @@ All channel indicators output 3 spans: upper, middle, lower (Pattern I). | ccyc | `Ccyc` | A | alpha | | cg | `Cg` | A | period | | dsp | `Dsp` | A | period | -| eacp | `Eacp` | A | minPeriod, maxPeriod, avgLength, enhance | +| acp | `Acp` | A | minPeriod, maxPeriod, avgLength, enhance | | ebsw | `Ebsw` | A | hpLength, ssfLength | | homod | `Homod` | A | minPeriod, maxPeriod | | ht_dcperiod | `HtDcperiod` | A | — | diff --git a/python/quantalib/_bridge.py b/python/quantalib/_bridge.py index 9fc0df65..80330992 100644 --- a/python/quantalib/_bridge.py +++ b/python/quantalib/_bridge.py @@ -564,7 +564,7 @@ HAS_CG = _bind("qtl_cg", [_dp, _ci, _dp, _ci]) HAS_DSP = _bind("qtl_dsp", [_dp, _ci, _dp, _ci]) HAS_CCOR = _bind("qtl_ccor", [_dp, _ci, _dp, _ci, _cd]) HAS_EBSW = _bind("qtl_ebsw", [_dp, _ci, _dp, _ci, _ci]) -HAS_EACP = _bind("qtl_eacp", [_dp, _ci, _dp, _ci, _ci, _ci, _ci]) +HAS_ACP = _bind("qtl_acp", [_dp, _ci, _dp, _ci, _ci, _ci, _ci]) # ── Numerics (Exports.cs — manual) ── HAS_CHANGE = _bind("qtl_change", [_dp, _ci, _dp, _ci]) diff --git a/python/quantalib/cycles.py b/python/quantalib/cycles.py index 90b01d46..367271b1 100644 --- a/python/quantalib/cycles.py +++ b/python/quantalib/cycles.py @@ -20,7 +20,7 @@ __all__ = [ "dsp", "ccor", "ebsw", - "eacp", + "acp", ] @@ -142,11 +142,11 @@ def ebsw(close: object, hp_length: int = 40, ssf_length: int = 10, return _wrap(dst, idx, f"EBSW_{hp_length}", "cycles", offset) -def eacp(close: object, min_period: int = 8, max_period: int = 48, - avg_length: int = 3, enhance: int = 1, - offset: int = 0, **kwargs) -> object: +def acp(close: object, min_period: int = 8, max_period: int = 48, + avg_length: int = 3, enhance: int = 1, + offset: int = 0, **kwargs) -> object: """Ehlers Autocorrelation Periodogram.""" offset = int(offset) src, idx = _arr(close); n = len(src); dst = _out(n) - _check(_lib.qtl_eacp(_ptr(src), n, _ptr(dst), int(min_period), int(max_period), int(avg_length), int(enhance))) - return _wrap(dst, idx, f"EACP_{min_period}_{max_period}", "cycles", offset) + _check(_lib.qtl_acp(_ptr(src), n, _ptr(dst), int(min_period), int(max_period), int(avg_length), int(enhance))) + return _wrap(dst, idx, f"ACP_{min_period}_{max_period}", "cycles", offset) diff --git a/python/src/Exports.cs b/python/src/Exports.cs index 52dcb1c2..b542f689 100644 --- a/python/src/Exports.cs +++ b/python/src/Exports.cs @@ -1465,13 +1465,13 @@ public static unsafe partial class Exports catch { return StatusCodes.QTL_ERR_INTERNAL; } } - // Eacp: (int minPeriod, int maxPeriod, int avgLength, bool enhance → int) - [UnmanagedCallersOnly(EntryPoint = "qtl_eacp")] - public static int QtlEacp(double* src, int n, double* dst, int minPeriod, int maxPeriod, int avgLength, int enhance) + // Acp: (int minPeriod, int maxPeriod, int avgLength, bool enhance → int) + [UnmanagedCallersOnly(EntryPoint = "qtl_acp")] + public static int QtlAcp(double* src, int n, double* dst, int minPeriod, int maxPeriod, int avgLength, int enhance) { int v = Chk1(src, dst, n); if (v != 0) return v; v = ChkPeriod(minPeriod); if (v != 0) return v; - try { Eacp.Batch(Src(src, n), Dst(dst, n), minPeriod, maxPeriod, avgLength, enhance != 0); return StatusCodes.QTL_OK; } + try { Acp.Batch(Src(src, n), Dst(dst, n), minPeriod, maxPeriod, avgLength, enhance != 0); return StatusCodes.QTL_OK; } catch { return StatusCodes.QTL_ERR_INTERNAL; } } diff --git a/python/tests/reports/pandas_ta_all_exported_report.md b/python/tests/reports/pandas_ta_all_exported_report.md index 3d75ff81..734a7876 100644 --- a/python/tests/reports/pandas_ta_all_exported_report.md +++ b/python/tests/reports/pandas_ta_all_exported_report.md @@ -73,7 +73,7 @@ | `dwma` | ⏭️ | no comparable pandas-ta equivalent | | `dwt` | ⏭️ | no comparable pandas-ta equivalent | | `dymoi` | ⏭️ | no comparable pandas-ta equivalent | -| `eacp` | ⏭️ | no comparable pandas-ta equivalent | +| `acp` | ⏭️ | no comparable pandas-ta equivalent | | `ebsw` | ⚠️ | max_diff=1.846e+00, n=100 | | `edcf` | ⏭️ | no comparable pandas-ta equivalent | | `efi` | ✔️ | max_diff=3.411e-13, n=100 | diff --git a/python/tests/run_all_exported_pandasta_validation.py b/python/tests/run_all_exported_pandasta_validation.py index dc303a82..9c97e0c5 100644 --- a/python/tests/run_all_exported_pandasta_validation.py +++ b/python/tests/run_all_exported_pandasta_validation.py @@ -103,7 +103,7 @@ NO_PTA_EQUIVALENT: set[str] = { "bwma", "ccor", "ccv", "ccyc", "cfitz", "change", "cheby1", "cheby2", "cointegration", "conv", "coral", "correl", "covariance", "crma", "cv", "cvi", "cwt", "deco", "decycler", "dem", "dema_alpha", "dosc", - "dsma", "dsp", "dwma", "dwt", "dymi", "eacp", "edcf", "elliptic", + "dsma", "dsp", "dwma", "dwt", "dymi", "acp", "edcf", "elliptic", "ema_alpha", "etherm", "evwma", "ewma", "expdist", "exptrans", "fisher04", "gdema", "hanma", "hema", "kri", "lema", "lsma", "mae", "mape", "mse", "parzen", "pvd", "rain", "rmse", "sgma", "sinema", diff --git a/python/tests/test_shapes.py b/python/tests/test_shapes.py index 87f59d46..73d27645 100644 --- a/python/tests/test_shapes.py +++ b/python/tests/test_shapes.py @@ -56,7 +56,7 @@ MULTI_PARAM = [ ("baxterking", {"length": 12, "min_period": 6, "max_period": 32}), ("cfitz", {"length": 6, "bw_period": 32}), ("ebsw", {"hp_length": 40, "ssf_length": 10}), - ("eacp", {"min_period": 8, "max_period": 48, "avg_length": 3, "enhance": 1}), + ("acp", {"min_period": 8, "max_period": 48, "avg_length": 3, "enhance": 1}), ("betadist", {"length": 50, "alpha": 2.0, "beta": 2.0}), ("expdist", {"length": 50, "lam": 3.0}), ("binomdist", {"length": 50, "trials": 20, "threshold": 10}),