Add new moving average implementations: LTMA, MCNMA, NLMA, NMA, NYQMA, RAIN, and TRAMA

- LTMA (Linear Trend Moving Average): Introduces a predictive moving average using dual cascaded EMAs for trend estimation.
- MCNMA (McNicholl EMA): Implements a zero-lag TEMA using a cascaded EMA structure for enhanced responsiveness.
- NLMA (Non-Lag Moving Average): Utilizes a damped cosine kernel to achieve reduced lag in moving averages.
- NMA (Natural Moving Average): Adapts smoothing based on volatility profiles using a square-root kernel.
- NYQMA (Nyquist Moving Average): Applies the Nyquist-Shannon theorem to prevent aliasing in cascaded moving averages.
- RAIN (Rainbow Moving Average): Combines multiple SMA layers with weighted averages for multi-scale smoothing.
- TRAMA (Trend Regularity Adaptive Moving Average): Adapts smoothing based on the frequency of new highs and lows in price data.
This commit is contained in:
Miha Kralj
2026-02-20 21:40:32 -08:00
parent cbeefc9d64
commit 90d5638008
121 changed files with 9595 additions and 6315 deletions
+89 -76
View File
@@ -1,112 +1,125 @@
# Vortex Indicator
# VORTEX: Vortex Indicator
> When bulls and bears clash, the Vortex measures the violence. Two opposing forces, one decisive signal.
> "When bulls and bears clash, the Vortex measures the violence."
The Vortex Indicator captures the directional momentum of price movement by measuring positive and negative trend movements relative to true range. Unlike directional indicators that rely on smoothing, Vortex uses pure ratio analysis over a rolling period, making it responsive yet stable.
The Vortex Indicator measures upward and downward trend momentum by computing the ratio of positive and negative vortex movements to true range over a rolling window. VI+ captures the distance from current high to previous low (upward force); VI- captures the distance from current low to previous high (downward force). Both are normalized by summed true range, producing two lines that oscillate around 1.0. Crossovers signal trend changes. The implementation uses three ring buffers with running sums for O(1) streaming updates.
## Historical Context
Etienne Botes and Douglas Siepman introduced the Vortex Indicator in a 2010 article for *Technical Analysis of Stocks & Commodities*. Inspired by the natural vortex patterns in water flow and the work of Viktor Schauberger, they designed a dual-line indicator that captures the essence of trend direction through geometric relationships between consecutive bars.
Etienne Botes and Douglas Siepman introduced the Vortex Indicator in a January 2010 article for *Technical Analysis of Stocks and Commodities*. Inspired by Viktor Schauberger's observations of natural vortex patterns in water flow, they designed a dual-line indicator that captures directional momentum through geometric relationships between consecutive bars. The indicator is conceptually related to Wilder's Directional Movement (DM) system but uses a simpler construction: raw absolute distances rather than conditional directional selection. This makes Vortex more responsive to sharp reversals but more susceptible to gap noise. The typical period range is 14-21 bars, with 14 being the most common default.
## Architecture & Physics
The Vortex Indicator is built on a simple geometric insight: in a strong uptrend, the current high tends to be far from the previous low. In a strong downtrend, the current low tends to be far from the previous high.
### 1. Vortex Movement
1. **Vortex Movement (VM)**: Measures directional distance.
* **VM+**: Distance from current high to previous low (upward force).
* **VM-**: Distance from current low to previous high (downward force).
Positive vortex movement measures the "reach" of bullish activity:
2. **True Range (TR)**: The denominator that normalizes the movements.
$$VM^+_t = |H_t - L_{t-1}|$$
3. **Vortex Index**: The ratio of summed VM to summed TR over $N$ periods.
Negative vortex movement measures the "reach" of bearish activity:
### The Physics of Trend
$$VM^-_t = |L_t - H_{t-1}|$$
* **VI+ > VI-**: Bullish momentum dominates. The market is reaching up.
* **VI- > VI+**: Bearish momentum dominates. The market is reaching down.
* **VI+ ≈ VI-**: Equilibrium. No clear trend; potential consolidation or reversal.
* **Crossover**: When VI+ crosses VI-, a trend change is signaled.
In a strong uptrend, the current high is far from the previous low ($VM^+$ large). In a strong downtrend, the current low is far from the previous high ($VM^-$ large).
### 2. True Range Normalization
$$TR_t = \max(H_t - L_t,\ |H_t - C_{t-1}|,\ |L_t - C_{t-1}|)$$
True range serves as the denominator that normalizes vortex movements to the prevailing volatility regime.
### 3. Vortex Indicators
$$VI^+_t = \frac{\sum_{i=1}^{N} VM^+_{t-i+1}}{\sum_{i=1}^{N} TR_{t-i+1}}$$
$$VI^-_t = \frac{\sum_{i=1}^{N} VM^-_{t-i+1}}{\sum_{i=1}^{N} TR_{t-i+1}}$$
The summation window creates period-based smoothing without introducing the lag of recursive (IIR) filters.
### 4. Running Sum Implementation
Three ring buffers store $VM^+$, $VM^-$, and $TR$ values. Running sums update incrementally:
```
sum_vm_plus += new_vm_plus - oldest_vm_plus
sum_vm_minus += new_vm_minus - oldest_vm_minus
sum_tr += new_tr - oldest_tr
```
This yields O(1) per-bar updates after the initial warmup fill.
### 5. Complexity
| Metric | Value |
|:-------|:------|
| Time | O(1) per bar (running sum updates) |
| Space | O(N) (three ring buffers of size N) |
| Warmup | N bars |
| Allocations | Zero in hot path |
## Mathematical Foundation
The calculations are straightforward geometric relationships.
### Parameters
### Vortex Movement
| Parameter | Type | Default | Constraint | Description |
|:----------|:-----|:--------|:-----------|:------------|
| period | int | 14 | > 0 | Rolling window for VM and TR sums |
$$ VM^+ = |High_t - Low_{t-1}| $$
### Pseudo-code
$$ VM^- = |Low_t - High_{t-1}| $$
```
VORTEX(bar, period=14):
### True Range
// Vortex movements (require previous bar)
vm_plus = abs(bar.High - prev_bar.Low)
vm_minus = abs(bar.Low - prev_bar.High)
$$ TR = \max(High_t - Low_t, |High_t - Close_{t-1}|, |Low_t - Close_{t-1}|) $$
// True range
tr = max(bar.High - bar.Low,
abs(bar.High - prev_bar.Close),
abs(bar.Low - prev_bar.Close))
### Vortex Indicator
// Ring buffer updates with running sums
if buffer_full:
sum_vm_plus -= vm_plus_buffer.oldest
sum_vm_minus -= vm_minus_buffer.oldest
sum_tr -= tr_buffer.oldest
$$ VI^+ = \frac{\sum_{i=1}^{N} VM^+_i}{\sum_{i=1}^{N} TR_i} $$
vm_plus_buffer.add(vm_plus)
vm_minus_buffer.add(vm_minus)
tr_buffer.add(tr)
$$ VI^- = \frac{\sum_{i=1}^{N} VM^-_i}{\sum_{i=1}^{N} TR_i} $$
sum_vm_plus += vm_plus
sum_vm_minus += vm_minus
sum_tr += tr
## Performance Profile
// Vortex indicators
if sum_tr > 0:
vi_plus = sum_vm_plus / sum_tr
vi_minus = sum_vm_minus / sum_tr
else:
vi_plus = 0
vi_minus = 0
The implementation uses running sums for O(1) updates after the initial warmup period.
return (vi_plus, vi_minus)
```
### Zero-Allocation Design
Three circular buffers maintain the VM+, VM-, and TR values. Running sums are updated incrementally:
- Add new value
- Subtract oldest value when buffer is full
- Compute ratio
| Metric | Score | Notes |
| :--- | :--- | :--- |
| **Throughput** | 8ns | 8ns / bar after warmup. |
| **Allocations** | 0 | Hot path is allocation-free. |
| **Complexity** | O(1) | Constant time updates with running sums. |
| **Accuracy** | 10/10 | Matches Skender reference implementation. |
| **Timeliness** | 9/10 | Responsive to trend changes. |
| **Overshoot** | 3/10 | Values typically 0.5-1.5, rarely extreme. |
| **Smoothness** | 7/10 | Period-based smoothing via summation. |
## Interpretation
### Crossover Signals
* **Bullish Crossover**: VI+ crosses above VI-. Indicates potential uptrend beginning.
* **Bearish Crossover**: VI- crosses above VI+. Indicates potential downtrend beginning.
### Reference Line
### Reference Line at 1.0
The value 1.0 serves as a natural reference:
- **VI+ > 1**: Strong upward pressure exceeds average true range.
- **VI- > 1**: Strong downward pressure exceeds average true range.
- **Both < 1**: Subdued market activity.
### Threshold Strategy
- $VI^+ > 1$: Upward reach exceeds average true range (strong bullish pressure)
- $VI^- > 1$: Downward reach exceeds average true range (strong bearish pressure)
- Both < 1: Subdued directional activity
Some practitioners use thresholds for confirmation:
- **Strong Trend**: VI+ > 1.1 and VI+ > VI- (bullish) or VI- > 1.1 and VI- > VI+ (bearish).
- **Weak/No Trend**: Both VI+ and VI- below 0.9 or very close to each other.
### Crossover Signal
## Validation
$$\text{Bullish} = VI^+ > VI^- \quad (\text{and } VI^+_{\text{prev}} \leq VI^-_{\text{prev}})$$
Validation is performed against industry-standard libraries.
$$\text{Bearish} = VI^- > VI^+ \quad (\text{and } VI^-_{\text{prev}} \leq VI^+_{\text{prev}})$$
| Library | Status | Notes |
| :--- | :--- | :--- |
| **QuanTAlib** | ✅ | Validated. |
| **Skender** | ✅ | Matches `GetVortex` (Pvi, Nvi). |
| **TA-Lib** | N/A | Not implemented in TA-Lib. |
| **Tulip** | N/A | Not implemented in Tulip. |
Period selection: too short (< 7) creates noise; too long (> 28) introduces excessive lag. The 14-21 range balances responsiveness and stability.
### Common Pitfalls
## Resources
* **Period Selection**: Too short a period (< 7) creates noise; too long (> 28) creates excessive lag. 14-21 is typical.
* **False Crossovers**: In choppy markets, VI+ and VI- oscillate around each other, creating whipsaws. Use with trend filters.
* **Single Line Trading**: Don't use VI+ or VI- in isolation. The relationship between them is the signal.
* **Ignoring True Range**: Low TR periods (consolidation) can cause extreme VI values. Always consider the market context.
## References
* Botes, E., & Siepman, D. (2010). "The Vortex Indicator." *Technical Analysis of Stocks & Commodities*, January 2010.
* Wikipedia: [Vortex Indicator](https://en.wikipedia.org/wiki/Vortex_indicator)
- Botes, E. & Siepman, D. (2010). "The Vortex Indicator." *Technical Analysis of Stocks and Commodities*, January 2010.