Super Smoother (2‑Pole Filter)
period = 14 Overview
Super Smoother employs a two pole infinite impulse response filter designed by John Ehlers to remove high frequency noise while maintaining the integrity of genuine price trends. Unlike traditional moving averages that simply weight past values, Super Smoother applies digital signal processing techniques derived from electrical engineering to create a frequency response that sharply attenuates noise above a cutoff frequency determined by the period parameter. The two pole design provides steeper rolloff characteristics than single pole filters, meaning it more effectively separates signal from noise without introducing excessive lag. The calculation uses recursive coefficients derived from the period to process each new price point, producing smoothed output that responds to real trend changes while ignoring minor fluctuations. Traders value Super Smoother for creating clean trend lines that avoid the choppy appearance of simple moving averages, making it particularly useful for identifying support and resistance levels or generating crossover signals without false triggers from market noise.
Default: period = 14.
Implementation Examples
Compute Super Smoother from prices or candles:
use vectorta::indicators::moving_averages::supersmoother::{supersmoother, SuperSmootherInput, SuperSmootherParams};
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 = SuperSmootherParams { period: Some(14) };
let input = SuperSmootherInput::from_slice(&prices, params);
let result = supersmoother(&input)?; // result.values is Vec<f64>
// Using with Candles (default source = "close", default period = 14)
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = SuperSmootherInput::with_default_candles(&candles);
let result = supersmoother(&input)?;
// Access values
for v in result.values { println!("SSF: {}", v); } API Reference
Input Methods ▼
// From price slice
SuperSmootherInput::from_slice(&[f64], SuperSmootherParams) -> SuperSmootherInput
// From candles with custom source (e.g., "close")
SuperSmootherInput::from_candles(&Candles, &str, SuperSmootherParams) -> SuperSmootherInput
// From candles with defaults (source="close", period=14)
SuperSmootherInput::with_default_candles(&Candles) -> SuperSmootherInput Parameters Structure ▼
pub struct SuperSmootherParams {
pub period: Option<usize>, // Default: 14
} Output Structure ▼
pub struct SuperSmootherOutput {
pub values: Vec<f64>, // One value per input sample
} Validation, Warmup & NaNs ▼
period > 0andperiod ≤ len(data). OtherwiseSuperSmootherError::InvalidPeriod.- Skips leading
NaNs; if all areNaN→SuperSmootherError::AllValuesNaN. - Requires at least
periodvalid points after the first finite; otherwiseSuperSmootherError::NotEnoughValidData. - Warmup: indices
[0 .. first + period − 2]areNaNin batch output. Streaming returnsNoneuntil two samples are buffered. - Subsequent
NaNs propagate through the recursive formula.
Error Handling ▼
use vectorta::indicators::moving_averages::supersmoother::{
supersmoother, SuperSmootherError, SuperSmootherInput, SuperSmootherParams
};
let input = SuperSmootherInput::from_slice(&prices, SuperSmootherParams { period: Some(14) });
match supersmoother(&input) {
Ok(out) => { /* use out.values */ }
Err(SuperSmootherError::EmptyData) => { /* handle */ }
Err(SuperSmootherError::AllValuesNaN) => { /* handle */ }
Err(SuperSmootherError::InvalidPeriod { period, data_len }) => { /* handle */ }
Err(SuperSmootherError::NotEnoughValidData { needed, valid }) => { /* handle */ }
} Python Bindings
Basic Calculation ▼
import numpy as np
from vectorta import supersmoother
prices = np.array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5], dtype=np.float64)
y = supersmoother(prices, period=14) # returns np.ndarray (float64) Streaming Real‑time Updates ▼
from vectorta import SuperSmootherStream
stream = SuperSmootherStream(period=14)
for price in price_feed:
val = stream.update(price) # None during warmup
if val is not None:
process(val) Batch Parameter Sweep ▼
import numpy as np
from vectorta import supersmoother_batch
prices = np.array([...], dtype=np.float64)
out = supersmoother_batch(prices, period_start=5, period_end=30, period_step=5)
# out['values'] is 2D: rows = number of periods, cols = len(prices)
# out['periods'] lists the periods used
matrix = out['values']
periods = out['periods'] CUDA Acceleration ▼
CUDA APIs are available when built with the cuda feature:
import numpy as np
from vectorta import (
supersmoother_cuda_batch_dev,
supersmoother_cuda_many_series_one_param_dev,
)
# 1) One series, many periods (float32 input on device)
prices_f32 = np.asarray([...], dtype=np.float32)
device_array, meta = supersmoother_cuda_batch_dev(prices_f32, (5, 30, 5), device_id=0)
periods = meta['periods'] # list of periods used
# 2) Many series (time‑major), one period
tm = np.asarray([...], dtype=np.float32) # shape [T, N]
device_array2 = supersmoother_cuda_many_series_one_param_dev(tm, period=14, device_id=0) JavaScript/WASM Bindings
Basic Usage ▼
import { supersmoother_js } from 'vectorta-wasm';
const prices = new Float64Array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5]);
const values = supersmoother_js(prices, 14); // Float64Array-like Vec copy out
console.log('Super Smoother:', values); Memory‑Efficient Operations ▼
import { supersmoother_alloc, supersmoother_free, supersmoother_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const n = prices.length;
const inPtr = supersmoother_alloc(n);
const outPtr = supersmoother_alloc(n);
new Float64Array(memory.buffer, inPtr, n).set(prices);
// Args: in_ptr, out_ptr, len, period
supersmoother_into(inPtr, outPtr, n, 14);
const out = new Float64Array(memory.buffer, outPtr, n).slice();
supersmoother_free(inPtr, n);
supersmoother_free(outPtr, n); Batch Processing ▼
import { supersmoother_batch as supersmoother_batch_js, supersmoother_batch_metadata_js } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
const meta = supersmoother_batch_metadata_js(5, 30, 5); // [period1, period2, ...]
const cfg = { period_range: [5, 30, 5] };
const res = supersmoother_batch_js(prices, cfg);
// res: { values: number[], combos: { period?: number }[], rows: number, cols: number }
// reshape flat results (rows x cols)
const rows = res.rows, cols = res.cols;
const matrix: number[][] = [];
for (let r = 0; r < rows; r++) {
const start = r * cols;
matrix.push(res.values.slice(start, start + cols));
} Performance Analysis
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05
Related Indicators
Arnaud Legoux Moving Average
Moving average indicator
Compound Ratio Moving Average (CoRa Wave)
Moving average indicator
Centered Weighted Moving Average
Moving average indicator
Double Exponential Moving Average
Moving average indicator
Ehlers Distance Coefficient Filter
Moving average indicator
Ehlers Error-Correcting EMA (ECEMA)
Moving average indicator