Ehlers Smoothed Adaptive Momentum
alpha = 0.07 (0–1) | cutoff = 8 Overview
Ehlers Smoothed Adaptive Momentum is a one-line momentum study that adjusts its effective lookback dynamically instead of staying locked to a single static period. Internally it smooths the source, tracks adaptive phase and period behavior, and then feeds the result through a recursive filter controlled by the cutoff parameter. The output is therefore a momentum line whose responsiveness changes with the evolving cycle structure of the series.
The tradeoff is warmup depth. This implementation intentionally withholds meaningful output for a long initial window because the adaptive lookback logic needs substantial history before it stabilizes. That makes it a better fit for longer continuous runs of data than for very short excerpts. Candle mode defaults to `hl2`, but the builder and batch APIs can target other candle sources when needed.
Defaults: Ehlers Smoothed Adaptive Momentum uses `alpha = 0.07`, `cutoff = 8.0`, and defaults candle input to `hl2`.
Implementation Examples
Compute the adaptive momentum line from a raw slice or from candle `hl2` data.
use vector_ta::indicators::ehlers_smoothed_adaptive_momentum::{
ehlers_smoothed_adaptive_momentum,
EhlersSmoothedAdaptiveMomentumInput,
EhlersSmoothedAdaptiveMomentumParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let output = ehlers_smoothed_adaptive_momentum(
&EhlersSmoothedAdaptiveMomentumInput::from_slice(
&values,
EhlersSmoothedAdaptiveMomentumParams {
alpha: Some(0.07),
cutoff: Some(8.0),
},
)
)?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = ehlers_smoothed_adaptive_momentum(
&EhlersSmoothedAdaptiveMomentumInput::with_default_candles(&candles)
)?;
println!("value = {:?}", output.values.last());
println!("series length = {}", candle_output.values.len()); API Reference
Input Methods ▼
// From candles and a named source field
EhlersSmoothedAdaptiveMomentumInput::from_candles(
&Candles,
&str,
EhlersSmoothedAdaptiveMomentumParams,
) -> EhlersSmoothedAdaptiveMomentumInput
// From a raw slice
EhlersSmoothedAdaptiveMomentumInput::from_slice(
&[f64],
EhlersSmoothedAdaptiveMomentumParams,
) -> EhlersSmoothedAdaptiveMomentumInput
// From candles with default parameters
EhlersSmoothedAdaptiveMomentumInput::with_default_candles(&Candles)
-> EhlersSmoothedAdaptiveMomentumInput Parameters Structure ▼
pub struct EhlersSmoothedAdaptiveMomentumParams {
pub alpha: Option<f64>, // default 0.07
pub cutoff: Option<f64>, // default 8.0
} Output Structure ▼
pub struct EhlersSmoothedAdaptiveMomentumOutput {
pub values: Vec<f64>,
} Validation, Warmup & NaNs ▼
- The input slice must be non-empty and contain at least one finite value.
alphamust be finite and valid for the internal filter.cutoffmust be finite and strictly greater than zero.- The implementation requires at least
76consecutive valid samples from the first finite value onward. - The standard output is NaN-prefixed through
first_valid + 75. - Streaming returns a single floating-point value on every call, but it remains NaN until the long adaptive warmup is complete.
- Batch mode enforces the same long-history requirement and sweeps both alpha and cutoff combinations.
Builder, Streaming & Batch APIs ▼
// Builder
EhlersSmoothedAdaptiveMomentumBuilder::new()
.source(&'static str)
.alpha(f64)
.cutoff(f64)
.kernel(Kernel)
.apply_slice(&[f64])
EhlersSmoothedAdaptiveMomentumBuilder::new()
.apply(&Candles)
EhlersSmoothedAdaptiveMomentumBuilder::new()
.into_stream()
// Stream
EhlersSmoothedAdaptiveMomentumStream::try_new(
EhlersSmoothedAdaptiveMomentumParams
)
EhlersSmoothedAdaptiveMomentumStream::update(f64) -> f64
// Batch
EhlersSmoothedAdaptiveMomentumBatchBuilder::new()
.source(&'static str)
.alpha_range((f64, f64, f64))
.cutoff_range((f64, f64, f64))
.kernel(Kernel)
.apply_slice(&[f64])
EhlersSmoothedAdaptiveMomentumBatchBuilder::new()
.apply(&Candles) Error Handling ▼
pub enum EhlersSmoothedAdaptiveMomentumError {
EmptyInputData,
AllValuesNaN,
InvalidAlpha { alpha: f64 },
InvalidCutoff { cutoff: f64 },
NotEnoughValidData { needed: usize, valid: usize },
OutputLengthMismatch { expected: usize, got: usize },
InvalidRange { start: String, end: String, step: String },
InvalidKernelForBatch(Kernel),
} Python Bindings
Python exposes an array-returning single-run function, a streaming class, and a batch function. The single-run binding returns one NumPy array of adaptive momentum values. Batch returns the values matrix plus the tested alpha and cutoff grids.
import numpy as np
from vector_ta import (
ehlers_smoothed_adaptive_momentum,
ehlers_smoothed_adaptive_momentum_batch,
EhlersSmoothedAdaptiveMomentumStream,
)
data = np.asarray(values, dtype=np.float64)
values_out = ehlers_smoothed_adaptive_momentum(
data,
alpha=0.07,
cutoff=8.0,
kernel="auto",
)
stream = EhlersSmoothedAdaptiveMomentumStream(alpha=0.07, cutoff=8.0)
print(stream.update(data[-1]))
batch = ehlers_smoothed_adaptive_momentum_batch(
data,
alpha_range=(0.07, 0.14, 0.07),
cutoff_range=(8.0, 10.0, 2.0),
kernel="auto",
)
print(batch["alphas"], batch["cutoffs"], batch["rows"], batch["cols"]) JavaScript/WASM Bindings
The WASM layer exposes a single-run array-returning helper, a batch wrapper, and pointer-oriented in-place exports. The batch helper returns the flattened values matrix together with alpha and cutoff metadata.
import init, {
ehlers_smoothed_adaptive_momentum_js,
ehlers_smoothed_adaptive_momentum_batch_js,
} from "/pkg/vector_ta.js";
await init();
const data = new Float64Array(values);
const valuesOut = ehlers_smoothed_adaptive_momentum_js(data, 0.07, 8.0);
console.log(valuesOut);
const batch = ehlers_smoothed_adaptive_momentum_batch_js(data, {
alpha_range: [0.07, 0.14, 0.07],
cutoff_range: [8.0, 10.0, 2.0],
});
console.log(batch.values, batch.alphas, batch.cutoffs, batch.rows, batch.cols); CUDA Bindings (Rust)
Additional details for the CUDA bindings can be found inside the VectorTA repository.
Performance Analysis
Across sizes, Rust CPU runs about 1.14× faster than Tulip C in this benchmark.
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU)
Related Indicators
Acceleration Oscillator
Technical analysis indicator
Accumulation/Distribution
Technical analysis indicator
Awesome Oscillator
Technical analysis indicator
Absolute Price Oscillator
Technical analysis indicator
Commodity Channel Index
Technical analysis indicator
CCI Cycle
Technical analysis indicator