- 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.
8.7 KiB
KCHANNEL: Keltner Channel
"Chester Keltner understood that volatility defines opportunity—his channel shows where price should travel, not just where it has been."
Keltner Channel wraps an Exponential Moving Average (EMA) with bands based on Average True Range (ATR). The middle band tracks trend direction via EMA smoothing; the upper and lower bands expand and contract with market volatility. Unlike Bollinger Bands that use standard deviation (sensitive to outliers), Keltner uses ATR—a volatility measure designed specifically for price movement that includes gaps.
Historical Context
Chester W. Keltner introduced the original Keltner Channel in his 1960 book "How to Make Money in Commodities." His version used a 10-period Simple Moving Average of the "typical price" (HLC/3) with bands at the 10-period average range.
Linda Bradford Raschke modernized the formula in the 1980s, replacing SMA with EMA for smoother trend following and swapping average range for Average True Range to properly account for gaps. Most modern implementations—including this one—follow Raschke's formulation with a 20-period EMA and 2× ATR width.
The PineScript reference algorithm adds warmup compensation: instead of the traditional EMA formula that converges slowly from the first value, it tracks cumulative weighted sums to produce accurate values even during warmup. This implementation replicates that approach for both EMA and ATR (via RMA/Wilder smoothing).
Architecture & Physics
Keltner Channel consists of three interdependent components: the EMA middle band, the ATR volatility measure, and the upper/lower bands.
1. Exponential Moving Average (Middle Band)
The middle band uses EMA with warmup compensation:
\alpha = \frac{2}{\text{period} + 1}
S_t = S_{t-1} \cdot (1 - \alpha) + P_t \cdot \alpha
W_t = W_{t-1} \cdot (1 - \alpha) + \alpha
\text{EMA}_t = \frac{S_t}{W_t}
where S is the cumulative weighted sum, W is the cumulative weight, and P is the close price. The division by W_t compensates for the geometric decay during warmup, producing accurate values from the first bar rather than requiring period bars to converge.
2. True Range
True Range captures the full price movement including gaps:
\text{TR}_t = \max\begin{cases}
H_t - L_t \\
|H_t - C_{t-1}| \\
|L_t - C_{t-1}|
\end{cases}
where H is high, L is low, and C is close. The first bar uses H_0 - L_0 (no previous close available).
3. Average True Range (via RMA)
ATR uses Wilder's RMA smoothing with warmup compensation:
\beta = \frac{1}{\text{period}}
\text{RawRMA}_t = \text{RawRMA}_{t-1} \cdot (1 - \beta) + \text{TR}_t \cdot \beta
E_t = E_{t-1} \cdot (1 - \beta)
\text{ATR}_t = \frac{\text{RawRMA}_t}{1 - E_t}
where E is the exponential decay factor that converges to 0 as the series progresses. The division compensates for warmup bias.
4. Upper and Lower Bands
Bands are placed symmetrically around the EMA:
U_t = \text{EMA}_t + \text{mult} \cdot \text{ATR}_t
L_t = \text{EMA}_t - \text{mult} \cdot \text{ATR}_t
where mult is typically 2.0. The bands expand during volatile periods and contract during consolidation.
Mathematical Foundation
EMA Warmup Compensation
Traditional EMA initializes with the first price and decays toward the true average:
\text{EMA}_t = \alpha \cdot P_t + (1 - \alpha) \cdot \text{EMA}_{t-1}
This produces biased early values. The warmup-compensated version tracks:
S_t = \sum_{i=0}^{t} P_i \cdot \alpha \cdot (1-\alpha)^{t-i}
W_t = \sum_{i=0}^{t} \alpha \cdot (1-\alpha)^{t-i} = 1 - (1-\alpha)^{t+1}
Dividing S_t / W_t normalizes by the actual accumulated weight rather than assuming unit weight.
RMA (Wilder's Smoothing)
RMA uses \alpha = 1/\text{period} compared to EMA's \alpha = 2/(\text{period}+1):
| Period | EMA α | RMA α |
|---|---|---|
| 10 | 0.1818 | 0.10 |
| 14 | 0.1333 | 0.0714 |
| 20 | 0.0952 | 0.05 |
RMA is slower/smoother than EMA for the same period. An RMA(14) roughly matches an EMA(27) in smoothness.
Band Width Interpretation
The ATR multiplier determines how many "volatility units" away the bands sit:
| Multiplier | Band Width | Usage |
|---|---|---|
| 1.0 | 1 ATR | Tight—frequent touches, aggressive trading |
| 2.0 | 2 ATR | Standard—balanced signal frequency |
| 3.0 | 3 ATR | Wide—rare touches, conservative entry |
Price spending extended time outside the bands indicates strong trend momentum (continuation) or potential exhaustion (reversal), depending on context.
Performance Profile
Operation Count (Streaming Mode, Scalar)
Per-bar cost for full Keltner Channel calculation:
| Operation | Count | Cost (cycles) | Subtotal |
|---|---|---|---|
| ADD/SUB | 8 | 1 | 8 |
| MUL | 6 | 3 | 18 |
| DIV | 2 | 15 | 30 |
| MAX | 1 | 2 | 2 |
| ABS | 2 | 1 | 2 |
| FMA | 2 | 4 | 8 |
| Total | 21 | — | ~68 cycles |
Dominant cost: Division operations (44% of total) for warmup compensation in both EMA and ATR.
Batch Mode (512 values, SIMD/FMA)
Both EMA and RMA are recursive filters with sequential dependencies. SIMD applies only to independent operations:
| Operation | Scalar Ops | SIMD Ops (AVX2) | Speedup |
|---|---|---|---|
| True Range (max/abs) | 5 | 1 | 5× |
| Band calculation (add/mul) | 4 | 1 | 4× |
| EMA recursion | 4 | 4 | 1× |
| ATR recursion | 4 | 4 | 1× |
Per-bar savings with FMA:
| Optimization | Cycles Saved | New Total |
|---|---|---|
| EMA FMA (α×P + decay×S) | 2 | 66 |
| RMA FMA (β×TR + decay×RMA) | 2 | 64 |
| Total FMA savings | ~4 cycles | ~64 cycles |
Batch efficiency (512 bars):
| Mode | Cycles/bar | Total (512 bars) | Improvement |
|---|---|---|---|
| Scalar streaming | 68 | 34,816 | — |
| FMA streaming | 64 | 32,768 | 6% |
Limited improvement due to IIR recursion dependencies.
Quality Metrics
| Metric | Score | Notes |
|---|---|---|
| Accuracy | 9/10 | Warmup compensation provides early accuracy |
| Timeliness | 7/10 | EMA responds faster than SMA; still lags trend changes |
| Overshoot | 8/10 | ATR is stable; minimal overshoot vs std dev bands |
| Smoothness | 8/10 | EMA + RMA produce smooth, continuous bands |
Validation
| Library | Status | Notes |
|---|---|---|
| TA-Lib | N/A | No Keltner implementation |
| Skender | ✅ | Structural match; minor divergence during warmup |
| Tulip | N/A | No Keltner implementation |
| Ooples | ❔ | Implementation exists; not fully validated |
| PineScript | ✅ | Reference implementation match |
Skender's implementation uses a different warmup approach (SMA seeding for initial values), causing 2-4% divergence during the first ~period bars. After warmup, values converge within floating-point tolerance.
Common Pitfalls
-
Warmup Period: Keltner requires
period × 2bars beforeIsHotbecomes true. The ATR component needs its own warmup on top of the EMA warmup. Using the indicator before full warmup produces less accurate values (though warmup compensation minimizes this). -
ATR vs. Standard Deviation: Keltner uses ATR (absolute range including gaps); Bollinger uses standard deviation (statistical dispersion). They're not interchangeable—ATR is more stable for gap-heavy instruments like futures or weekend-gapping equities.
-
RMA vs. EMA for ATR: True ATR uses Wilder's RMA smoothing (
\alpha = 1/\text{period}), not EMA (\alpha = 2/(\text{period}+1)). Using EMA for ATR produces faster-reacting but less smooth bands. -
Multiplier Sensitivity: The default multiplier of 2.0 places bands at ±2 ATR. Changing to 1.5 or 3.0 dramatically alters signal frequency. Backtest your multiplier choice—don't assume the default is optimal.
-
Gap Handling: ATR explicitly handles gaps via true range. On gap-up, TR includes
|H_t - C_{t-1}|, expanding the channel. This is intentional—gaps represent volatility that SMA-based channels ignore. -
Memory Footprint: The implementation stores minimal state—just the running sums/weights for EMA and ATR. Approximately 64 bytes per instance. For 5,000 symbols, budget ~320 KB.
-
Bar Correction (isNew=false): When correcting the current bar, the indicator restores the previous state and recalculates. State consists of 6 scalar values—efficient to copy and restore.
References
- Keltner, C. W. (1960). How to Make Money in Commodities. The Keltner Statistical Service.
- Raschke, L. B. (1995). "Keltner Channel." Technical Analysis of Stocks & Commodities.
- Wilder, J. W. (1978). New Concepts in Technical Trading Systems. Trend Research.
- TradingView. (2024). "Keltner Channels." Pine Script Reference Manual.