feat: Enhance volume indicators with ADOSC and SSF implementation and validation

This commit is contained in:
Miha Kralj
2025-12-20 15:08:07 -08:00
parent 5549c7329a
commit d21fea3c18
85 changed files with 5144 additions and 3954 deletions
+34 -107
View File
@@ -1,130 +1,57 @@
# TEMA: Triple Exponential Moving Average
## What It Does
> "Patrick Mulloy looked at the lag of an EMA and took it personally. TEMA is what happens when you apply algebra to impatience."
The Triple Exponential Moving Average (TEMA) is a technical indicator designed to smooth price data while virtually eliminating the lag associated with traditional moving averages. By combining a single, double, and triple Exponential Moving Average (EMA), TEMA creates a composite line that tracks price action with remarkable speed and accuracy.
The Triple Exponential Moving Average (TEMA) is a lag-reducing filter that combines a single, double, and triple EMA. Unlike a simple triple smoothing (which would be incredibly slow), TEMA uses a weighted combination of the three to cancel out the lag, resulting in an indicator that hugs price action tighter than a spandex cycling short.
## Historical Context
Developed by Patrick Mulloy and introduced in his 1994 article "Smoothing Data with Faster Moving Averages" in *Technical Analysis of Stocks & Commodities*, TEMA was created alongside DEMA (Double EMA) to solve the persistent problem of lag in trend-following indicators. Mulloy's innovation was to use the lag inherent in multiple EMA calculations to estimate and subtract the total lag from the original signal.
Introduced by Patrick Mulloy in *Technical Analysis of Stocks & Commodities* (Jan 1994), "Smoothing Data With Less Lag." Mulloy's goal was to replace the standard moving averages in MACD and other indicators to reduce the delay in signal generation.
## How It Works
## Architecture & Physics
### The Core Idea
TEMA is not just "EMA applied three times." That would be $EMA(EMA(EMA(x)))$. TEMA is a composite:
$$ TEMA = 3 \cdot EMA_1 - 3 \cdot EMA_2 + EMA_3 $$
TEMA is not just "an EMA of an EMA of an EMA" (which would be very slow). Instead, it uses a clever formula to cancel out lag:
This formula effectively projects the trend forward to compensate for the delay inherent in smoothing.
- $EMA_1$ has some lag.
- $EMA_2$ (EMA of EMA) has roughly double the lag.
- $EMA_3$ (EMA of EMA of EMA) has roughly triple the lag.
### Convergence Speed
By combining these terms with specific weights ($3 \times EMA_1 - 3 \times EMA_2 + EMA_3$), the lag terms cancel out, leaving a moving average that hugs the price closely.
Because of the aggressive weighting, TEMA converges (warms up) faster than a standard EMA. While an EMA takes $\approx 3.45(N+1)$ steps to converge to 99.9%, TEMA stabilizes quicker due to the subtraction terms canceling out the initial error.
### Mathematical Foundation
## Mathematical Foundation
### 1. The Cascade
$$ EMA_1 = EMA(Price) $$
$$ EMA_2 = EMA(EMA_1) $$
$$ EMA_3 = EMA(EMA_2) $$
### 2. The Combination
$$ TEMA = (3 \times EMA_1) - (3 \times EMA_2) + EMA_3 $$
Where:
- $EMA_1 = EMA(Price)$
- $EMA_2 = EMA(EMA_1)$
- $EMA_3 = EMA(EMA_2)$
### Implementation Details
Our implementation uses three internal EMA instances.
- **Complexity:** O(1) per update.
- **Initialization:** We use Hunter's method for initializing the underlying EMAs to ensure the TEMA starts with valid values as early as possible.
## Configuration
| Parameter | Default | Purpose | Adjustment Guidelines |
|-----------|---------|---------|----------------------|
| Period | 14 | Lookback window | Short (5-10) for scalping; Medium (20-50) for swing trading. |
## Performance Profile
| Operation | Complexity | Description |
|-----------|------------|-------------------|
| Streaming update | O(1) | 3 EMA updates + scalar math |
| Bar correction | O(1) | Efficient state rollback |
| Batch processing | O(N) | Single pass through data |
| Memory footprint | O(1) | Stores state for 3 internal EMAs |
### Zero-Allocation Design
## Interpretation
QuanTAlib's `Tema` implementation does not create three separate `Ema` objects. Instead, it maintains three lightweight `EmaState` structs within the main class. This ensures zero heap allocations during updates and keeps the memory footprint minimal.
### Trading Signals
| Metric | Score | Notes |
| :--- | :--- | :--- |
| **Throughput** | High | 3 EMAs |
| **Complexity** | O(1) | Constant time update |
| **Accuracy** | 8/10 | Extremely responsive to turns |
| **Timeliness** | 9/10 | Near-zero lag (Lag ≈ 0) |
| **Overshoot** | 4/10 | Significant overshoot on reversals |
| **Smoothness** | 7/10 | Smoother than DEMA, less than T3 |
#### Trend Direction
## Validation
- **Fast Response:** TEMA turns much faster than SMA or EMA. A turn in TEMA often precedes a turn in price trend.
Validated against TA-Lib (`TA_TEMA`) and Skender.Stock.Indicators.
#### Crossovers
### Common Pitfalls
- **Price Crossover:** Because TEMA hugs price so closely, crossovers are frequent. They are best used for short-term entries in the direction of a larger trend.
### When It Works Best
- **Momentum Trading:** TEMA is excellent for capturing short-term bursts of momentum.
### When It Struggles
- **Overshoot:** In a sudden V-shaped reversal, TEMA can "overshoot" the price briefly due to the momentum of its internal calculation components.
## Architecture Notes
This implementation makes specific trade-offs:
### Choice: Composition
- **Implementation:** Composed of 3 `Ema` objects.
- **Rationale:** Reusing the robust `Ema` class ensures consistent behavior (like initialization and NaN handling) across the library.
## References
- Mulloy, Patrick G. "Smoothing Data with Faster Moving Averages." *Technical Analysis of Stocks & Commodities*, Jan 1994.
## C# Usage
### Streaming Updates (Single Instance)
```csharp
using QuanTAlib;
var tema = new Tema(period: 14);
// Process each new bar
TValue result = tema.Update(new TValue(timestamp, closePrice));
Console.WriteLine($"TEMA: {result.Value:F2}");
// Check if buffer is full
if (tema.IsHot)
{
// Indicator is fully initialized
}
```
### Batch Processing (Historical Data)
```csharp
// TSeries API
TSeries prices = ...;
TSeries temaValues = Tema.Batch(prices, period: 14);
// Span API (High Performance)
double[] prices = new double[1000];
double[] output = new double[1000];
Tema.Calculate(prices.AsSpan(), output.AsSpan(), period: 14);
```
### Bar Correction (isNew Parameter)
```csharp
var tema = new Tema(14);
// New bar
tema.Update(new TValue(time, 100), isNew: true);
// Intra-bar update
tema.Update(new TValue(time, 101), isNew: false); // Replaces 100 with 101
1. **Overshoot**: TEMA is so responsive it can overshoot price turns, creating a "whiplash" effect in volatile markets.
2. **Noise**: By reducing lag, TEMA sacrifices some noise suppression. It is "nervous" compared to an SMA.
3. **Identity Crisis**: Often confused with T3 (Tillson). T3 is a generalized version; TEMA is specifically T3 with $v=1$.