Files
QuanTAlib/lib/channels/decaychannel/decaychannel.md
T
Miha Kralj 3eae9a76fe Add Standard Deviation Channel (SDCHANNEL) implementation and documentation
- Implemented Sdchannel class for calculating standard deviation channels based on linear regression.
- Added detailed documentation for SDCHANNEL, including overview, calculation methods, and interpretation.
- Updated project files to include new numerics library components in Channels and Volatility projects.
2026-01-21 14:41:31 -05:00

8.0 KiB
Raw Blame 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]