- MAMA: replace atan2+angle-wrapping with Ehlers/TA-Lib's atan(Q/I) signed-delta discriminator for both phase and period calculations. Was diverging from TA-Lib/Skender by up to 11%; now matches within 0.01 absolute tolerance. - NATR: fix TA-Lib validation test dividing ATR by a close price ~14 bars misaligned (TA-Lib's output array is offset-compact, not absolute-indexed). Now passes at 1e-9 instead of masking the bug with a 0.10 tolerance. - ValidationHelper: tighten default tolerances to match AGENTS.md (1e-9 for Skender/TALib/Tulip, 1e-6 for Ooples, was 1e-7 uniformly). Added documented per-test tolerance overrides where large-window/large-magnitude sums (WMA/HMA/TRIMA/DWMA period=100, rolling StdDev/Variance, AD cumulative sum, linear regression) genuinely exceed 1e-9 due to floating-point accumulation order, not algorithmic divergence. - ROC/ROCP/ROCR: old Roc (Price-Price[N]) was an exact duplicate of Mom; removed. Old Rocp (100*(P-P[N])/P[N]) was actually TA-Lib's ROC formula; renamed to Roc. New Rocp created with TA-Lib's real ROCP formula ((P-P[N])/P[N], no *100). Updated C#, Quantower, Python bindings, and pandas-ta parity tests accordingly. - Added Validation.Tests.cs for 12 previously-unvalidated indicators: Sarext (TA-Lib SarExt), Minindex/Maxindex (TA-Lib MinIndex/MaxIndex, exact match), Convexity (Skender GetBeta BetaType.All), Vwmacd (Vwma+Ema composition), and independent formula re-derivations for Usi, Eeo, Net, Pta, Amfm, Hwc (no external library implements these Ehlers indicators). Lpf validated structurally (documented invariants) given its 5-stage adaptive algorithm. - Updated docs/validation.md, Roc.md/Rocp.md/Mom.md/Mama.md accordingly.
6.2 KiB
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 |
| Inputs | Source (close) |
| Parameters | period (default 10) |
| Outputs | Single series (Mom) |
| Output range | Varies (see docs) |
| Warmup | period + 1 bars |
| PineScript | mom.pine |
- MOM (Momentum) calculates the absolute price difference between the current value and the value N periods ago.
- Similar: ROC, ROCP, Vel | Complementary: Moving average for smoothing | Trading note: Raw momentum: Price(t) − Price(t−n). Simplest momentum measure.
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
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. Maps directly to TA-Lib's MOM function; see ROC for the percentage form and ROCP for the decimal-fraction form.
Historical Context
Momentum is arguably the oldest quantitative concept in technical analysis. Before oscillators, before moving averages, traders measured "how much has price changed" by simple subtraction. The term appears in Gerald Appel's work on MACD (1979) and in Martin Pring's "Technical Analysis Explained" as a foundation concept.
Different libraries handle the naming inconsistently:
- TA-Lib / Tulip:
MOM= absolute change (this calculation);ROC= percentage;ROCP= decimal fraction - TradingView / PineScript:
ta.mom= absolute change - QuanTAlib:
Mom= absolute change (matches TA-LibMOM),Roc= percentage (matches TA-LibROC),Rocp= decimal fraction (matches TA-LibROCP)
The implementation uses a ring buffer of size period + 1 for O(1) streaming with zero allocations on the hot path.
Architecture & Physics
1. Ring Buffer Storage
The indicator maintains a sliding window of period + 1 values:
\text{buffer} = [v_{t-n}, v_{t-n+1}, \ldots, v_{t-1}, v_t]
where n is the lookback period. Only the oldest and newest values participate in the calculation.
2. Absolute Change Calculation
\text{MOM}_t = v_t - v_{t-n}
The result is in the same units as the input (dollars, points, ticks). No normalization is applied.
3. State Management
The indicator uses record struct State with _state / _p_state pairs for bar correction:
if isNew:
_p_state = _state // snapshot for rollback
else:
_state = _p_state // restore on correction
NaN/Infinity inputs are sanitized via last-valid-value substitution stored in State.LastValid.
Mathematical Foundation
Core Formula
\text{MOM}_t = P_t - P_{t-n}
where:
P_t= current priceP_{t-n}= price fromnperiods ago- Default
n = 10
Relationship to Other Momentum Variants
| Indicator | Formula | Output |
|---|---|---|
| MOM | P_t - P_{t-n} |
Absolute (price units) |
| ROC | \frac{P_t - P_{t-n}}{P_{t-n}} \times 100 |
Percentage (%) |
| ROCP | \frac{P_t - P_{t-n}}{P_{t-n}} |
Decimal fraction |
| ROCR | \frac{P_t}{P_{t-n}} |
Ratio (dimensionless) |
Conversions
\text{ROC} = \text{ROCP} \times 100 = \frac{\text{MOM}}{P_{t-n}} \times 100
\text{ROCR} = \frac{P_t}{P_{t-n}} = \frac{\text{MOM}}{P_{t-n}} + 1
Performance Profile
Operation Count (Streaming Mode)
| Operation | Count | Notes |
|---|---|---|
| SUB | 1 | current - past |
| Buffer add | 1 | O(1) ring buffer |
| State copy | 1 | rollback support |
| Total | ~3 ops | Extremely lightweight |
Batch Mode (Span-based)
| Operation | Complexity | Notes |
|---|---|---|
| Per-element | O(1) | Single subtraction |
| Total | O(n) | Linear scan |
| Memory | O(1) | No additional allocation |
Quality Metrics
| Metric | Score | Notes |
|---|---|---|
| Accuracy | 10/10 | Exact arithmetic, no approximation |
| Timeliness | 10/10 | Zero lag by definition |
| Smoothness | 3/10 | No smoothing, reflects raw volatility |
| Simplicity | 10/10 | Single subtraction |
Validation
| Library | Status | Notes |
|---|---|---|
| Skender | ✅ | Matches exactly |
| TA-Lib | ✅ | MOM function matches |
| Tulip | ✅ | MOM matches exactly |
| Ooples | ✅ | Matches within tolerance |
Common Pitfalls
-
Unit confusion: MOM returns absolute values in price units, not percentages. A MOM of 5 means price moved 5 dollars/points, not 5%.
-
Scale dependency: MOM values are not comparable across instruments with different price levels. Use ROC or ROCP for normalized comparisons.
-
Warmup period: The first
periodvalues return 0.0 because there is no historical reference point yet.IsHotbecomes true afterperiod + 1bars. -
Zero handling: Unlike percentage-based variants, MOM has no division-by-zero risk.
-
Sign interpretation: Positive MOM indicates price increase over the lookback window; negative indicates decrease. The magnitude indicates the size of the move.
-
MOM vs ROC naming: In QuanTAlib,
Mom(absolute change, matches TA-LibMOM) andRoc(percentage, matches TA-LibROC) are distinct indicators computing different formulas — do not assume they are interchangeable.
References
- Pring, M. J. (2014). "Technical Analysis Explained." McGraw-Hill.
- Murphy, J. J. (1999). "Technical Analysis of the Financial Markets." New York Institute of Finance.
- Appel, G. (2005). "Technical Analysis: Power Tools for Active Investors." FT Press.
- TA-Lib documentation: MOM function reference
- TradingView PineScript Reference: ta.mom