refactor: move Decay/Edecay from trends_IIR to numerics; update filter signatures
- Move lib/trends_IIR/decay/ → lib/numerics/decay/ - Move lib/trends_IIR/edecay/ → lib/numerics/edecay/ - Update Category in Decay.md/Edecay.md from Trends (IIR) to Numerics - Add DECAY/EDECAY entries to lib/numerics/_index.md and docs/indicators.md - Update filter signature .md files and .svg assets - Update trends_IIR signature docs (htit, mama, holt, etc.) - All 163 tests passing, 0 warnings, 0 errors
@@ -433,7 +433,9 @@ Mathematical transformations and derivative indicators. Building blocks for anal
|
||||
| [**WEIBULLDIST**](../lib/numerics/weibulldist/Weibulldist.md) | Weibull Distribution (CDF) | Rolling Weibull CDF — two-parameter closed-form probability transform via pow + exp |
|
||||
| [**CHANGE**](../lib/numerics/change/Change.md) | Percentage Change | Relative price movement |
|
||||
| [**CWT**](../lib/numerics/cwt/Cwt.md) | Continuous Wavelet Transform | Morlet CWT magnitude at a specified scale — time-frequency decomposition |
|
||||
| [**DECAY**](../lib/numerics/decay/Decay.md) | Linear Decay | Peak envelope with linear degradation |
|
||||
| [**DWT**](../lib/numerics/dwt/Dwt.md) | Discrete Wavelet Transform | À trous Haar stationary DWT — multi-resolution approximation + detail, WarmupPeriod = 2^levels |
|
||||
| [**EDECAY**](../lib/numerics/edecay/Edecay.md) | Exponential Decay | Peak envelope with exponential degradation |
|
||||
| [**EXPTRANS**](../lib/numerics/exptrans/Exptrans.md) | Exponential Transform | e^x for log-space reversal |
|
||||
| [**HIGHEST**](../lib/numerics/highest/Highest.md) | Rolling Maximum | O(1) via monotonic deque |
|
||||
| [**MAXINDEX**](../lib/numerics/maxindex/Maxindex.md) | Rolling Maximum Index | Position of max in window |
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
| **Outputs** | Single series (BaxterKing) |
|
||||
| **Output range** | Oscillates around zero |
|
||||
| **Warmup** | `2K+1` bars (default 25) |
|
||||
| **Signature** | [baxterking_signature](baxterking_signature.md) |
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# BAXTERKING Signature
|
||||
|
||||

|
||||
|
Before Width: | Height: | Size: 546 KiB |
@@ -8,7 +8,6 @@
|
||||
| **Outputs** | Single series (BPF) |
|
||||
| **Output range** | Oscillates around zero |
|
||||
| **Warmup** | `Math.Max(lowerPeriod, upperPeriod)` bars |
|
||||
| **Signature** | [bpf_signature](bpf_signature.md) |
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# BPF Signature
|
||||
|
||||

|
||||
|
Before Width: | Height: | Size: 553 KiB |
@@ -8,7 +8,6 @@
|
||||
| **Outputs** | Single series (Cfitz) |
|
||||
| **Output range** | Oscillates around zero |
|
||||
| **Warmup** | `2` bars |
|
||||
| **Signature** | [cfitz_signature](cfitz_signature.md) |
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# CFITZ Signature
|
||||
|
||||

|
||||
|
Before Width: | Height: | Size: 544 KiB |
@@ -8,6 +8,8 @@
|
||||
| **Outputs** | Single series (Gauss) |
|
||||
| **Output range** | Tracks input |
|
||||
| **Warmup** | 1 bar |
|
||||
| **Signature** | [gauss_signature](gauss_signature.md) |
|
||||
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# ELLIPTIC Signature
|
||||
|
||||

|
||||
@@ -8,6 +8,8 @@
|
||||
| **Outputs** | Single series (HP) |
|
||||
| **Output range** | Tracks input |
|
||||
| **Warmup** | 1 bar |
|
||||
| **Signature** | [hp_signature](hp_signature.md) |
|
||||
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# ELLIPTIC Signature
|
||||
|
||||

|
||||
@@ -8,7 +8,6 @@
|
||||
| **Outputs** | Single series (HPF) |
|
||||
| **Output range** | Tracks input |
|
||||
| **Warmup** | 1 bar |
|
||||
| **Signature** | [hpf_signature](hpf_signature.md) |
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# HPF Signature
|
||||
|
||||

|
||||
|
Before Width: | Height: | Size: 545 KiB |
@@ -8,6 +8,8 @@
|
||||
| **Outputs** | Single series (Kalman) |
|
||||
| **Output range** | Tracks input |
|
||||
| **Warmup** | `10` bars |
|
||||
| **Signature** | [kalman_signature](kalman_signature.md) |
|
||||
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# ELLIPTIC Signature
|
||||
|
||||

|
||||
@@ -8,6 +8,8 @@
|
||||
| **Outputs** | Single series (Laguerre) |
|
||||
| **Output range** | Tracks input |
|
||||
| **Warmup** | `WarmupBars` bars |
|
||||
| **Signature** | [laguerre_signature](laguerre_signature.md) |
|
||||
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# ELLIPTIC Signature
|
||||
|
||||

|
||||
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 542 KiB |
@@ -8,6 +8,8 @@
|
||||
| **Outputs** | Single series (OneEuro) |
|
||||
| **Output range** | Tracks input |
|
||||
| **Warmup** | `1` bars |
|
||||
| **Signature** | [oneeuro_signature](oneeuro_signature.md) |
|
||||
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# LOESS Signature
|
||||
|
||||

|
||||
@@ -8,6 +8,8 @@
|
||||
| **Outputs** | Single series (RLS) |
|
||||
| **Output range** | Tracks input |
|
||||
| **Warmup** | `order + 1` bars |
|
||||
| **Signature** | [rls_signature](rls_signature.md) |
|
||||
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# LOESS Signature
|
||||
|
||||

|
||||
|
Before Width: | Height: | Size: 537 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 546 KiB |
|
Before Width: | Height: | Size: 548 KiB |
@@ -8,7 +8,6 @@
|
||||
| **Outputs** | Single series (VOSS) |
|
||||
| **Output range** | Oscillates around zero |
|
||||
| **Warmup** | `period` bars |
|
||||
| **Signature** | [voss_signature](voss_signature.md) |
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# VOSS Signature
|
||||
|
||||

|
||||
|
Before Width: | Height: | Size: 539 KiB |
@@ -8,6 +8,8 @@
|
||||
| **Outputs** | Single series (Wavelet) |
|
||||
| **Output range** | Tracks input |
|
||||
| **Warmup** | `2^levels` bars (default 16) |
|
||||
| **Signature** | [wavelet_signature](wavelet_signature.md) |
|
||||
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# SGF Signature
|
||||
|
||||

|
||||
@@ -10,8 +10,10 @@ Basic mathematical transforms and utility functions for time series. These build
|
||||
| [BETADIST](betadist/Betadist.md) | Beta Distribution | Beta probability distribution transform. |
|
||||
| [BINOMDIST](binomdist/Binomdist.md) | Binomial Distribution | Binomial probability distribution transform. |
|
||||
| [CHANGE](change/Change.md) | Percentage Change | Relative price movement over lookback period. |
|
||||
| [DECAY](decay/Decay.md) | Linear Decay | Peak envelope with linear degradation; max(input, prev − 1/period). |
|
||||
| [CWT](cwt/Cwt.md) | Continuous Wavelet Transform | Time-frequency decomposition with continuous wavelets. |
|
||||
| [DWT](dwt/Dwt.md) | Discrete Wavelet Transform | À trous Haar stationary DWT; multi-resolution approximation + detail decomposition. |
|
||||
| [EDECAY](edecay/Edecay.md) | Exponential Decay | Peak envelope with exponential degradation; max(input, prev × (period−1)/period). |
|
||||
| [EXPDIST](expdist/Expdist.md) | Exponential Distribution | Exponential probability distribution transform. |
|
||||
| [EXPTRANS](exptrans/Exptrans.md) | Exponential Transform | e^x transform for log-space conversion reversal. |
|
||||
| [FDIST](fdist/Fdist.md) | F-Distribution | Fisher-Snedecor probability distribution transform. |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Trends (IIR) |
|
||||
| **Category** | Numerics |
|
||||
| **Inputs** | Source (close) |
|
||||
| **Parameters** | `period` (default 5) |
|
||||
| **Outputs** | Single series (Decay) |
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Trends (IIR) |
|
||||
| **Category** | Numerics |
|
||||
| **Inputs** | Source (close) |
|
||||
| **Parameters** | `period` (default 5) |
|
||||
| **Outputs** | Single series (Edecay) |
|
||||
|
After Width: | Height: | Size: 545 KiB |
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 546 KiB |
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 546 KiB |
@@ -224,11 +224,12 @@ public sealed class Nlma : AbstractBase
|
||||
// ── Weight computation ─────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// Computes original Igorad two-phase kernel weights.
|
||||
/// Computes original Igorad two-phase kernel weights (MQL4 NonLagMA v7.1 order).
|
||||
/// Phase zone (i=0..period-2): t = i/(period-2), g = t≤0.5 ? 1 : 1/(3πt+1), w = g*cos(πt)
|
||||
/// Cycle zone (i=period-1..flen-2): t = 1 + (i-phase+1)*(2*Cycle-1)/(Cycle*period-1), same g/w
|
||||
/// Last tap (i=flen-1): weight = 0.
|
||||
/// weights[0] = newest bar, weights[flen-1] = oldest bar.
|
||||
/// weights[0] = newest bar (=1.0), weights[flen-1] = oldest bar (=0.0).
|
||||
/// Matches MQL4 alfa[] order: alfa[0]*Close[0] (newest) .. alfa[Len-1]*Close[Len-1] (oldest).
|
||||
/// Returns the signed weight sum for normalization.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -238,58 +239,36 @@ public sealed class Nlma : AbstractBase
|
||||
int phase = period - 1;
|
||||
double coeff = 3.0 * Math.PI;
|
||||
|
||||
// Compute weights in "oldest-first" order (taps[0]=oldest, taps[flen-1]=newest)
|
||||
// then reverse into weights[] so weights[0]=newest, weights[flen-1]=oldest
|
||||
const int StackallocThreshold = 256;
|
||||
double[]? rented = flen > StackallocThreshold ? ArrayPool<double>.Shared.Rent(flen) : null;
|
||||
Span<double> taps = flen <= StackallocThreshold
|
||||
? stackalloc double[flen]
|
||||
: rented!.AsSpan(0, flen);
|
||||
|
||||
// Compute weights directly in MQL4 alfa[] order:
|
||||
// weights[0] = alfa[0] = weight for newest bar (=1.0 at t=0)
|
||||
// weights[flen-1] = alfa[flen-1] = weight for oldest bar (=0.0)
|
||||
double wsum = 0.0;
|
||||
|
||||
try
|
||||
for (int i = 0; i < flen - 1; i++)
|
||||
{
|
||||
for (int i = 0; i < flen - 1; i++)
|
||||
double t;
|
||||
if (i <= phase - 1)
|
||||
{
|
||||
double t;
|
||||
if (i <= phase - 1)
|
||||
{
|
||||
// Phase zone: t ramps from 0 to 1
|
||||
t = phase > 1 ? (double)i / (phase - 1) : 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cycle zone: t continues from 1 upward
|
||||
double numer = (double)(i - phase + 1) * (2 * Cycle - 1);
|
||||
double denom = (double)(Cycle * period - 1);
|
||||
t = 1.0 + (denom > 0 ? numer / denom : 0.0);
|
||||
}
|
||||
|
||||
double beta = Math.Cos(Math.PI * t);
|
||||
double g = t <= 0.5 ? 1.0 : 1.0 / Math.FusedMultiplyAdd(coeff, t, 1.0);
|
||||
double w = g * beta;
|
||||
taps[i] = w;
|
||||
wsum += w;
|
||||
// Phase zone: t ramps from 0 to 1
|
||||
t = phase > 1 ? (double)i / (phase - 1) : 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cycle zone: t continues from 1 upward
|
||||
double numer = (double)(i - phase + 1) * (2 * Cycle - 1);
|
||||
double denom = (double)(Cycle * period - 1);
|
||||
t = 1.0 + (denom > 0 ? numer / denom : 0.0);
|
||||
}
|
||||
|
||||
// Last tap has weight 0 (original MQL4 loop goes to Len-2)
|
||||
taps[flen - 1] = 0.0;
|
||||
|
||||
// Reverse into weights[]: weights[0]=newest=taps[flen-1], weights[flen-1]=oldest=taps[0]
|
||||
for (int i = 0; i < flen; i++)
|
||||
{
|
||||
weights[i] = taps[flen - 1 - i];
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (rented != null)
|
||||
{
|
||||
ArrayPool<double>.Shared.Return(rented);
|
||||
}
|
||||
double beta = Math.Cos(Math.PI * t);
|
||||
double g = t <= 0.5 ? 1.0 : 1.0 / Math.FusedMultiplyAdd(coeff, t, 1.0);
|
||||
weights[i] = g * beta;
|
||||
wsum += weights[i];
|
||||
}
|
||||
|
||||
// Last tap has weight 0 (original MQL4 loop goes to Len-2)
|
||||
weights[flen - 1] = 0.0;
|
||||
|
||||
return wsum;
|
||||
}
|
||||
|
||||
@@ -297,7 +276,8 @@ public sealed class Nlma : AbstractBase
|
||||
|
||||
/// <summary>
|
||||
/// Convolves when buffer is full (count == flen). Uses precomputed weights.
|
||||
/// weights[0] = newest, weights[flen-1] = oldest. Normalized by signed weight sum.
|
||||
/// weights[0] = newest bar weight (=1.0), weights[flen-1] = oldest bar weight (=0.0).
|
||||
/// Normalized by signed weight sum. Matches MQL4: alfa[0]*Close[0] + ... + alfa[Len-1]*Close[Len-1].
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private double ConvolveFull()
|
||||
@@ -307,7 +287,7 @@ public sealed class Nlma : AbstractBase
|
||||
int capacity = _buffer.Capacity;
|
||||
double sum = 0.0;
|
||||
|
||||
// Iterate oldest-to-newest: oldest bar gets weights[flen-1], newest gets weights[0]
|
||||
// Iterate oldest-to-newest: oldest bar gets weights[flen-1] (≈0), newest gets weights[0] (=1.0)
|
||||
int wi = _flen - 1;
|
||||
for (int i = head; i < capacity; i++)
|
||||
{
|
||||
|
||||
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 546 KiB |
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 538 KiB |
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 545 KiB |
|
Before Width: | Height: | Size: 544 KiB After Width: | Height: | Size: 544 KiB |
@@ -8,6 +8,8 @@
|
||||
| **Outputs** | Single series (HTIT) |
|
||||
| **Output range** | Tracks input |
|
||||
| **Warmup** | `12` bars |
|
||||
| **Signature** | [htit_signature](htit_signature.md) |
|
||||
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# HOLT Signature
|
||||
|
||||

|
||||
|
After Width: | Height: | Size: 552 KiB |
@@ -8,6 +8,8 @@
|
||||
| **Outputs** | Single series (Mama) |
|
||||
| **Output range** | Tracks input |
|
||||
| **Warmup** | `50` bars |
|
||||
| **Signature** | [mama_signature](mama_signature.md) |
|
||||
|
||||
|
||||
### TL;DR
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# LTMA Signature
|
||||
|
||||

|
||||
|
After Width: | Height: | Size: 545 KiB |
|
Before Width: | Height: | Size: 527 KiB After Width: | Height: | Size: 527 KiB |