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 @@
# Momentum
> "Momentum tells you how fast price is moving. Whether that movement has meaning: entirely different question." Unknown
Momentum indicators measure the velocity and acceleration of price changes. Unlike trend indicators (which answer "where is price going?"), momentum indicators answer "how fast?" and "is it slowing down?". This distinction matters: a strong trend can have weakening momentum (divergence), and a ranging market can show momentum spikes (false breakouts).
## Indicators
+2 -2
View File
@@ -1,5 +1,7 @@
# ASI: Accumulation Swing Index
> *Price tells us what is happening. The Accumulation Swing Index tells us whether to believe it.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -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.
> "Price tells us what is happening. The Accumulation Swing Index tells us whether to believe it." — J. Welles Wilder Jr.
The Accumulation Swing Index is Wilder's method for separating genuine breakouts from whipsaw noise. Each bar computes a Swing Index value by comparing current OHLC prices to the previous bar, scaled by a user-supplied limit move parameter T. The cumulative sum of these SI values — the ASI — forms a "phantom" price line whose peaks and troughs can be compared directly to the price chart. A trendline break on ASI that accompanies a trendline break on price is confirmed; a price break without ASI confirmation is a probable false move. Introduced in Wilder's 1978 book, it predates most modern oscillators by a decade.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# BIAS: Price Deviation from Moving Average (also known as Disparity Index)
> *When traders ask 'how overbought is it?', they're really asking how far price has strayed from its anchor. Bias answers that question in percentage terms, telling you whether the current price is 5% above or 10% below its moving average. It's the market's stretch marks made visible.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -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.
> "When traders ask 'how overbought is it?', they're really asking how far price has strayed from its anchor. Bias answers that question in percentage terms, telling you whether the current price is 5% above or 10% below its moving average. It's the market's stretch marks made visible."
The Bias indicator measures the percentage difference between the current price and its Simple Moving Average (SMA). A positive bias indicates price is above the average (potentially overbought), while negative bias suggests price is below average (potentially oversold). This is one of the simplest yet most effective tools for identifying mean-reversion opportunities.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# BOP: Balance of Power
> *The market is a tug of war between buyers and sellers. BOP tells you who's pulling harder.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -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 market is a tug of war between buyers and sellers. BOP tells you who's pulling harder."
The Balance of Power measures buying versus selling pressure by comparing the body (Close minus Open) to the range (High minus Low). Created by Igor Livshin in 2001, this ratio oscillates between -1 and +1, providing instantaneous momentum readings with zero lag. A stateless indicator: each bar evaluated independently, no memory of previous values required.
## Historical Context
+2
View File
@@ -1,5 +1,7 @@
# CCI - Commodity Channel Index
> *CCI measures how far price deviates from its statistical mean, scaled by mean absolute deviation — a z-score with character.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
+2 -2
View File
@@ -1,5 +1,7 @@
# CFB: Jurik Composite Fractal Behavior
> *Mark Jurik's CFB is not a momentum indicator. It is a stopwatch for chaos.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -16,8 +18,6 @@
- Requires `maxLen` bars (192 default) of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Mark Jurik's CFB is not a momentum indicator. It is a stopwatch for chaos."
The Composite Fractal Behavior index measures trend duration by analyzing fractal efficiency across 96 simultaneous lookback periods (2 to 192 bars by default). Rather than asking "how strong is the trend," CFB asks "how long has the market been moving efficiently." The answer: a single integer representing the dominant trending timeframe. Use CFB to dynamically tune other indicators: instead of RSI(14), use RSI(CFB).
## Historical Context
+2
View File
@@ -1,5 +1,7 @@
# CMO (Chande Momentum Oscillator)
> *Chande's momentum oscillator compares the sum of gains to the sum of losses, yielding a symmetric measure of directional force.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
+2 -2
View File
@@ -1,5 +1,7 @@
# MACD: Moving Average Convergence Divergence
> *The trend is your friend, until it bends.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -16,8 +18,6 @@
- Requires `Max(fast, slow) + signal - 2` bars (33 default) of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The trend is your friend, until it bends." — Ed Seykota
The Moving Average Convergence Divergence measures momentum through the relationship between two exponential moving averages. Created by Gerald Appel in 1979, the indicator transforms price into a bounded oscillator that reveals trend strength, direction, and potential reversals. Standard parameters (12, 26, 9) detect monthly and biweekly cycles: the 26-period represents roughly one trading month, the 12-period half that duration.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# MOM: Momentum (Absolute Price Change)
> *The market's simplest question answered: how much has price moved in N bars? No ratios, no percentages. Just the raw delta.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -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 market's simplest question answered: how much has price moved in N bars? No ratios, no percentages. Just the raw delta."
MOM (Momentum) calculates the absolute price difference between the current value and the value N periods ago. It is the purest expression of directional price movement, returning a signed value in the same units as the input. Positive MOM indicates rising prices; negative indicates falling. This is functionally identical to ROC but with a configurable lookback period (default 10 vs ROC's convention), and maps directly to TA-Lib's `MOM` function.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# PMO: Price Momentum Oscillator
> *Double-smooth the rate of change and you get something that actually tells you where momentum is headed, not where it was five bars ago.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -16,8 +18,6 @@
- Requires `timePeriods + smoothPeriods` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Double-smooth the rate of change and you get something that actually tells you where momentum is headed, not where it was five bars ago."
PMO (Price Momentum Oscillator), developed by Carl Swenlin at DecisionPoint, is a double-smoothed 1-bar rate of change. It applies two custom EMA passes to a percentage ROC, producing a momentum oscillator that is smoother than raw ROC yet more responsive than triple-smoothed alternatives like TRIX. The custom EMA uses $\alpha = 2/N$ rather than the standard $2/(N+1)$, and seeds with the SMA of the first N values. PMO oscillates around zero: positive values indicate upward momentum, negative values indicate downward momentum.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# PPO: Percentage Price Oscillator
> *MACD told you the spread in dollars. PPO tells you the spread in percent. One of those actually works across instruments.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -16,8 +18,6 @@
- Requires `slowPeriod + signalPeriod` bars (35 default) of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "MACD told you the spread in dollars. PPO tells you the spread in percent. One of those actually works across instruments."
PPO (Percentage Price Oscillator) measures the percentage difference between a fast EMA and a slow EMA. It is functionally equivalent to MACD normalized by the slow EMA, producing values that are comparable across instruments with different price levels. The implementation outputs three components: the PPO line, a signal line (EMA of PPO), and a histogram (PPO minus Signal).
## Historical Context
+2
View File
@@ -1,5 +1,7 @@
# PRS: Price Relative Strength
> *Price relative strength ratios two instruments, revealing which one leads and which one lags in the race.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
+2 -2
View File
@@ -1,5 +1,7 @@
# ROC: Rate of Change (Absolute)
> *The simplest momentum measure: how far has price moved? Not percentage, not ratio - just the raw difference.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -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 momentum measure: how far has price moved? Not percentage, not ratio - just the raw difference."
ROC (Rate of Change) calculates the absolute price difference between the current value and the value N periods ago. This is the most basic form of momentum measurement, returning the raw price change in the same units as the input data. Unlike ROCP (percentage) or ROCR (ratio), ROC preserves the original scale, making it directly interpretable in dollar/point terms.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# ROCP: Rate of Change Percentage
> *The percentage form of momentum: by what percent has price changed? The most intuitive momentum measure.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -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 percentage form of momentum: by what percent has price changed? The most intuitive momentum measure."
ROCP (Rate of Change Percentage) calculates the percentage change between the current value and the value N periods ago. This is the most commonly used form of rate of change, expressing change in percentage terms that are directly interpretable (e.g., 5.0 = 5% increase).
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# ROCR: Rate of Change Ratio
> *The ratio form of momentum: how many times larger is the current price compared to the past? A multiplier view of market movement.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -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 ratio form of momentum: how many times larger is the current price compared to the past? A multiplier view of market movement."
ROCR (Rate of Change Ratio) calculates the ratio between the current value and the value N periods ago. Values hover around 1.0, with values above 1.0 indicating price increase and values below 1.0 indicating price decrease. Unlike ROC (absolute) or ROCP (percentage), ROCR provides a dimensionless multiplier that directly shows the price ratio.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# RSI: Relative Strength Index
> *Momentum is the premier anomaly.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -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.
> "Momentum is the premier anomaly." — Clifford Asness, AQR Capital (who actually said it, and meant it)
The Relative Strength Index measures the speed and magnitude of price changes. Introduced by J. Welles Wilder Jr. in 1978, it oscillates between 0 and 100, identifying overbought and oversold conditions. The "Relative Strength" name is misleading: RSI measures internal strength (price versus itself) not relative strength (asset versus benchmark). Wilder knew this. He kept the name anyway. Marketing, perhaps.
## Historical Context
+2 -2
View File
@@ -1,5 +1,7 @@
# RSX: Relative Strength Xtra (Jurik RSX)
> *RSX is to RSI what a Tesla is to a horse-drawn carriage: same basic concept, vastly superior engineering.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -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.
> "RSX is to RSI what a Tesla is to a horse-drawn carriage: same basic concept, vastly superior engineering."
Mark Jurik's RSX represents the pinnacle of bounded momentum oscillator design. Standard RSI suffers from a fundamental paradox: raw RSI produces jagged noise triggering false signals at overbought/oversold boundaries, but smoothing introduces unacceptable lag that delays turning points. RSX solves this through cascaded IIR filter topology that eliminates high-frequency noise while preserving linear phase response. The result: output so smooth it resembles a sine wave, yet turns precisely at market extrema with zero effective lag.
## Historical Context
+2
View File
@@ -1,5 +1,7 @@
# SAM: Smoothed Adaptive Momentum
> *Smoothed adaptive momentum adjusts its sensitivity to volatility, amplifying signals in trending regimes and dampening them in noise.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
+2
View File
@@ -1,5 +1,7 @@
# TSI: True Strength Index
> *True Strength Index double-smooths momentum, filtering out noise while preserving the directional signal in price change.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
+2 -2
View File
@@ -1,5 +1,7 @@
# VEL: Jurik Velocity
> *Momentum is easy. Smooth momentum without lag is hard. Jurik Velocity is the answer.*
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Momentum |
@@ -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.
> "Momentum is easy. Smooth momentum without lag is hard. Jurik Velocity is the answer."
Jurik Velocity (VEL) measures price rate-of-change through the differential between two weighted moving averages with distinct inertia profiles. Standard momentum ($P_t - P_{t-n}$) amplifies noise: single outlier bars create false signals. VEL exploits the different convergence speeds of Parabolic Weighted Moving Average (PWMA) and linear Weighted Moving Average (WMA) to isolate clean velocity information. The quadratic weighting of PWMA responds faster than linear WMA; their difference captures acceleration without bar-to-bar noise.
## Historical Context