Smooth Theil Sen

Parameters: length = 25 | offset = 0 | multiplier = 2 | slope_style = smooth_median | residual_style = smooth_median | deviation_style = mad | mad_style = smooth_median | include_prediction_in_deviation =

Overview

Smooth Theil Sen is a robust rolling regression channel. For each window it derives a Theil-Sen-style slope and intercept, then constructs upper and lower envelopes from a configurable deviation measure. The output includes the center line, bands, slope, intercept, and the final deviation series itself.

The statistic controls let you bias the slope and residual aggregation toward a mean, a median, or a smoothed median blend. That makes the indicator useful both as a robust trend estimator and as a configurable channel for dispersion and regime analysis.

Defaults: `length = 25`, `offset = 0`, `multiplier = 2.0`, `slope_style = "smooth_median"`, `residual_style = "smooth_median"`, `deviation_style = "mad"`, `mad_style = "smooth_median"`, and `include_prediction_in_deviation = false`.

Implementation Examples

Run the channel on candle closes or on a direct source slice with one resolved parameter set.

use vector_ta::indicators::smooth_theil_sen::{
    smooth_theil_sen,
    SmoothTheilSenInput,
    SmoothTheilSenParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};

let out = smooth_theil_sen(&SmoothTheilSenInput::from_slice(
    &close,
    SmoothTheilSenParams {
        length: Some(25),
        offset: Some(0),
        multiplier: Some(2.0),
        slope_style: None,
        residual_style: None,
        deviation_style: None,
        mad_style: None,
        include_prediction_in_deviation: Some(false),
    },
))?;

let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_out = smooth_theil_sen(&SmoothTheilSenInput::with_default_candles(&candles))?;

println!("value = {:?}", out.value.last());
println!("upper = {:?}", candle_out.upper.last());

API Reference

Input Methods
SmoothTheilSenInput::from_candles(&Candles, "close", SmoothTheilSenParams)
    -> SmoothTheilSenInput

SmoothTheilSenInput::from_slice(&[f64], SmoothTheilSenParams)
    -> SmoothTheilSenInput

SmoothTheilSenInput::with_default_candles(&Candles)
    -> SmoothTheilSenInput
Parameters Structure
pub struct SmoothTheilSenParams {
    pub length: Option<usize>,                         // default 25
    pub offset: Option<usize>,                         // default 0
    pub multiplier: Option<f64>,                       // default 2.0
    pub slope_style: Option<SmoothTheilSenStatStyle>,  // mean, smooth_median, median
    pub residual_style: Option<SmoothTheilSenStatStyle>,
    pub deviation_style: Option<SmoothTheilSenDeviationType>, // mad or rmsd
    pub mad_style: Option<SmoothTheilSenStatStyle>,
    pub include_prediction_in_deviation: Option<bool>, // default false
}
Output Structure
pub struct SmoothTheilSenOutput {
    pub value: Vec<f64>,
    pub upper: Vec<f64>,
    pub lower: Vec<f64>,
    pub slope: Vec<f64>,
    pub intercept: Vec<f64>,
    pub deviation: Vec<f64>,
}
Validation, Warmup & Modes
  • The source slice must not be empty and must contain at least one finite value.
  • length must be at least 2.
  • multiplier must be finite and non-negative.
  • The candle path validates that the requested source exists.
  • The direct and batch paths require at least length + offset valid bars after the first finite value.
  • The stream path returns six NaN values until its rolling window reaches length + offset samples.
  • Supported statistic styles are mean, smooth_median, and median. Supported deviation styles are mad and rmsd.
Builder, Streaming & Batch APIs
SmoothTheilSenBuilder::new()
    .source("close")
    .length(usize)
    .offset(usize)
    .multiplier(f64)
    .slope_style(SmoothTheilSenStatStyle)
    .residual_style(SmoothTheilSenStatStyle)
    .deviation_style(SmoothTheilSenDeviationType)
    .mad_style(SmoothTheilSenStatStyle)
    .include_prediction_in_deviation(bool)
    .kernel(Kernel)
    .apply(&Candles)
    .apply_slice(&[f64])
    .into_stream()

SmoothTheilSenStream::try_new(params)
stream.update(f64) -> (f64, f64, f64, f64, f64, f64)

SmoothTheilSenBatchBuilder::new()
    .source("close")
    .length_range((start, end, step))
    .offset_range((start, end, step))
    .multiplier_range((start, end, step))
    .slope_style(SmoothTheilSenStatStyle)
    .residual_style(SmoothTheilSenStatStyle)
    .deviation_style(SmoothTheilSenDeviationType)
    .mad_style(SmoothTheilSenStatStyle)
    .include_prediction_in_deviation(bool)
    .kernel(Kernel)
    .apply(&Candles)
    .apply_slice(&[f64])

Python Bindings

Python exposes one scalar function, one stream class, and one batch helper. The scalar path returns a dictionary of six NumPy arrays, the stream emits a six-value tuple each update, and the batch helper returns six reshaped matrices plus the expanded length, offset, and multiplier axes.

from vector_ta import smooth_theil_sen, smooth_theil_sen_batch, SmoothTheilSenStream

out = smooth_theil_sen(
    close,
    length=25,
    offset=0,
    multiplier=2.0,
    slope_style="smooth_median",
    residual_style="smooth_median",
    deviation_style="mad",
    mad_style="smooth_median",
    include_prediction_in_deviation=False,
)

stream = SmoothTheilSenStream()
point = stream.update(close[-1])

batch = smooth_theil_sen_batch(
    close,
    length_range=(20, 30, 5),
    offset_range=(0, 2, 1),
    multiplier_range=(1.5, 2.5, 0.5),
)

print(out["value"][-1])
print(batch["rows"], batch["cols"])

JavaScript/WASM Bindings

The WASM layer exposes high-level scalar and batch helpers plus low-level allocation and into-buffer APIs. The scalar call returns all six output arrays in one object, and the low-level paths write six flattened buffers into caller-managed memory.

import init, {
  smooth_theil_sen_js,
  smooth_theil_sen_batch_js,
  smooth_theil_sen_alloc,
  smooth_theil_sen_free,
  smooth_theil_sen_into,
  smooth_theil_sen_batch_into,
} from "vector-ta-wasm";

await init();

const out = smooth_theil_sen_js(
  close,
  25,
  0,
  2.0,
  "smooth_median",
  "smooth_median",
  "mad",
  "smooth_median",
  false,
);

const batch = smooth_theil_sen_batch_js(close, {
  length_range: [20, 30, 5],
  offset_range: [0, 2, 1],
  multiplier_range: [1.5, 2.5, 0.5],
});

CUDA Bindings (Rust)

Additional details for the CUDA bindings can be found inside the VectorTA repository.

Performance Analysis

Comparison:
View:
Placeholder data (no recorded benchmarks for this indicator)

Across sizes, Rust CPU runs about 1.14× faster than Tulip C in this benchmark.

Loading chart...

AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU)

Related Indicators