> *Gaussian distributions govern everything from particle diffusion to the distribution of shoe sizes. Applying them to price action isn't 'technical analysis'; it's just physics with a profit motive.*
ALMA is a Finite Impulse Response (FIR) filter that applies a Gaussian window to price data. Unlike the Simple Moving Average (which treats 10-minute-old data with the same reverence as 1-minute-old data) or the Exponential Moving Average (which holds onto history like a hoarder), ALMA allows you to shape the weight distribution precisely. It lets you define the trade-off between smoothness and lag using standard deviation ($\sigma$) and offset, rather than arbitrary periods.
## Historical Context / The Standard
Arnaud Legoux and Dimitris Kouzis-Loukas published ALMA in 2009. The context was a trading world drowning in "adaptive" moving averages (KAMA, FRAMA) that often adapted too late or overshot the turn.
While Hull (HMA) attempted to solve lag through algebraic subtraction (and created overshoot), and Jurik (JMA) hid behind proprietary black-box math, Legoux returned to first principles: Signal Processing. He applied the Gaussian filter—standard in electrical engineering for noise reduction—to financial time series. It is not a "modern" invention so much as the correct application of established math to a messy domain.
## Architecture & Physics
ALMA is a weighted moving average where weights follow a normal distribution (bell curve).
The physics of ALMA rely on shifting the "center of gravity" of the window.
* **SMA:** Center of gravity is always the middle ($0.5$). Lag is fixed.
* **EMA:** Center of gravity is front-loaded but has an infinite tail.
* **ALMA:** You move the center. An offset of $0.85$ pushes the bulk of the weight to the most recent 15% of the window.
This shift allows the indicator to capture momentum (high responsiveness) while the Gaussian decay kills high-frequency noise (smoothness). It behaves less like a lagging indicator and more like a mass-dampener system.
### The Compute Challenge
Naive implementations recalculate the Gaussian weights on every tick. This is CPU suicide.
QuanTAlib precomputes the weight vector $\mathbf{W}$ upon initialization. The runtime operation effectively becomes a dot product of the price buffer and the weight vector.
While heavier than the recursive EMA ($O(1)$), the memory locality of the arrays allows modern CPUs to vectorise these operations (SIMD), making the penalty negligible for typical window sizes (< 100).
## Mathematical Foundation
The weight calculation relies on three inputs:
1.**Window ($L$)**: The lookback period.
2.**Offset ($o$)**: Where the Gaussian peak sits (0.0 to 1.0). Default is 0.85.
3.**Sigma ($\sigma$)**: The width of the bell curve. Default is 6.0.
### 1. Center and Width Calculation
First, QuanTAlib defines the peak index ($m$) and the spread ($s$):
$$ m = o \cdot (L - 1) $$
$$ s = \frac{L}{\sigma} $$
### 2. Weight Generation
For each index $i$ from $0$ to $L-1$, the unnormalized weight is calculated:
The final ALMA value is the weighted sum. The weights are not normalized to sum to 1.0 beforehand; instead, division by the total sum of weights $W_{sum}$ happens at the end.
| **TA-Lib** | ❌ | Not included in standard C distribution. |
| **Tulip** | ❌ | Not included. |
## Common Pitfalls
1.**Offset Abuse**: Setting offset to `0.99` creates a filter that barely filters. It tracks price so closely you might as well use `Price[0]`. Setting it to `0.5` makes it a centered moving average (great for smoothing, terrible for trading due to repainting if used as such, but ALMA does not repaint). The magic is in the `0.85` region.
2.**Sigma Confusion**:
* $\sigma = 1$: The curve is flat. You have reinvented the Simple Moving Average (badly).
* $\sigma = 10$: The curve is a needle. You are sampling one specific bar in history.