3-Pole SuperSmoother Filter
period = 14 Overview
The Three Pole Supersmoother applies a sophisticated digital filter design based on the Butterworth filter response to eliminate market noise while preserving underlying trend information. This advanced smoothing algorithm employs three cascaded filter stages, providing a sharper cutoff than simpler two pole versions and dramatically attenuating high frequency price fluctuations. The indicator excels at removing whipsaws and false signals that plague traditional moving averages, though the additional filtering stage introduces slightly more lag than the two pole variant. Traders appreciate its ability to clearly define trend direction without the jittery behavior of less sophisticated smoothers. The filter maintains near zero lag around steady trends while providing steep rolloff in the stopband, making it particularly effective for identifying high probability trend continuation setups. Default period is 14, balancing responsiveness with noise rejection in most market conditions.
Implementation Examples
Get started with the 3‑Pole SuperSmoother in a few lines:
use vectorta::indicators::supersmoother_3_pole::{
supersmoother_3_pole, SuperSmoother3PoleInput, SuperSmoother3PoleParams
};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using with a price slice
let prices = vec![100.0, 101.0, 100.5, 102.0, 103.0];
let params = SuperSmoother3PoleParams { period: Some(14) };
let input = SuperSmoother3PoleInput::from_slice(&prices, params);
let result = supersmoother_3_pole(&input)?;
// Using with Candles data (defaults: period=14, source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = SuperSmoother3PoleInput::with_default_candles(&candles);
let result = supersmoother_3_pole(&input)?;
// Access the smoothed values
for value in result.values {
println!("SS3: {}", value);
} API Reference
Input Methods ▼
// From price slice
SuperSmoother3PoleInput::from_slice(&[f64], SuperSmoother3PoleParams) -> SuperSmoother3PoleInput
// From candles with custom source
SuperSmoother3PoleInput::from_candles(&Candles, &str, SuperSmoother3PoleParams) -> SuperSmoother3PoleInput
// From candles with default params (close, period=14)
SuperSmoother3PoleInput::with_default_candles(&Candles) -> SuperSmoother3PoleInput Parameters Structure ▼
pub struct SuperSmoother3PoleParams {
pub period: Option<usize>, // Default: 14
} Output Structure ▼
pub struct SuperSmoother3PoleOutput {
pub values: Vec<f64>, // Filtered values, same length as input
} Validation, Warmup & NaNs ▼
period > 0andperiod ≤ len(data); otherwiseSuperSmoother3PoleError::InvalidPeriod.- Requires at least
periodvalid values after the first finite input; otherwiseSuperSmoother3PoleError::NotEnoughValidData. - Indices before the first finite input are
NaN(zero‑copy prefix allocation). - Warmup: first three outputs after the first finite input are the raw input values; recursion begins at index
first+3. supersmoother_3_pole_into_slicevalidates destination length and may returnOutputLengthMismatch.
Error Handling ▼
use vectorta::indicators::supersmoother_3_pole::{
supersmoother_3_pole, SuperSmoother3PoleError
};
match supersmoother_3_pole(&input) {
Ok(output) => process(output.values),
Err(SuperSmoother3PoleError::EmptyInputData) =>
eprintln!("Input data is empty"),
Err(SuperSmoother3PoleError::AllValuesNaN) =>
eprintln!("All values are NaN"),
Err(SuperSmoother3PoleError::InvalidPeriod { period }) =>
eprintln!("Invalid period: {}", period),
Err(SuperSmoother3PoleError::NotEnoughValidData { needed, valid }) =>
eprintln!("Need {} points, only {} valid", needed, valid),
Err(SuperSmoother3PoleError::OutputLengthMismatch { expected, actual }) =>
eprintln!("Output length mismatch: expected={}, actual={}", expected, actual),
Err(SuperSmoother3PoleError::InvalidKernel) =>
eprintln!("Invalid kernel for batch operation"),
} Python Bindings
Basic Usage ▼
Compute the filter using NumPy arrays (specify period; kernel optional):
import numpy as np
from vectorta import supersmoother_3_pole
prices = np.array([100.0, 101.0, 100.5, 102.0, 103.0], dtype=float)
# Required period; kernel is optional: 'auto' | 'scalar' | 'avx2' | 'avx512'
result = supersmoother_3_pole(prices, period=14, kernel="auto")
print("SS3 values:", result) Streaming Real-time Updates ▼
Maintain internal state and update in O(1):
from vectorta import SuperSmoother3PoleStream
stream = SuperSmoother3PoleStream(period=14)
for price in price_feed:
value = stream.update(price)
handle(value) Batch Parameter Optimization ▼
Evaluate multiple periods in one call:
import numpy as np
from vectorta import supersmoother_3_pole_batch
prices = np.asarray([...], dtype=float)
# (start, end, step)
out = supersmoother_3_pole_batch(prices, period_range=(5, 30, 5), kernel="auto")
print(out["values"].shape) # (num_periods, len(prices))
print(out["periods"]) # array of tested periods CUDA Acceleration ▼
CUDA is available for this indicator when built with python+cuda features.
import numpy as np
from vectorta import (
supersmoother_3_pole_cuda_batch_dev,
supersmoother_3_pole_cuda_many_series_one_param_dev,
)
# 1) One series, many periods (F32 device output)
prices_f32 = np.asarray([...], dtype=np.float32)
dev_array = supersmoother_3_pole_cuda_batch_dev(
prices_f32, period_range=(5, 30, 1), device_id=0
)
# dev_array is a device-backed array wrapper (DeviceArrayF32Py)
# 2) Many series (time-major), one period
tm_f32 = np.asarray([[...], [...]], dtype=np.float32) # shape [T, N]
dev_array = supersmoother_3_pole_cuda_many_series_one_param_dev(
tm_f32, period=14, device_id=0
) JavaScript/WASM Bindings
Basic Usage ▼
Compute in JS/TS with the WASM package:
import { supersmoother_3_pole_js } from 'vectorta-wasm';
const prices = new Float64Array([100, 101, 100.5, 102, 103]);
const values = supersmoother_3_pole_js(prices, 14);
console.log('SS3 values:', values); Memory-Efficient Operations ▼
Use zero-copy buffers for large arrays:
import { supersmoother_3_pole_alloc, supersmoother_3_pole_free, supersmoother_3_pole_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const len = prices.length;
const inPtr = supersmoother_3_pole_alloc(len);
const outPtr = supersmoother_3_pole_alloc(len);
new Float64Array(memory.buffer, inPtr, len).set(prices);
// Args: in_ptr, out_ptr, len, period
supersmoother_3_pole_into(inPtr, outPtr, len, 14);
const out = new Float64Array(memory.buffer, outPtr, len).slice();
supersmoother_3_pole_free(inPtr, len);
supersmoother_3_pole_free(outPtr, len); Batch Processing ▼
Evaluate many periods and reshape as needed:
import { supersmoother_3_pole_batch_js, supersmoother_3_pole_batch_metadata_js } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
const start = 5, end = 30, step = 5;
const metadata = supersmoother_3_pole_batch_metadata_js(start, end, step); // [periods]
const flat = supersmoother_3_pole_batch_js(prices, start, end, step);
const rows = metadata.length;
const cols = prices.length;
// Reshape: rows x cols
const matrix = [] as Float64Array[];
for (let r = 0; r < rows; r++) {
const begin = r * cols;
matrix.push(flat.slice(begin, begin + 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