Super Smoother (2‑Pole Filter)

Parameters: 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 > 0 and period ≤ len(data). Otherwise SuperSmootherError::InvalidPeriod.
  • Skips leading NaNs; if all are NaNSuperSmootherError::AllValuesNaN.
  • Requires at least period valid points after the first finite; otherwise SuperSmootherError::NotEnoughValidData.
  • Warmup: indices [0 .. first + period − 2] are NaN in batch output. Streaming returns None until 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

Comparison:
View:
Loading chart...

AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05

Related Indicators