Gaussian Filter

Parameters: period = 14 | poles = 4 (1–4)

Overview

The Gaussian Filter creates an exceptionally smooth price curve by cascading multiple stages of exponential smoothing to approximate the bell shaped Gaussian distribution, producing minimal lag while eliminating market noise more effectively than traditional moving averages. Each pole represents a filtering stage that recursively smooths the output of the previous stage, with more poles creating a response closer to the ideal Gaussian curve that balances responsiveness with stability. When using four poles, the filter achieves near perfect Gaussian characteristics, removing high frequency noise while preserving the underlying trend structure with less delay than comparable smooth averages. Traders employ Gaussian filters to identify clean trend direction without the jagged movements of faster averages or the excessive lag of slower ones, making it ideal for automated systems that require stable signals. The adjustable pole count allows fine tuning between aggressive filtering for noisy markets (4 poles) and responsive tracking for cleaner price action (1 or 2 poles). Additionally, the Gaussian filter excels as a baseline for oscillators and divergence analysis because its mathematical properties create predictable lag characteristics that remain consistent across different market conditions.

Implementation Examples

Create inputs from a slice or candles and compute Gaussian:

use vector_ta::indicators::gaussian::{gaussian, GaussianInput, GaussianParams};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};

// Using with price data slice
let prices = vec![100.0, 102.0, 101.5, 103.0, 105.0, 104.5];
let params = GaussianParams { period: Some(14), poles: Some(4) };
let input = GaussianInput::from_slice(&prices, params);
let result = gaussian(&input)?;

// Using with Candles data structure (defaults: period=14, poles=4; source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = GaussianInput::with_default_candles(&candles);
let result = gaussian(&input)?;

// Access values
for v in result.values { println!("Gaussian: {}", v); }

API Reference

Input Methods ▼
// From price slice
GaussianInput::from_slice(&[f64], GaussianParams) -> GaussianInput

// From candles with custom source
GaussianInput::from_candles(&Candles, &str, GaussianParams) -> GaussianInput

// From candles with default params (close prices, period=14, poles=4)
GaussianInput::with_default_candles(&Candles) -> GaussianInput
Parameters Structure ▼
pub struct GaussianParams {
    pub period: Option<usize>, // Default: 14
    pub poles: Option<usize>,  // Default: 4 (allowed: 1..=4)
}
Output Structure ▼
pub struct GaussianOutput {
    pub values: Vec<f64>, // Filtered values
}
Validation, Warmup & NaNs ▼
  • period ≥ 2. period == 1 is rejected: GaussianError::PeriodOneDegenerate; period < 2 yields GaussianError::DegeneratePeriod.
  • poles ∈ [1, 4]; otherwise GaussianError::InvalidPoles.
  • period ≤ data.len(); otherwise GaussianError::PeriodLongerThanData.
  • Must have at least period valid points after first finite input; otherwise GaussianError::NotEnoughValidData.
  • Leading indices up to first_valid + period are set to NaN (warmup); subsequent NaNs propagate.
Error Handling ▼
use vector_ta::indicators::gaussian::GaussianError;

match gaussian(&input) {
    Ok(output) => process_results(output.values),
    Err(GaussianError::NoData) => println!("No input data"),
    Err(GaussianError::PeriodOneDegenerate) => println!("period=1 is not allowed"),
    Err(GaussianError::DegeneratePeriod { period }) => println!("period {} must be ≥ 2", period),
    Err(GaussianError::InvalidPoles { poles }) => println!("poles must be 1..4; got {}", poles),
    Err(GaussianError::PeriodLongerThanData { period, data_len }) =>
        println!("period {} exceeds data length {}", period, data_len),
    Err(GaussianError::AllValuesNaN) => println!("All inputs are NaN"),
    Err(GaussianError::NotEnoughValidData { needed, valid }) =>
        println!("Need {} valid points after first finite; got {}", needed, valid),
}

Python Bindings

Basic Usage ▼

Calculate Gaussian using NumPy arrays (explicit parameters required):

import numpy as np
from vector_ta import gaussian

prices = np.array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5], dtype=np.float64)

# Specify parameters explicitly (no implicit defaults in Python wrapper)
values = gaussian(prices, period=14, poles=4, kernel="auto")
Streaming ▼
import numpy as np
from vector_ta import GaussianStream

stream = GaussianStream(period=14, poles=4)
for x in [100.0, 101.0, 100.5, 102.0]:
    y = stream.update(float(x))
    print(y)
Batch Processing ▼

Test multiple parameter combinations efficiently:

import numpy as np
from vector_ta import gaussian_batch

prices = np.array([/* your data */], dtype=np.float64)
out = gaussian_batch(
    prices,
    period_range=(10, 30, 10),
    poles_range=(1, 4, 1),
    kernel="auto"
)

print(out["values"].shape)  # (num_combos, len(prices))
print(out["periods"])       # list of periods for each row
print(out["poles"])         # list of pole counts for each row
CUDA Acceleration ▼

Available when built with Python + CUDA features.

import numpy as np
from vector_ta import gaussian_cuda_batch_dev, gaussian_cuda_many_series_one_param_dev

# Option 1: One series, many parameters (parameter sweep)
prices_f32 = np.array([/* your data */], dtype=np.float32)
res = gaussian_cuda_batch_dev(
    data_f32=prices_f32,
    period_range=(10, 30, 1),
    poles_range=(1, 4, 1),
    device_id=0
)
# res is a device-resident array wrapper (DeviceArrayF32Py)

# Option 2: Many series, one parameter set (time-major: [T, N])
tm = np.array([/* T x N */], dtype=np.float32)
out = gaussian_cuda_many_series_one_param_dev(
    prices_tm_f32=tm,
    period=14,
    poles=4,
    device_id=0
)

JavaScript/WASM Bindings

Basic Usage ▼

Calculate Gaussian in JavaScript/TypeScript:

import { gaussian_js } from 'vectorta-wasm';

const prices = new Float64Array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5]);
const values = gaussian_js(prices, 14, 4);
console.log('Gaussian values:', values);
Memory-Efficient Operations ▼

Use zero-copy operations for large datasets:

import { gaussian_alloc, gaussian_free, gaussian_into, memory } from 'vectorta-wasm';

const prices = new Float64Array([/* your data */]);
const len = prices.length;

const inPtr = gaussian_alloc(len);
const outPtr = gaussian_alloc(len);
new Float64Array(memory.buffer, inPtr, len).set(prices);

// Args: in_ptr, out_ptr, len, period, poles
gaussian_into(inPtr, outPtr, len, 14, 4);

const out = new Float64Array(memory.buffer, outPtr, len).slice();

gaussian_free(inPtr, len);
gaussian_free(outPtr, len);
Batch Processing ▼

Test parameter combinations in one call:

import { gaussian_batch_js, gaussian_batch_metadata_js } from 'vectorta-wasm';

const prices = new Float64Array([/* historical prices */]);

const pStart = 10, pEnd = 30, pStep = 10;  // 10, 20, 30
const kStart = 1,  kEnd = 4,  kStep = 1;   // 1..4

const metadata = gaussian_batch_metadata_js(pStart, pEnd, pStep, kStart, kEnd, kStep);
const numCombos = metadata.length / 2; // [period, poles] pairs

const flat = gaussian_batch_js(prices, pStart, pEnd, pStep, kStart, kEnd, kStep);

// Reshape flat results into matrix
const matrix = [];
for (let i = 0; i < numCombos; i++) {
  const start = i * prices.length;
  const end = start + prices.length;
  matrix.push(flat.slice(start, end));
}

CUDA Bindings (Rust)

use vector_ta::cuda::CudaGaussian;
use vector_ta::indicators::moving_averages::gaussian::GaussianBatchRange;

let cuda = CudaGaussian::new(0)?;

let prices: [f32] = /* ... */;
let sweep = GaussianBatchRange::default();

let out = cuda.gaussian_batch_dev(&prices, &sweep)?;
let _ = out;

Performance Analysis

Comparison:
View:
Loading chart...

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

Related Indicators