> "Markets do not move at one speed. FRAMA listens to the roughness and adjusts the filter."
FRAMA is John Ehlers' fractal adaptive moving average. It estimates a fractal dimension from high and low ranges, then converts that dimension into a dynamic EMA alpha. The result is a moving average that tightens in trends and relaxes in noise.
## Historical Context
FRAMA was introduced in Traders' Tips as an adaptive filter that uses fractal geometry as a proxy for market roughness. It is a classic Ehlers indicator and remains a reference point for adaptive smoothing.
## Architecture & Physics
FRAMA splits the window into two halves, compares the combined range to the full range, and derives a fractal dimension:
1. Compute ranges over the first half, second half, and full window.
2. Convert range ratios to a dimension estimate.
3. Convert dimension to a dynamic alpha.
4. Apply EMA smoothing to HL2 using that alpha.
The implementation follows the strict Ehlers definition:
| **Timeliness** | 8/10 | Adapts to trends quickly |
| **Overshoot** | 5/10 | Can overshoot on sharp reversals |
| **Smoothness** | 7/10 | Smoother than EMA in noise |
## Validation
FRAMA is not implemented in the common TA libraries used by QuanTAlib. Validation uses a direct reference implementation that mirrors the PineScript logic.
FRAMA maintains separate High and Low buffers for fractal dimension calculation:
```csharp
privatereadonlyRingBuffer_highs;
privatereadonlyRingBuffer_lows;
```
The `GetMax` and `GetMin` helper methods scan these buffers for range calculations, supporting both recent-half and full-window lookups via `startOffset` parameter.
### Precomputed Constants
Constructor enforces even period and precalculates half-period:
The `GetMax`/`GetMin` methods perform O(N) linear scans with modular indexing:
```csharp
intidx=start+offset+i;
if(idx>=capacity)idx-=capacity;
```
This approach is simple and cache-friendly for typical periods (10-50). Monotonic deque optimization would reduce to O(1) amortized but adds complexity.
## Common Pitfalls
1.**Period parity**: The algorithm requires even `N`. Odd values are rounded up.
2.**Warmup**: Outputs are `NaN` until `N` bars are available.
3.**Range source**: FRAMA uses High and Low ranges. Feeding Close-only data collapses the ranges.