KAMA (Kaufman's Adaptive Moving Average) is an intelligent moving average that adjusts its smoothing speed based on market noise. When the price is moving steadily (high signal-to-noise ratio), KAMA speeds up to capture the trend. When the price is chopping sideways (low signal-to-noise ratio), KAMA slows down to filter out the noise.
## Historical Context
Perry Kaufman introduced KAMA in his book *Smarter Trading* (1998). It was one of the first widely adopted adaptive indicators, solving the problem of "whipsaws" in sideways markets without sacrificing responsiveness in trends.
## Architecture & Physics
KAMA uses an **Efficiency Ratio (ER)** to drive the smoothing constant of an EMA.
1.**Efficiency Ratio (ER)**: Measures the fractal efficiency of price movement.
* $ER = \frac{\text{Net Change}}{\text{Sum of Absolute Changes}}$
* ER approaches 1.0 in a straight line trend.
* ER approaches 0.0 in pure noise.
2.**Smoothing Constant (SC)**: Scales between a "Fast" EMA (e.g., 2-period) and a "Slow" EMA (e.g., 30-period) based on ER.
## Mathematical Foundation
$$ ER = \frac{|P_t - P_{t-n}|}{\sum_{i=0}^{n-1} |P_{t-i} - P_{t-i-1}|} $$
During warmup, only accumulates `diff_in` without removal.
### Batch Mode (SIMD Analysis)
KAMA is an IIR filter with adaptive alpha — not vectorizable across bars due to recursive state dependency. The sliding-window volatility sum uses O(1) incremental updates rather than O(n) window scans.
| Optimization | Benefit |
| :--- | :--- |
| FMA instructions | Saves ~2 cycles per bar |
| Incremental volatility | O(1) vs O(period) per bar |
| stackalloc buffer | Zero heap allocation for period ≤256 |
### Quality Metrics
| Metric | Score | Notes |
| :--- | :---: | :--- |
| **Accuracy** | 7/10 | Flattens in noise, tracks in trends |
KAMA uses a **RingBuffer** for the sliding price window:
```csharp
privatereadonlyRingBuffer_buffer;// period + 1 values
```
The buffer stores `period + 1` values to calculate the net change (`Price[0] - Price[period]`) while maintaining incremental volatility updates. Buffer indexing uses `[^1]` for newest, `[0]` for oldest, enabling O(1) change calculation.
### State Management
State uses a record struct with `LayoutKind.Auto`:
| `VolatilitySum` | 8 bytes | Running sum of |ΔP| |
| `NextDiffOut` | 8 bytes | Pre-staged diff for next removal |
| `LastValidValue` | 8 bytes | NaN substitution fallback |
| **Total** | **32 bytes** | Compact state for rollback |
The `NextDiffOut` field enables O(1) volatility updates by pre-calculating `|buffer[0] - buffer[1]|` — the value that will exit the window on the next bar.
### FMA Optimization
Two FMA operations replace traditional arithmetic in the hot path:
The epsilon guard (1e-10) prevents division by zero in flat markets, while the ER cap handles numerical precision issues where accumulated volatility might slightly undercount actual change.
| **Per-instance** | **~168 bytes** | For period=10 |
### Common Pitfalls
1.**Flatlining**: In very choppy markets, KAMA can become almost horizontal. This is a feature, not a bug—it's telling you to stay out.
2.**Parameters**: The standard settings are (10, 2, 30). 10 is the ER period, 2 is the fast EMA, 30 is the slow EMA. Tweaking the ER period changes the sensitivity to noise.