Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: aider (openrouter/anthropic/claude-sonnet-4) <aider@aider.chat> Co-authored-by: Warp <agent@warp.dev>
4.0 KiB
T3: Tillson T3 Moving Average
"If one EMA is good, six must be better. Tim Tillson's logic is impeccable, provided you hate noise more than you love latency."
The T3 Moving Average is a hyper-smooth, low-lag filter that cascades six Exponential Moving Averages (EMAs). Unlike standard cascading (which increases lag), T3 uses a "Volume Factor" (v) to weight the EMAs in a way that partially cancels out the lag, resulting in a curve that is smoother than an EMA but more responsive than an SMA.
Historical Context
Introduced by Tim Tillson in Technical Analysis of Stocks & Commodities (Jan 1998), "Smoothing Techniques for More Accurate Signals." Tillson sought to improve upon the DEMA (Double EMA) and TEMA (Triple EMA) concepts by generalizing the lag-reduction mathematics.
Architecture & Physics
T3 is essentially a filter of filters. It passes data through a chain of 6 EMAs:
Input \to EMA_1 \to EMA_2 \to EMA_3 \to EMA_4 \to EMA_5 \to EMA_6
It then combines these outputs using coefficients derived from the Volume Factor (v).
The Volume Factor (v)
- $v = 0$: T3 becomes a standard EMA (actually, a triple EMA of EMAs).
- $v = 1$: T3 behaves like DEMA/TEMA with aggressive lag reduction (and potential overshoot).
- $v = 0.7$: The default. A "Goldilocks" zone of smoothness and responsiveness.
Mathematical Foundation
1. Coefficients
Given v (default 0.7):
c_1 = -v^3
c_2 = 3v^2 + 3v^3
c_3 = -6v^2 - 3v - 3v^3
c_4 = 1 + 3v + 3v^2 + v^3
2. The Formula
(Note: There are multiple variations of T3. QuanTAlib uses the standard Tillson formula).
T3 = c_1 e_6 + c_2 e_5 + c_3 e_4 + c_4 e_3
Where e_n is the output of the $n$-th EMA in the cascade.
Performance Profile
Operation Count (Streaming Mode)
T3 requires 6 cascaded EMA updates plus the weighted combination:
| Operation | Count | Cost (cycles) | Subtotal |
|---|---|---|---|
| EMA update (×6) | 6 | 7 | 42 |
| MUL (c1×e6, c2×e5, c3×e4, c4×e3) | 4 | 3 | 12 |
| ADD (combination) | 3 | 1 | 3 |
| Total (hot) | 13 | — | ~57 cycles |
During warmup, each EMA stage has additional compensator overhead (~21 cycles × 6 = ~126 cycles).
Total during warmup: ~183 cycles/bar; Post-warmup: ~57 cycles/bar.
Batch Mode (SIMD Analysis)
T3 is inherently recursive due to 6 cascaded EMAs. SIMD parallelization across bars is not possible:
| Optimization | Operations | Cycles Saved |
|---|---|---|
| FMA in each EMA stage | 6 FMA vs 6×(MUL+ADD) | ~12 cycles |
| FMA in coefficient combination | 4 FMA ops | ~8 cycles |
Per-bar efficiency: ~57 cycles is 8× EMA cost, reflecting 6 EMA stages + 4-term combiner.
Quality Metrics
| Metric | Score | Notes |
|---|---|---|
| Accuracy | 10/10 | Matches TA-Lib exactly |
| Timeliness | 9/10 | Very low lag due to volume factor cancellation |
| Overshoot | 6/10 | Can overshoot significantly if v > 1 |
| Smoothness | 10/10 | Extremely smooth due to 6-pole filtering |
Benchmark Results
| Metric | Value | Notes |
|---|---|---|
| Throughput | ~12 ns/bar | 6× EMA overhead |
| Allocations | 0 bytes | Zero-allocation in hot paths |
| Complexity | O(1) | Constant time regardless of period |
| State Size | 192 bytes | Six EMA states (32 bytes each) |
Validation
| Library | Status | Notes |
|---|---|---|
| TA-Lib | ✅ | Matches TA_T3 exactly. |
| Skender | ✅ | Matches GetT3 exactly. |
| Tulip | N/A | Not implemented. |
| Ooples | ✅ | Matches CalculateTillsonT3MovingAverage. |
Common Pitfalls
- Warmup: Because it cascades 6 EMAs, T3 takes significantly longer to stabilize than a standard EMA. A T3(10) might need 60+ bars to converge.
- Overshoot: With high
vvalues (>1), T3 can overshoot price turns, creating false breakout signals. - Complexity: It is computationally heavier than SMA or EMA (approx 6x ops), though still negligible on modern CPUs.