Files
QuanTAlib/lib/channels/decaychannel/decaychannel.md
T

225 lines
8.0 KiB
Markdown
Raw Normal View History

# DECAYCHANNEL: Decay Min-Max Channel
> "Yesterday's high matters less today. Tomorrow, it matters even less. Decay channels know this."
Decay Min-Max Channel (DECAYCHANNEL) tracks the highest high and lowest low like Donchian, then applies exponential decay toward the midpoint. Fresh extremes snap the bands outward; time compresses them inward. The result: channels that respect recent price action while gradually forgetting stale levels. This implementation uses true half-life mathematics—50% convergence over the period length—ensuring predictable decay behavior across all timeframes.
## Historical Context
Traditional Donchian Channels treat all extremes within the lookback window equally. A high from 19 bars ago has the same influence as a high from 1 bar ago. This works for breakout detection but creates artificial support/resistance levels that persist until they mechanically exit the window.
Traders noticed this rigidity. A 20-day high from exactly 20 days ago shouldn't matter as much as one from 5 days ago. Various "adaptive channel" approaches emerged in the 1990s-2000s, but most used arbitrary decay rates or complex volatility weighting.
DECAYCHANNEL takes a simpler approach: pure exponential decay with mathematically defined half-life. The decay constant $\lambda = \ln(2) / \text{period}$ guarantees that bands converge 50% toward the midpoint over exactly one period. After two periods: 75%. After three: 87.5%. No tuning parameters, no volatility lookups—just consistent, predictable decay.
## Architecture & Physics
DECAYCHANNEL consists of four interconnected components that balance extreme tracking with temporal decay.
### 1. Extreme Tracking (Highest/Lowest)
Internal Highest and Lowest indicators maintain the actual max/min over the period:
$$
H_t^{raw} = \max_{i=0}^{n-1}(High_{t-i})
$$
$$
L_t^{raw} = \min_{i=0}^{n-1}(Low_{t-i})
$$
These raw values constrain the decayed bands—the upper band can never exceed the actual highest high, and the lower band can never go below the actual lowest low.
### 2. Decay Timers
Separate counters track how long since each band was reset by a new extreme:
$$
\tau_U = \text{bars since } High_t = H_t^{raw}
$$
$$
\tau_L = \text{bars since } Low_t = L_t^{raw}
$$
When price makes a new extreme, the corresponding timer resets to zero. Otherwise, it increments each bar.
### 3. Exponential Decay Engine
The decay rate uses the half-life formula:
$$
\lambda = \frac{\ln(2)}{\text{period}}
$$
For each bar, compute the decay factor based on elapsed time:
$$
d_U = 1 - e^{-\lambda \cdot \tau_U}
$$
$$
d_L = 1 - e^{-\lambda \cdot \tau_L}
$$
At $\tau = 0$ (new extreme), $d = 0$ (no decay). At $\tau = \text{period}$, $d = 0.5$ (half decayed).
### 4. Midpoint Convergence
Bands decay toward the current midpoint, not toward price:
$$
M_t = \frac{U_{t-1} + L_{t-1}}{2}
$$
$$
U_t = U_{t-1} - d_U \cdot (U_{t-1} - M_t)
$$
$$
L_t = L_{t-1} + d_L \cdot (M_t - L_{t-1})
$$
Finally, constrain to actual extremes:
$$
U_t = \max(U_t, H_t^{raw})
$$
$$
L_t = \min(L_t, L_t^{raw})
$$
## Mathematical Foundation
### Half-Life Derivation
Exponential decay follows:
$$
V(t) = V_0 \cdot e^{-\lambda t}
$$
For half-life $t_{1/2}$ where $V(t_{1/2}) = \frac{V_0}{2}$:
$$
\frac{V_0}{2} = V_0 \cdot e^{-\lambda t_{1/2}}
$$
$$
\lambda = \frac{\ln(2)}{t_{1/2}}
$$
Setting $t_{1/2} = \text{period}$ gives the implementation's decay constant.
### Convergence Schedule
| Elapsed Time | Decay Factor | Remaining Distance |
| :--- | :---: | :---: |
| 0 bars | 0% | 100% |
| period/2 bars | 29.3% | 70.7% |
| period bars | 50% | 50% |
| 2×period bars | 75% | 25% |
| 3×period bars | 87.5% | 12.5% |
### Middle Band Calculation
The output middle band is the average of the decayed upper and lower bands:
$$
Middle_t = \frac{U_t + L_t}{2}
$$
This differs from the convergence midpoint (which uses previous bar's values) to avoid feedback loops.
## Performance Profile
### Operation Count (Streaming Mode, Scalar)
Per-bar cost including internal Highest/Lowest updates:
| Operation | Count | Cost (cycles) | Subtotal |
| :--- | :---: | :---: | :---: |
| ADD/SUB | 8 | 1 | 8 |
| MUL | 4 | 3 | 12 |
| DIV | 1 | 15 | 15 |
| EXP | 2 | 50 | 100 |
| CMP/MAX/MIN | 6 | 1 | 6 |
| **Total** | **21** | — | **~141 cycles** |
**Breakdown:**
- Lambda: precomputed at construction (0 cycles per bar)
- Midpoint: 1 ADD + 1 DIV = 16 cycles
- Decay factors (×2): 2 MUL + 2 EXP + 2 SUB = 106 cycles
- Band updates: 2 MUL + 2 SUB = 8 cycles
- Constraint checks: 4 CMP = 4 cycles
- Internal Highest/Lowest: ~8 cycles (amortized O(1))
**Dominant cost:** EXP operations at 71% of total cycles.
### Batch Mode (512 values, SIMD/FMA)
| Operation | Scalar Ops | SIMD Benefit | Notes |
| :--- | :---: | :---: | :--- |
| Decay calculation | 2 | Limited | Sequential dependency on timers |
| Band update | 4 | 2× via FMA | `band - decay × (band - mid)` |
| Max/Min constraint | 4 | 1× | Comparison-based |
**Batch efficiency (512 bars):**
| Mode | Cycles/bar | Total (512 bars) | Improvement |
| :--- | :---: | :---: | :---: |
| Scalar streaming | 141 | 72,192 | — |
| FMA-optimized | ~135 | ~69,120 | **~4%** |
Limited improvement due to:
1. **EXP dominates**: 100 of 141 cycles are exponential operations (not SIMD-friendly in scalar mode)
2. **Timer dependency**: Each bar's decay factor depends on its timer value
3. **State coupling**: Upper/lower bands depend on previous bar's midpoint
### Quality Metrics
| Metric | Score | Notes |
| :--- | :---: | :--- |
| **Accuracy** | 10/10 | Mathematically exact exponential decay |
| **Timeliness** | 8/10 | Immediate response to new extremes |
| **Overshoot** | 6/10 | New extremes reset decay, can spike bands |
| **Smoothness** | 7/10 | Exponential decay provides smooth convergence between resets |
| **Adaptivity** | 8/10 | Channels naturally tighten during consolidation |
## Validation
| Library | Status | Notes |
| :--- | :---: | :--- |
| **TA-Lib** | N/A | Not implemented |
| **Skender** | N/A | Not implemented |
| **Tulip** | N/A | Not implemented |
| **Ooples** | N/A | Not implemented |
| **Internal** | ✅ | Four-mode consistency verified (streaming, batch, span, event) |
DECAYCHANNEL is a QuanTAlib-specific indicator with no external reference implementations.
## Common Pitfalls
1. **Decay Rate Confusion**: The period parameter controls half-life, not full decay. At period=100, bands are 50% decayed after 100 bars, not fully converged. For near-complete convergence (>95%), allow 4-5× the period.
2. **Constraint Snap-Back**: When the actual highest high drops (because an old extreme exits the Highest window), the upper band can snap downward even mid-decay. This is intentional—decayed bands never exceed actual extremes.
3. **Initialization Period**: DECAYCHANNEL needs `period` bars to establish meaningful extremes before decay becomes relevant. IsHot reflects this warmup requirement.
4. **Timer State Management**: Using `isNew=false` for bar correction requires restoring both the band values and the decay timers. The implementation handles this via state snapshots, but improper use corrupts both.
5. **Midpoint Targeting**: Bands decay toward the channel midpoint, not toward current price. In strong trends, this means the trailing band decays toward a point that may be far from price, creating asymmetric behavior.
6. **Memory Overhead**: Each instance maintains two Highest/Lowest indicators plus decay state. For period=100, budget ~1.6 KB per instance for the internal monotonic deques plus ~64 bytes for state.
7. **Exponential Sensitivity**: Small period values create aggressive decay. At period=10, bands are 50% converged after just 10 bars. For most applications, period≥50 provides more stable channels.
## References
- Murphy, J. J. (1999). *Technical Analysis of the Financial Markets*. New York Institute of Finance.
- Kaufman, P. J. (2013). *Trading Systems and Methods* (5th ed.). John Wiley & Sons.
- Press, W. H., et al. (2007). *Numerical Recipes: The Art of Scientific Computing* (3rd ed.). Cambridge University Press. [Exponential decay mathematics]