feat(dynamics): add PlusDI, MinusDI, PlusDM, MinusDM indicators

Complete thin Dx-composition wrapper indicators with full test coverage:

- PlusDi/MinusDi: Directional Indicator wrappers (DiPlus/DiMinus from Dx)
- PlusDm/MinusDm: Directional Movement wrappers (DmPlus/DmMinus from Dx)
- Individual validation tests per indicator directory (TALib, Skender, bounds)
- Combined unit tests (DiDm.Tests.cs) and validation tests (DiDm.Validation.Tests.cs)
- Quantower wrappers + tests for all 4 indicators
- PineScript v6 implementations with compensated RMA
- Normalized .md documentation for all indicators and categories
- 182 tests passing, 0 failures
This commit is contained in:
Miha Kralj
2026-03-11 20:21:52 -07:00
parent 56b86bebfb
commit 33d20f2a18
437 changed files with 4589 additions and 2792 deletions
-2
View File
@@ -1,7 +1,5 @@
# Trends (FIR)
> "FIR filters are always stable. The question is how many coefficients you need." Digital Signal Processing folklore
Finite Impulse Response (FIR) trend indicators. These use fixed-length windows with explicit coefficients. No feedback loops, no recursion. Output depends only on current and past inputs. Always stable. Linear phase possible. SIMD-friendly batch computation.
## Indicators
+2 -2
View File
@@ -1,5 +1,7 @@
# ALMA: Arnaud Legoux Moving Average
> *Gaussian distributions govern everything from particle diffusion to the distribution of shoe sizes. Applying them to price action isn't 'technical analysis'; it's just physics with a profit motive.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Gaussian distributions govern everything from particle diffusion to the distribution of shoe sizes. Applying them to price action isn't 'technical analysis'; it's just physics with a profit motive."
ALMA is a Finite Impulse Response (FIR) filter that applies a Gaussian window to price data. Unlike the Simple Moving Average (which treats 10-minute-old data with the same reverence as 1-minute-old data) or the Exponential Moving Average (which holds onto history like a hoarder), ALMA allows you to shape the weight distribution precisely. It lets you define the trade-off between smoothness and lag using standard deviation ($\sigma$) and offset, rather than arbitrary periods.
## Historical Context / The Standard
+2 -2
View File
@@ -1,5 +1,7 @@
# BLMA: Blackman Window Moving Average
> *If you want to filter noise, don't just average it - window it.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "If you want to filter noise, don't just average it - window it."
The Blackman Window Moving Average (BLMA) applies a triple-cosine window function from digital signal processing to financial time series. Originally developed by **Ralph Beebe Blackman** at Bell Labs in the 1950s for spectral analysis, this filter provides superior noise suppression compared to standard moving averages by minimizing spectral leakage.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# BWMA: Bessel-Weighted Moving Average
> *The Bessel function appears in problems involving cylindrical symmetry—heat flow in pipes, vibration of drumheads, and apparently, the smoothing of financial time series. Mathematics doesn't care about your asset class.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The Bessel function appears in problems involving cylindrical symmetry—heat flow in pipes, vibration of drumheads, and apparently, the smoothing of financial time series. Mathematics doesn't care about your asset class."
BWMA is a Finite Impulse Response (FIR) filter that applies a Bessel-derived window function to weight price data. The weighting follows a parabolic (or higher-order polynomial) profile that emphasizes the center of the lookback window while smoothly tapering to zero at the edges. Unlike rectangular (SMA) or exponential (EMA) weighting, BWMA provides a mathematically smooth transition that reduces spectral leakage and Gibbs phenomenon artifacts.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# CONV: Convolution Moving Average
> *If you want a moving average that behaves exactly how you want it to, build it yourself. CONV is the 'Bring Your Own Kernel' of indicators.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -16,8 +18,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "If you want a moving average that behaves exactly how you want it to, build it yourself. CONV is the 'Bring Your Own Kernel' of indicators."
CONV (Convolution Moving Average) is the ultimate tool for the signal processing purist. It doesn't presume to know what kind of smoothing you need; it simply asks for a kernel (a set of weights) and applies it to the data. Want a Gaussian filter? A Sinc filter? A custom edge-detection filter? CONV runs them all.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# CRMA: Cubic Regression Moving Average
> *Linear regression tells you where the trend is going. Quadratic regression tells you it's curving. Cubic regression tells you the curve is changing its mind.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Linear regression tells you where the trend is going. Quadratic regression tells you it's curving. Cubic regression tells you the curve is changing its mind."
CRMA fits a degree-3 polynomial $y = a_0 + a_1 x + a_2 x^2 + a_3 x^3$ to the most recent $N$ bars via ordinary least squares, then returns the fitted endpoint value $a_0$. By capturing inflection and curvature that linear and quadratic models miss, CRMA tracks S-shaped reversals and accelerating trends with measurably lower endpoint error than LSMA or QRMA on non-stationary price series. The cost is a 4x4 linear system solve per bar, which is O(1) once power sums are accumulated in O(N).
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# DWMA: Double Weighted Moving Average
> *If one WMA is good, two must be better. DWMA is for when you want your signal so smooth it looks like it's been sanded, polished, and waxed.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `(period * 2) - 1` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "If one WMA is good, two must be better. DWMA is for when you want your signal so smooth it looks like it's been sanded, polished, and waxed."
DWMA (Double Weighted Moving Average) is exactly what it says on the tin: a Weighted Moving Average of a Weighted Moving Average. Unlike DEMA, which tries to *remove* lag, DWMA accepts lag as the price of admission for superior noise reduction. It produces a curve that is incredibly smooth, ideal for identifying long-term trends without getting faked out by market chop.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# FWMA: Fibonacci Weighted Moving Average
> *Nature uses Fibonacci for sunflower seeds and nautilus shells. Using it for price weighting is either profound biological insight or the most expensive numerology in finance. The math doesn't care which.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Nature uses Fibonacci for sunflower seeds and nautilus shells. Using it for price weighting is either profound biological insight or the most expensive numerology in finance. The math doesn't care which."
The Fibonacci Weighted Moving Average applies the Fibonacci sequence as FIR filter weights, assigning exponentially growing importance to recent bars. Where WMA uses linear weights (1, 2, 3, ..., N) and PWMA uses parabolic weights ($1^2, 2^2, ..., N^2$), FWMA uses F(1), F(2), ..., F(N). The Fibonacci growth rate ($\phi \approx 1.618$) produces a weighting profile between exponential and parabolic, giving FWMA a distinctive "golden ratio decay" that concentrates roughly 61.8% of total weight in the most recent third of the window.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# GWMA: Gaussian-Weighted Moving Average
> *The Gaussian distribution shows up everywhere from thermal noise to the central limit theorem. Using it to weight price data isn't magic; it's just applied statistics with a trading account.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The Gaussian distribution shows up everywhere from thermal noise to the central limit theorem. Using it to weight price data isn't magic; it's just applied statistics with a trading account."
GWMA is a Finite Impulse Response (FIR) filter that applies a centered Gaussian window to price data. Unlike ALMA (which allows shifting the Gaussian peak via an offset parameter), GWMA centers the bell curve at the middle of the lookback window. The sigma parameter controls the width of the Gaussian, determining how sharply the weights decay from the center.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# HAMMA: Hamming-Weighted Moving Average
> *Julius von Hann picked his window function to suppress spectral leakage; we're just using it to smooth price data. Same math, different trading floor.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Julius von Hann picked his window function to suppress spectral leakage; we're just using it to smooth price data. Same math, different trading floor."
HAMMA is a Finite Impulse Response (FIR) filter that applies a Hamming window to price data. The Hamming window is a raised cosine with specific coefficients (0.54 and 0.46) chosen to minimize the amplitude of the first side lobe in the frequency domain. This makes it particularly effective at separating the signal (trend) from nearby noise frequencies.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# HANMA: Hanning-Weighted Moving Average
> *Julius von Hann deserves credit for the window that bears his name—even if autocomplete keeps trying to change it to 'Hamming.' The zero-edge weights aren't a bug; they're the whole point.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Julius von Hann deserves credit for the window that bears his name—even if autocomplete keeps trying to change it to 'Hamming.' The zero-edge weights aren't a bug; they're the whole point."
HANMA is a Finite Impulse Response (FIR) filter that applies a Hanning (Hann) window to price data. The Hanning window is a pure raised cosine with edge weights of exactly zero, which provides excellent side lobe suppression while maintaining a narrower main lobe than Hamming. It's particularly effective when you want to eliminate boundary discontinuities entirely.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# HEND: Henderson Moving Average
> *Robert Henderson designed a filter so good that the Australian Bureau of Statistics still uses it a century later. When your smoothing algorithm outlasts empires, you did something right.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Robert Henderson designed a filter so good that the Australian Bureau of Statistics still uses it a century later. When your smoothing algorithm outlasts empires, you did something right."
HEND is a symmetric FIR filter derived from the Henderson (1916) closed-form weight formula, designed to pass cubic polynomial trends without distortion while maximally suppressing irregular noise. Used as the core smoother in the X-11 and X-13ARIMA-SEATS seasonal adjustment frameworks by statistical agencies worldwide, HEND achieves the theoretically optimal trade-off between smoothness (measured by the sum of squared third differences of the weights) and fidelity for cubic trends. Weights can be negative at the edges, giving the filter a bandpass-like property that sharpens trend-cycle extraction.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# HMA: Hull Moving Average
> *Alan Hull looked at the lag in moving averages and said, 'I can fix that.' And he did, by making the math do gymnastics.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period + sqrtPeriod - 1` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Alan Hull looked at the lag in moving averages and said, 'I can fix that.' And he did, by making the math do gymnastics."
HMA (Hull Moving Average) is a solution to the eternal struggle between smoothness and lag. Most indicators force you to choose one; HMA gives you both. It achieves this by using weighted moving averages (WMAs) in a clever configuration that cancels out lag while maintaining the smoothing properties of the WMA.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# ILRS: Integral of Linear Regression Slope
> *John Ehlers took the slope of a regression line, integrated it, and got a smoother trend follower. Differentiate to find direction, integrate to find position. Calculus: still useful after 300 years.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "John Ehlers took the slope of a regression line, integrated it, and got a smoother trend follower. Differentiate to find direction, integrate to find position. Calculus: still useful after 300 years."
ILRS computes the linear regression slope over a rolling window, then accumulates it via discrete integration (running sum) to reconstruct a smoothed price-level signal. By differentiating (slope extraction) and reintegrating, ILRS acts as a low-pass filter that preserves trend direction while suppressing high-frequency noise more aggressively than LSMA. The integration step introduces a natural momentum quality: the output continues rising even as slope magnitude diminishes, making ILRS particularly effective for trend-following systems that need early exit signals based on slope deceleration.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# KAISER: Kaiser Window Moving Average
> *James Kaiser gave signal processing a knob. Turn beta up, sidelobes go down, transition band widens. Turn it down, you get an SMA. One parameter to rule them all.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "James Kaiser gave signal processing a knob. Turn beta up, sidelobes go down, transition band widens. Turn it down, you get an SMA. One parameter to rule them all."
KAISER applies the Kaiser-Bessel window function as FIR filter weights, providing a single parameter ($\beta$) that continuously controls the trade-off between main lobe width (transition band sharpness) and sidelobe attenuation (stopband rejection). At $\beta = 0$ it degenerates to a rectangular window (SMA); at $\beta \approx 5.65$ it approximates the Blackman window; at $\beta \approx 8.6$ it matches the Hamming window's sidelobe profile. This makes KAISER the most flexible single-parameter window-based moving average, allowing traders to tune frequency selectivity without changing the window length.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# LANCZOS: Lanczos (Sinc) Window Moving Average
> *Cornelius Lanczos used the sinc function to reconstruct band-limited signals from discrete samples. Apply it to price data and you get a moving average that respects the Nyquist limit while your competitors are still using SMAs.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Cornelius Lanczos used the sinc function to reconstruct band-limited signals from discrete samples. Apply it to price data and you get a moving average that respects the Nyquist limit while your competitors are still using SMAs."
LANCZOS applies the normalized sinc function $\text{sinc}(x) = \sin(\pi x)/(\pi x)$ as a symmetric FIR window, producing a moving average with near-ideal low-pass frequency characteristics. The sinc function is the impulse response of the perfect brick-wall low-pass filter; windowing it to finite length trades sharp cutoff for practical realizability. The result is a smoother with minimal Gibbs phenomenon ringing and excellent passband flatness, at the cost of small negative sidelobe weights that can cause minor overshooting on sharp price discontinuities.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# LSMA: Least Squares Moving Average
> *If you want to know where the price is going, draw a line through where it's been. LSMA does this for every single bar, tirelessly fitting linear regressions while you sleep.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "If you want to know where the price is going, draw a line through where it's been. LSMA does this for every single bar, tirelessly fitting linear regressions while you sleep."
LSMA (Least Squares Moving Average), also known as the Moving Linear Regression or Endpoint Moving Average, calculates the least squares regression line for the preceding time periods. In plain English: it finds the "best fit" line for the data window and tells you where that line ends.
## Historical Context
+2 -42
View File
@@ -1,5 +1,7 @@
# NLMA: Non-Lag Moving Average
> *Igorad at TrendLaboratory built a two-phase FIR kernel that uses five times more taps than the period parameter suggests. The extra taps carry negative weights that actively cancel group delay. Most 'non-lag' indicators are marketing. This one is signal processing.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires 1 bar of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Igorad at TrendLaboratory built a two-phase FIR kernel that uses five times more taps than the period parameter suggests. The extra taps carry negative weights that actively cancel group delay. Most 'non-lag' indicators are marketing. This one is signal processing."
NLMA uses a two-phase damped cosine kernel with $5P - 1$ taps (where $P$ is the user period). Phase 1 builds the initial sweep; Phase 2 extends it through multiple cosine cycles. The kernel's negative weights in the mid-section subtract lagged price components, reducing group delay well below what a positive-only SMA of the same length achieves. Normalization by the signed weight sum preserves DC gain of 1.0. The result is a trend-following filter with moderate overshoot but substantially less lag than conventional moving averages.
## Historical Context
@@ -134,46 +134,6 @@ The signed-sum normalization guarantees unit DC gain regardless of the weight di
| Phase | $P - 1$ | derived | Boundary between Phase 1 and Phase 2 |
| Coeff | $3\pi$ | fixed | Gain decay rate in Phase 2 |
### Pseudo-code (streaming)
```text
// Constants
Cycle = 4
Phase = period - 1
Coeff = 3 * PI
flen = 5 * period - 1
// Precompute weights once
wsum = 0
for i = 0 to flen-1:
if i <= Phase - 1:
t = i / (Phase - 1)
else:
t = 1.0 + (i - Phase + 1) * (2*Cycle - 1) / (Cycle * period - 1)
if t <= 0.5:
g = 1.0
else:
g = 1.0 / (Coeff * t + 1)
w[i] = g * cos(PI * t)
wsum += w[i]
// Per bar: insert into circular buffer of size flen
buffer[head] = price
head = (head + 1) % flen
// Warmup: return price when count < flen
if count < flen: return price
// Full convolution
sum = 0
for k = 0 to flen-1:
sum += buffer[(head+k) % flen] * w[flen-1-k]
return sum / wsum
```
## Performance Profile
### Operation Count (Streaming Mode)
+2 -2
View File
@@ -1,5 +1,7 @@
# NYQMA: Nyquist Moving Average
> *Manfred Dürschner applied the Nyquist-Shannon sampling theorem to cascaded moving averages: the second smoothing period must not exceed half the first, or you get aliasing artifacts. Respect the theorem and the ghost signals disappear.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires 1 bar of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Manfred Dürschner applied the Nyquist-Shannon sampling theorem to cascaded moving averages: the second smoothing period must not exceed half the first, or you get aliasing artifacts. Respect the theorem and the ghost signals disappear."
NYQMA combines a primary LWMA (Linear Weighted Moving Average) with a secondary LWMA applied to the first, using lag-compensating extrapolation: $\text{NYQMA} = (1+\alpha) \cdot \text{MA}_1 - \alpha \cdot \text{MA}_2$, where $\alpha = N_2 / (N_1 - N_2)$. The Nyquist constraint $N_2 \leq \lfloor N_1/2 \rfloor$ ensures the second smoothing does not introduce aliasing artifacts into the output. This produces a lag-reduced moving average grounded in sampling theory rather than ad-hoc coefficient tuning. Streaming update is O(1) per bar via composed Wma instances; batch mode uses stackalloc/ArrayPool with FMA in the extrapolation loop.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# PARZEN: Parzen (de la Vallée-Poussin) Window Moving Average
> *Emanuel Parzen convolved two triangular windows and got a piecewise cubic with zero sidelobe discontinuity. When your window function is its own proof of smoothness, the spectral leakage has nowhere to hide.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Emanuel Parzen convolved two triangular windows and got a piecewise cubic with zero sidelobe discontinuity. When your window function is its own proof of smoothness, the spectral leakage has nowhere to hide."
PARZEN applies the Parzen (de la Vallée-Poussin) window function as FIR filter weights, producing a moving average with exceptional sidelobe suppression ($-24$ dB/octave rolloff) and a smooth bell-shaped kernel. The Parzen window is the self-convolution of two triangular (Bartlett) windows at half-length, which guarantees continuous first and second derivatives at all points. This makes it one of the few windows whose frequency response has no discontinuities in its first three derivatives, yielding the fastest sidelobe decay rate among common windows without requiring the computational cost of Bessel functions (Kaiser) or specialized polynomials (Henderson).
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# PMA: Predictive Moving Average
> *John Ehlers looked at WMA's lag and said: 'What if we just extrapolated it away?' The result is a moving average that actually tries to predict where price is going, not where it has been.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `(period * 2) - 1` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "John Ehlers looked at WMA's lag and said: 'What if we just extrapolated it away?' The result is a moving average that actually tries to predict where price is going, not where it has been."
PMA (Predictive Moving Average) is a lag-cancellation filter that uses linear extrapolation of dual WMA (Weighted Moving Average) cascades to predict price direction. It produces two outputs: the PMA line (extrapolated trend) and a Trigger line for crossover signals. Default period is 7 per Ehlers' original specification.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# PWMA: Parabolic Weighted Moving Average
> *Linear weighting is for people who think the world is flat. PWMA squares the weights, because recent data isn't just more important—it's exponentially more important.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Linear weighting is for people who think the world is flat. PWMA squares the weights, because recent data isn't just more important—it's exponentially more important."
PWMA (Parabolic Weighted Moving Average) applies a parabolic ($i^2$) weighting scheme to the data window. This assigns massive importance to the most recent data points while still technically including the older data. It's like a WMA on steroids.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# QRMA: Quadratic Regression Moving Average
> *Linear regression assumes the world is a straight line. Quadratic regression admits it might curve. For parabolic price moves, that admission turns out to be worth 40% less endpoint error.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Linear regression assumes the world is a straight line. Quadratic regression admits it might curve. For parabolic price moves, that admission turns out to be worth 40% less endpoint error."
QRMA fits a second-degree polynomial $y = a + bx + cx^2$ to the most recent $N$ bars via ordinary least squares, then returns the fitted value at the endpoint (newest bar). By capturing curvature that LSMA (degree-1) misses, QRMA provides meaningfully better tracking of accelerating or decelerating price trends. The 3x3 normal-equation system is solved via Cramer's rule in O(1) after an O(N) data accumulation pass, making it computationally efficient and suitable for streaming applications.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# RAIN: Rainbow Moving Average
> *Mel Widner applied SMA ten times recursively, then weighted the layers like a rainbow: brightest at the top, fading toward the base. Ten colors of smoothing, one composite average that sees both fast and slow structure simultaneously.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires 1 bar of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Mel Widner applied SMA ten times recursively, then weighted the layers like a rainbow: brightest at the top, fading toward the base. Ten colors of smoothing, one composite average that sees both fast and slow structure simultaneously."
RAIN recursively applies SMA 10 times, producing 10 layers of progressively smoother price representation, then computes a weighted average across all layers. Layers 1-4 receive weights 5, 4, 3, 2 (emphasizing the more responsive layers), while layers 5-10 each receive weight 1, for a total divisor of 20. This multi-scale composition produces a moving average that responds to short-term price changes through the lightly smoothed upper layers while maintaining stability through the heavily smoothed lower layers.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# RWMA: Range Weighted Moving Average
> *Most averages weight by position: recent bars matter more. RWMA weights by volatility: volatile bars matter more. The market spoke loudest when the range was widest, so listen to those bars.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -16,8 +18,6 @@
- Requires `> period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Most averages weight by position: recent bars matter more. RWMA weights by volatility: volatile bars matter more. The market spoke loudest when the range was widest, so listen to those bars."
RWMA weights each bar's contribution to the average by its price range (high minus low), giving greater influence to volatile bars and less to narrow-range, indecisive bars. The logic: a bar with a large range represents stronger price discovery and carries more informational content than a low-range doji. This produces a moving average that gravitates toward prices established during high-activity periods, naturally incorporating volatility as a relevance signal without requiring a separate volatility indicator.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# SGMA: Savitzky-Golay Moving Average
> *Least-squares polynomial fitting has been solving signal processing problems since 1964. That most traders still use medieval averaging techniques says more about the industry than the math.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Least-squares polynomial fitting has been solving signal processing problems since 1964. That most traders still use medieval averaging techniques says more about the industry than the math."
SGMA is a Finite Impulse Response (FIR) filter that uses polynomial fitting to smooth data while preserving higher moments (peaks, valleys, and inflection points). Unlike the Simple Moving Average (which flattens everything) or the Exponential Moving Average (which introduces phase lag), SGMA uses polynomial weighting to maintain the original signal's shape characteristics.
## Historical Context / The Standard
+2 -2
View File
@@ -1,5 +1,7 @@
# SINEMA: Sine-Weighted Moving Average
> *Nature doesn't do straight lines, and neither should your weights.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Nature doesn't do straight lines, and neither should your weights."
The Sine-Weighted Moving Average (SINEMA) applies sine-wave weighting to data points within the lookback window. Weights follow the formula $w_i = \sin(\pi \cdot (i+1) / N)$, creating a smooth bell-shaped distribution that emphasizes middle values while gracefully tapering at the edges. Unlike SMA's uniform weighting or WMA's linear ramp, sine weighting provides a natural transition that reduces high-frequency noise while preserving mid-frequency trends.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# SMA: Simple Moving Average
> *The vanilla ice cream of technical analysis. Boring, ubiquitous, and the only thing your grandfather and your high-frequency trading bot agree on.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The vanilla ice cream of technical analysis. Boring, ubiquitous, and the only thing your grandfather and your high-frequency trading bot agree on."
The Simple Moving Average (SMA) is the unweighted arithmetic mean of the last $N$ data points. It acts as a low-pass filter, smoothing out high-frequency noise to reveal the underlying trend. While conceptually simple, efficient implementation on modern hardware requires careful attention to memory access patterns and vectorization.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# SP15: Spencer 15-Point Moving Average
> *John Spencer designed 15 weights that zero out quarterly and quintile seasonality from economic data. Eighty years later, statisticians still reach for them when they need a quick seasonal adjustment that does not require the German engineering of X-13ARIMA.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `Period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "John Spencer designed 15 weights that zero out quarterly and quintile seasonality from economic data. Eighty years later, statisticians still reach for them when they need a quick seasonal adjustment that does not require the German engineering of X-13ARIMA."
SP15 is a fixed-coefficient symmetric FIR filter with 15 weights: $[-3, -6, -5, 3, 21, 46, 67, 74, 67, 46, 21, 3, -5, -6, -3]$ divided by 320. The weights were designed by John Spencer to have zero frequency response at periods 4 and 5 (frequencies $2\pi/4$ and $2\pi/5$), making the filter effective at removing quarterly and quintile seasonal components from economic time series. The negative edge weights provide bandpass-like characteristics, and the fixed design requires no parameters beyond the source series.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# SWMA: Symmetric Weighted Moving Average
> *Take the SMA of an SMA and you get a triangular filter. It is the simplest possible smoothing kernel that has zero phase distortion and no frequency-domain discontinuities. Sometimes simple is exactly what you need.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Take the SMA of an SMA and you get a triangular filter. It is the simplest possible smoothing kernel that has zero phase distortion and no frequency-domain discontinuities. Sometimes simple is exactly what you need."
SWMA applies triangular (symmetric) weights that peak at the center of the window and taper linearly to the edges. For period $N$, the weight at position $i$ is $w(i) = (N/2 + 1) - |i - N/2|$, producing a tent-shaped kernel. This is mathematically equivalent to convolving two rectangular windows (SMA of SMA), giving SWMA a frequency response that is the square of the SMA's sinc-like response. The result is smoother than SMA with better sidelobe suppression, at the cost of slightly more lag.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# TRIMA: Triangular Moving Average
> *The weighted blanket of moving averages. It doesn't care where the price is going right now; it cares where the price feels most comfortable.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `p1 + p2 - 1` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The weighted blanket of moving averages. It doesn't care where the price is going right now; it cares where the price feels most comfortable."
The Triangular Moving Average (TRIMA) places the majority of its weight on the middle of the data window, tapering off linearly towards the ends. This creates a triangular weight distribution (hence the name). It is mathematically equivalent to a double-smoothed SMA.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# TSF: Time Series Forecast
> *The best prediction of the future is the trend that's already in motion — extended by exactly one step.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The best prediction of the future is the trend that's already in motion — extended by exactly one step."
TSF projects the least-squares regression line one bar forward, providing a statistically grounded forecast of the next bar's value. Unlike simple moving averages that smooth past data, TSF answers the question: "If the current trend continues, where will price be next?" This makes it inherently leading rather than lagging, though the forecast degrades quickly beyond one step.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# TUKEY_W: Tukey (Tapered Cosine) Window Moving Average
> *John Tukey designed a window with a knob that goes from 'do nothing' to 'full Hann' in one parameter. Set alpha to 0.5 and you get the pragmatist's compromise: flat where it matters, tapered where it would otherwise ring.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "John Tukey designed a window with a knob that goes from 'do nothing' to 'full Hann' in one parameter. Set alpha to 0.5 and you get the pragmatist's compromise: flat where it matters, tapered where it would otherwise ring."
TUKEY_W applies the Tukey (tapered cosine) window as FIR filter weights, offering a single parameter $\alpha$ that controls the fraction of the window that is cosine-tapered. At $\alpha = 0$, the window is rectangular (SMA). At $\alpha = 1$, it becomes the Hann window. The default $\alpha = 0.5$ tapers 25% at each edge while keeping the central 50% flat at unity, combining the passband efficiency of the rectangular window with the sidelobe suppression of cosine tapering. This makes Tukey the default "when in doubt" window in spectral analysis, and by extension, a sensible default for window-based moving averages.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# WMA: Weighted Moving Average
> *Because yesterday matters more than last Tuesday. WMA is the linear answer to the question: 'What have you done for me lately?'*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Trend (FIR MA) |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Because yesterday matters more than last Tuesday. WMA is the linear answer to the question: 'What have you done for me lately?'"
The Weighted Moving Average (WMA) assigns a linearly decreasing weight to data points. The most recent price gets weight $N$, the one before it $N-1$, down to 1. This makes it more responsive to recent price changes than an SMA, but without the infinite tail of an EMA.
## Historical Context