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 @@
# Numerics
> "Price is raw signal. Transform exposes hidden structure. Derivative reveals momentum. Normalization enables comparison."
Basic mathematical transforms and utility functions for time series. These building blocks convert raw price data into forms suitable for analysis, comparison, and downstream indicator consumption.
| Indicator | Full Name | Description |
+2 -2
View File
@@ -1,5 +1,7 @@
# ACCEL: Second Derivative (Acceleration)
> *Velocity tells you where you're going. Acceleration tells you if you're getting there faster or slower.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -16,8 +18,6 @@
- Requires `3` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Velocity tells you where you're going. Acceleration tells you if you're getting there faster or slower."
ACCEL measures the rate of change of velocity—the acceleration of a time series. As the second derivative, it reveals momentum shifts before they manifest in price direction. Positive acceleration means velocity is increasing (trend strengthening); negative means velocity is decreasing (trend weakening). This O(1) streaming implementation uses FMA optimization and SIMD batch processing.
## Historical Context
+2
View File
@@ -1,5 +1,7 @@
# BETADIST: Beta Distribution CDF
> *The Beta distribution CDF maps values onto a flexible probability curve defined by two shape parameters — versatile enough to model any bounded outcome.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2
View File
@@ -1,5 +1,7 @@
# BINOMDIST: Binomial Distribution CDF
> *Binomial distribution CDF counts the probability of success in fixed trials — discrete probability at its most fundamental.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2 -2
View File
@@ -1,5 +1,7 @@
# CHANGE: Relative Price Change
> *The simplest measure of movement is often the most powerful.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -16,8 +18,6 @@
- Requires `period + 1` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The simplest measure of movement is often the most powerful."
CHANGE calculates the percentage change between the current value and a value N periods ago. This fundamental indicator forms the basis for momentum analysis, rate of change calculations, and relative performance comparisons.
## Mathematical Foundation
+2
View File
@@ -1,5 +1,7 @@
# CWT: Continuous Wavelet Transform
> *The continuous wavelet transform decomposes a signal across scale and time simultaneously — frequency analysis with temporal precision.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2 -2
View File
@@ -1,5 +1,7 @@
# DECAY: Linear Decay
> *A ratchet that only moves down slowly: price can push it up instantly, but gravity pulls it back at a steady, linear pace.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numerics |
@@ -16,8 +18,6 @@
- Requires `1` bar of warmup before first valid output (IsHot = true).
- Validated against Tulip Indicators `ti_decay` reference algorithm.
> "A ratchet that only moves down slowly: price can push it up instantly, but gravity pulls it back at a steady, linear pace."
DECAY implements the Tulip Indicators `ti_decay` function. When price is above the decayed level, output snaps to price. When price falls below, the output decays linearly at a rate of `1/period` per bar, creating a ceiling that gradually descends. This produces a one-sided envelope that hugs price from above.
## Historical Context
+2
View File
@@ -1,5 +1,7 @@
# DWT: Discrete Wavelet Transform
> *The discrete wavelet transform splits a signal into approximation and detail at each scale — multiresolution analysis in action.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2 -2
View File
@@ -1,5 +1,7 @@
# EDECAY: Exponential Decay
> *A ratchet that only moves down gradually: price can push it up instantly, but gravity pulls it back at an exponential pace — faster when far from zero, slower as it approaches.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numerics |
@@ -16,8 +18,6 @@
- Requires `1` bar of warmup before first valid output (IsHot = true).
- Validated against Tulip Indicators `ti_edecay` reference algorithm.
> "A ratchet that only moves down gradually: price can push it up instantly, but gravity pulls it back at an exponential pace — faster when far from zero, slower as it approaches."
EDECAY implements the exponential decaying function. When price is above the decayed level, output snaps to price. When price falls below, the output decays exponentially by multiplying by `(period-1)/period` per bar, creating a ceiling that gradually descends. Unlike linear DECAY which subtracts a fixed amount, EDECAY's multiplicative factor produces a proportional decay rate.
## Historical Context
+2
View File
@@ -1,5 +1,7 @@
# EXPDIST: Exponential Distribution CDF
> *The exponential distribution models the time between events — memoryless waiting distilled into a single rate parameter.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2 -2
View File
@@ -1,5 +1,7 @@
# EXPTRANS: Exponential Function
> *The exponential function is the only function that is its own derivative—a mathematical curiosity that makes it indispensable for modeling growth, decay, and everything compounding.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -16,8 +18,6 @@
- Requires `0` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The exponential function is the only function that is its own derivative—a mathematical curiosity that makes it indispensable for modeling growth, decay, and everything compounding."
The Exponential (EXP) transformer applies the natural exponential function $e^x$ to each value in a time series. As the inverse of the natural logarithm, it converts additive relationships back to multiplicative ones, making it essential for reconstructing price levels from log-returns and implementing models that assume log-normal distributions.
## Mathematical Foundation
+2
View File
@@ -1,5 +1,7 @@
# FDIST: F-Distribution CDF
> *The F-distribution CDF tests variance ratios — a cornerstone of hypothesis testing built from two chi-squared variables.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2
View File
@@ -1,5 +1,7 @@
# FFT: Fast Fourier Transform (Dominant Cycle Detector)
> *The FFT decomposes price into its constituent frequencies, revealing how much of each cycle lives inside the data.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2
View File
@@ -1,5 +1,7 @@
# GAMMADIST: Gamma Distribution CDF
> *The Gamma distribution generalizes the exponential, modeling the sum of waiting times with a shape that bends to fit.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2 -2
View File
@@ -1,5 +1,7 @@
# HIGHEST: Rolling Maximum
> *What's the peak? The answer to that question defines support, resistance, and breakout levels.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -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.
> "What's the peak? The answer to that question defines support, resistance, and breakout levels."
HIGHEST calculates the maximum value over a rolling lookback window. This O(1) amortized streaming implementation uses a monotonic deque algorithm, enabling real-time updates without re-scanning the entire window. Validated against TA-Lib MAX and Tulip max functions.
## Historical Context
+2
View File
@@ -1,5 +1,7 @@
# IFFT: Inverse Fast Fourier Transform (Spectral Low-Pass Filter)
> *Inverse FFT reconstructs a time series from selected frequency components — a spectral scalpel for noise removal.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2 -2
View File
@@ -1,5 +1,7 @@
# JERK: Third Derivative
> *Acceleration tells you the trend is changing. Jerk tells you that change is itself changing—the earliest possible warning.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -16,8 +18,6 @@
- Requires `4` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Acceleration tells you the trend is changing. Jerk tells you that change is itself changing—the earliest possible warning."
JERK measures the rate of change of acceleration—called "jerk" in physics. As the third derivative, it detects changes in momentum dynamics before they appear in acceleration, velocity, or price. A positive jerk means acceleration is increasing; negative means acceleration is decreasing. This O(1) streaming implementation uses dual FMA optimization and SIMD batch processing for four-point calculations.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# LINEARTRANS: Linear Scaling Transformer
> *The simplest transformations are often the most powerful—linear scaling is the mathematical equivalent of adjusting the volume and tuning the dial.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -16,8 +18,6 @@
- Requires `0` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The simplest transformations are often the most powerful—linear scaling is the mathematical equivalent of adjusting the volume and tuning the dial."
The Linear transformer applies an affine transformation $y = \text{slope} \cdot x + \text{intercept}$ to each value in a time series. This fundamental operation enables scaling, offsetting, unit conversion, and normalization—the building blocks for preparing data for analysis or combining signals from different sources.
## Mathematical Foundation
+2
View File
@@ -1,5 +1,7 @@
# LOGNORMDIST: Log-Normal Distribution CDF
> *The log-normal CDF models variables whose logarithm is normal — the natural distribution of prices and multiplicative processes.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2 -2
View File
@@ -1,5 +1,7 @@
# LOGTRANS: Natural Logarithm Transformer
> *The logarithm is one of the most useful mathematical functions, turning multiplicative relationships into additive ones—a property that makes many financial calculations tractable.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -16,8 +18,6 @@
- Requires `0` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The logarithm is one of the most useful mathematical functions, turning multiplicative relationships into additive ones—a property that makes many financial calculations tractable."
The LOG transformer applies the natural logarithm function $\ln(x)$ to input values. This point-wise transformation compresses large values and expands small ones, making it essential for analyzing multiplicative processes like compounded returns.
## Mathematical Foundation
+2 -2
View File
@@ -1,5 +1,7 @@
# LOWEST: Rolling Minimum
> *Know your floor. Support levels are just historical minimums waiting to be tested.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -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.
> "Know your floor. Support levels are just historical minimums waiting to be tested."
LOWEST calculates the minimum value over a rolling lookback window. This O(1) amortized streaming implementation uses a monotonic deque algorithm, enabling real-time updates without re-scanning the entire window. Validated against TA-Lib MIN and Tulip min functions.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# MAXINDEX: Rolling Maximum Index
> *It's not just about the peak — it's about *when* the peak occurred.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Cross-validation: `source[Maxindex.Batch[i]] == Highest.Batch[i]` for all bars after warmup.
> "It's not just about the peak — it's about *when* the peak occurred."
MAXINDEX identifies the position of the maximum value within a rolling window. While HIGHEST tells you the peak *value*, MAXINDEX tells you *where* that peak is relative to the current bar. This is essential for pattern recognition, timing analysis, and detecting how "stale" a high is.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# MININDEX: Rolling Minimum Index
> *Finding support isn't just about the price — it's about *when* the floor was set.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -17,8 +19,6 @@
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Cross-validation: `source[Minindex.Batch[i]] == Lowest.Batch[i]` for all bars after warmup.
> "Finding support isn't just about the price — it's about *when* the floor was set."
MININDEX identifies the position of the minimum value within a rolling window. While LOWEST tells you the trough *value*, MININDEX tells you *where* that trough is relative to the current bar. This is essential for support analysis, timing studies, and detecting how "stale" a low is.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# NORMALIZE: Min-Max Normalization
> *Normalization is the art of making apples and oranges comparable—by insisting that everything lives on the same scale from 0 to 1.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -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.
> "Normalization is the art of making apples and oranges comparable—by insisting that everything lives on the same scale from 0 to 1."
The Normalize transformer applies min-max scaling to map any value series into the bounded range [0, 1] based on the observed minimum and maximum within a rolling lookback window. This technique is fundamental for feature scaling, creating bounded oscillators, and comparing series with different magnitudes.
## Mathematical Foundation
+2
View File
@@ -1,5 +1,7 @@
# NORMDIST: Normal Distribution CDF
> *The normal distribution CDF is the bell curve's integral — the universal reference for probabilistic reasoning.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2
View File
@@ -1,5 +1,7 @@
# POISSONDIST: Poisson Distribution CDF
> *Poisson distribution CDF counts rare events in fixed intervals — the mathematics of arrivals, defaults, and surprises.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2 -2
View File
@@ -1,5 +1,7 @@
# RELU: Rectified Linear Unit
> *The simplest non-linearity that works—ReLU's computational efficiency and gradient-friendly properties made deep learning practical.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -16,8 +18,6 @@
- Requires `0` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The simplest non-linearity that works—ReLU's computational efficiency and gradient-friendly properties made deep learning practical."
The Rectified Linear Unit (ReLU) activation function applies `max(0, x)` to each value, passing positive inputs unchanged while zeroing negative ones. Its simplicity belies its importance: ReLU enabled the training of deep neural networks by mitigating vanishing gradients, and its computational efficiency makes it the default activation for most architectures.
## Mathematical Foundation
+2 -2
View File
@@ -1,5 +1,7 @@
# SIGMOID: Logistic Function
> *The sigmoid function is the S-curve that turns messy reality into neat probabilities—a mathematical diplomat that insists every answer must be between 0 and 1.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -16,8 +18,6 @@
- Requires `0` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The sigmoid function is the S-curve that turns messy reality into neat probabilities—a mathematical diplomat that insists every answer must be between 0 and 1."
The Sigmoid (Logistic) transformer maps any real-valued input to the bounded range (0, 1) using the standard logistic function. Its characteristic S-shaped curve makes it indispensable for probability estimation, neural network activations, and any scenario requiring bounded outputs from unbounded inputs.
## Mathematical Foundation
+2 -2
View File
@@ -1,5 +1,7 @@
# SLOPE: First Derivative (Velocity)
> *The simplest measure of change reveals the most: is it going up, or going down?*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -16,8 +18,6 @@
- Requires `2` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The simplest measure of change reveals the most: is it going up, or going down?"
SLOPE measures the instantaneous rate of change—the velocity of a time series. As the first derivative, it answers the fundamental question: how fast is the value changing right now? A positive slope means ascending; negative means descending; zero means flat. This O(1) streaming implementation uses SIMD optimization for batch calculations and handles bar corrections via state rollback.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# SQRTTRANS: Square Root Transform
> *The square root is nature's variance-stabilizing trick—halving the exponent space while preserving monotonicity. When price volatility scales with level, sqrt compresses the noise.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
@@ -16,8 +18,6 @@
- Requires `0` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The square root is nature's variance-stabilizing trick—halving the exponent space while preserving monotonicity. When price volatility scales with level, sqrt compresses the noise."
The Square Root (SQRT) transformer applies $\sqrt{x}$ to each value in a time series. This variance-stabilizing transformation compresses ranges where volatility scales with magnitude, making it useful for heteroscedastic data where standard deviation increases with price level.
## Mathematical Foundation
+2
View File
@@ -1,5 +1,7 @@
# TDIST: Student's t-Distribution CDF
> *Student's t-distribution CDF handles small samples with heavier tails than the normal — uncertainty acknowledged in the shape itself.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |
+2
View File
@@ -1,5 +1,7 @@
# WEIBULLDIST: Weibull Distribution CDF
> *The Weibull distribution models failure rates that change over time — a flexible tool for reliability and survival analysis.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Numeric |