Ehlers Kaufman Adaptive Moving Average (Ehlers KAMA)
period = 20 Overview
The Ehlers Kaufman Adaptive Moving Average combines Perry Kaufman's efficiency ratio concept with John Ehlers' smoothing constants to create an adaptive filter that automatically adjusts to market conditions. The indicator calculates an Efficiency Ratio (ER) by comparing the net price change over a period to the sum of absolute price changes. This ratio measures how efficiently price moves from point A to point B, with values near 1 indicating strong directional movement and values near 0 suggesting choppy, inefficient action. Ehlers' modification applies specific smoothing constants that optimize the balance between responsiveness and stability, creating a more refined adaptation mechanism than the original KAMA.
When markets trend efficiently with high ER values, Ehlers KAMA reduces its smoothing to track price closely and capture the move. During choppy periods with low ER values, the indicator increases smoothing dramatically to filter out whipsaws and false signals. This automatic adjustment happens continuously, with the smoothing factor recalculated at each bar based on current market efficiency. The 20 period default provides a good balance for measuring efficiency across different timeframes. The Ehlers constants ensure smoother transitions between trending and ranging states compared to the original KAMA, reducing the indicator's tendency to overshoot during regime changes.
Traders use Ehlers KAMA as an intelligent trend following tool that adapts to market character without manual intervention. The indicator excels at staying with trends while avoiding whipsaws during consolidations, making it ideal for systematic trading strategies. Crossovers between price and Ehlers KAMA generate trading signals with an excellent risk reward profile, as the adaptive smoothing helps filter out low probability setups. Many traders combine Ehlers KAMA with momentum oscillators, entering positions when both align. The indicator also serves as an adaptive trailing stop, maintaining appropriate distance from price based on current market efficiency rather than fixed parameters.
Implementation Examples
Get started with Ehlers KAMA in a few lines:
use vectorta::indicators::{ehlers_kama, EhlersKamaInput, EhlersKamaParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using with a price slice
let prices = vec![100.0, 102.0, 101.5, 103.0, 105.0, 104.5];
let params = EhlersKamaParams { period: Some(20) };
let input = EhlersKamaInput::from_slice(&prices, params);
let result = ehlers_kama(&input)?;
// Using with Candles (defaults: source="close", period=20)
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = EhlersKamaInput::with_default_candles(&candles);
let result = ehlers_kama(&input)?;
// Access the values
for v in result.values { println!("KAMA: {}", v); } API Reference
Input Methods ▼
// From price slice
EhlersKamaInput::from_slice(&[f64], EhlersKamaParams) -> EhlersKamaInput
// From candles with custom source
EhlersKamaInput::from_candles(&Candles, &str, EhlersKamaParams) -> EhlersKamaInput
// From candles with defaults (close, period=20)
EhlersKamaInput::with_default_candles(&Candles) -> EhlersKamaInput Parameters Structure ▼
pub struct EhlersKamaParams {
pub period: Option<usize>, // Default: 20
} Output Structure ▼
pub struct EhlersKamaOutput {
pub values: Vec<f64>, // Adaptive moving average values
} Validation, Warmup & NaNs ▼
period > 0andperiod ≤ len(data); otherwiseEhlersKamaError::InvalidPeriod.- Requires at least
periodvalid points after the first finite value; elseEhlersKamaError::NotEnoughValidData. - Leading
NaNs are skipped; indices beforefirst + period - 1areNaNin output (warmup prefix). - Initial seed uses the previous price (Pine-style). Smoothing constant:
s = (0.6667·EF + 0.0645)^2. - Streaming returns
Noneuntilperiodsamples are received; then one value per update.
Error Handling ▼
use vectorta::indicators::{ehlers_kama, EhlersKamaInput, EhlersKamaParams};
use vectorta::indicators::moving_averages::ehlers_kama::EhlersKamaError;
match ehlers_kama(&input) {
Ok(output) => process(output.values),
Err(EhlersKamaError::EmptyInputData) => eprintln!("input slice is empty"),
Err(EhlersKamaError::AllValuesNaN) => eprintln!("all values are NaN"),
Err(EhlersKamaError::InvalidPeriod { period, data_len }) =>
eprintln!("invalid period: {} (len={})", period, data_len),
Err(EhlersKamaError::NotEnoughValidData { needed, valid }) =>
eprintln!("need {} valid points, got {}", needed, valid),
} Python Bindings
Basic Usage ▼
Calculate Ehlers KAMA using NumPy arrays (default period=20):
import numpy as np
from vectorta import ehlers_kama
prices = np.array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5])
# Default period=20
vals = ehlers_kama(prices, period=20)
# Specify kernel for performance ("auto", "avx2", "avx512", "scalar")
vals = ehlers_kama(prices, period=20, kernel="auto")
print(vals) Streaming Real-time Updates ▼
from vectorta import EhlersKamaStream
stream = EhlersKamaStream(period=20)
for price in price_feed:
v = stream.update(price)
if v is not None:
print(v) Batch Parameter Optimization ▼
import numpy as np
from vectorta import ehlers_kama_batch
prices = np.array([...])
# period_range = (start, end, step)
res = ehlers_kama_batch(
prices,
period_range=(10, 50, 5),
kernel="auto"
)
values = res["values"] # shape: [num_periods, len(prices)]
periods = res["periods"] # list of periods used CUDA Acceleration ▼
CUDA-enabled Python APIs (when built with CUDA support):
from vectorta import (
ehlers_kama_cuda_batch_dev,
ehlers_kama_cuda_many_series_one_param_dev,
)
import numpy as np
# One series, many parameters (batch sweep on GPU)
prices = np.array([...], dtype=np.float32)
device_id = 0
gpu_result = ehlers_kama_cuda_batch_dev(
data_f32=prices,
period_range=(10, 50, 1),
device_id=device_id,
)
# Many series, one parameter (time-major [T, N])
portfolio = np.array([...], dtype=np.float32) # shape [T, N]
gpu_result2 = ehlers_kama_cuda_many_series_one_param_dev(
data_tm_f32=portfolio,
period=20,
device_id=device_id,
) JavaScript/WASM Bindings
Basic Usage ▼
Calculate Ehlers KAMA with WASM:
import { ehlers_kama_js } from 'vectorta-wasm';
const prices = new Float64Array([100, 102, 101.5, 103, 105, 104.5]);
const values = ehlers_kama_js(prices, 20);
console.log('KAMA values:', values); Memory-Efficient Operations ▼
Use zero-copy operations for large datasets:
import { ehlers_kama_alloc, ehlers_kama_free, ehlers_kama_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* data */]);
const n = prices.length;
const inPtr = ehlers_kama_alloc(n);
const outPtr = ehlers_kama_alloc(n);
// Copy input into WASM memory
new Float64Array(memory.buffer, inPtr, n).set(prices);
// Args: in_ptr, out_ptr, len, period
ehlers_kama_into(inPtr, outPtr, n, 20);
const out = new Float64Array(memory.buffer, outPtr, n).slice();
ehlers_kama_free(inPtr, n);
ehlers_kama_free(outPtr, n);
console.log('KAMA values:', out); Batch Processing ▼
Sweep multiple period values:
import { ehlers_kama_batch } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
// Unified batch API returns values, combos, rows, cols
const cfg = { period_range: [10, 50, 5] };
const res = ehlers_kama_batch(prices, cfg);
console.log(res.rows, res.cols);
console.log(res.combos); // [{ period: 10 }, { period: 15 }, ...]
console.log(res.values); // flat array: rows * cols
// Reshape if needed
const matrix = [] as number[][];
for (let i = 0; i < res.rows; i++) {
const start = i * res.cols;
matrix.push(res.values.slice(start, start + res.cols));
} Performance Analysis
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05
CUDA note
In our benchmark workload, the Rust CPU implementation is faster than CUDA for this indicator. Prefer the Rust/CPU path unless your workload differs.
Related Indicators
Arnaud Legoux Moving Average
Moving average indicator
Compound Ratio Moving Average (CoRa Wave)
Moving average indicator
High-Low Correlation
Technical analysis indicator
Centered Weighted Moving Average
Moving average indicator
Double Exponential Moving Average
Moving average indicator
Ehlers Distance Coefficient Filter
Moving average indicator