EMA Deviation Corrected T3

Parameters: period = 10 | hot = 0.7 | t3_mode = 0

Overview

EMA Deviation Corrected T3 is a two-line overlay that starts from a classic multi-stage T3 smoothing chain and then adds a second line designed to correct for the amount of deviation that line can support. The base output is the T3 itself. The companion corrected line compares the current T3 value against a rolling EMA-based estimate of price variance and only lets the correction expand when the gap is large enough to justify it.

In practice, that means the page documents two related overlays rather than one. The T3 line gives you the raw smoothed trend estimate, while the corrected line tries to keep that trend estimate from overreacting when the move is already well explained by recent variance. Candle mode defaults to `close`, and unlike many longer-cycle studies this implementation starts producing finite output immediately from the first valid value.

Defaults: EMA Deviation Corrected T3 uses `period = 10`, `hot = 0.7`, `t3_mode = 0`, and defaults candle input to `close`.

Implementation Examples

Compute both the corrected overlay and the baseline T3 line from a slice or candle closes.

use vector_ta::indicators::moving_averages::ema_deviation_corrected_t3::{
    ema_deviation_corrected_t3,
    EmaDeviationCorrectedT3Input,
    EmaDeviationCorrectedT3Params,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};

let values = vec![100.0, 100.5, 101.1, 101.8, 101.4, 102.0, 102.6];

let output = ema_deviation_corrected_t3(
    &EmaDeviationCorrectedT3Input::from_slice(
        &values,
        EmaDeviationCorrectedT3Params {
            period: Some(10),
            hot: Some(0.7),
            t3_mode: Some(0),
        },
    )
)?;

let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = ema_deviation_corrected_t3(
    &EmaDeviationCorrectedT3Input::with_default_candles(&candles)
)?;

println!("corrected = {:?}", output.corrected.last());
println!("t3 = {:?}", candle_output.t3.last());

API Reference

Input Methods
// From candles and a named source field
EmaDeviationCorrectedT3Input::from_candles(
    &Candles,
    &str,
    EmaDeviationCorrectedT3Params,
) -> EmaDeviationCorrectedT3Input

// From a raw slice
EmaDeviationCorrectedT3Input::from_slice(&[f64], EmaDeviationCorrectedT3Params)
    -> EmaDeviationCorrectedT3Input

// From candles with default parameters
EmaDeviationCorrectedT3Input::with_default_candles(&Candles)
    -> EmaDeviationCorrectedT3Input
Parameters Structure
pub struct EmaDeviationCorrectedT3Params {
    pub period: Option<usize>, // default 10
    pub hot: Option<f64>,      // default 0.7
    pub t3_mode: Option<usize>, // default 0
}
Output Structure
pub struct EmaDeviationCorrectedT3Output {
    pub corrected: Vec<f64>,
    pub t3: Vec<f64>,
}
Validation, Warmup & NaNs
  • The input slice must be non-empty and contain at least one finite value.
  • period must be valid for the supplied data length.
  • hot must be finite and valid for the T3 coefficient calculation.
  • t3_mode must be a supported integer mode for the alpha calculation path.
  • There is no long warmup gate here: the first finite input produces finite T3 and corrected outputs immediately.
  • Streaming returns None for non-finite input and resets its internal state when that happens.
  • Batch mode validates both integer and floating-point ranges and rejects unsupported non-batch kernels.
Builder, Streaming & Batch APIs
// Builder
EmaDeviationCorrectedT3Builder::new()
    .period(usize)
    .hot(f64)
    .t3_mode(usize)
    .kernel(Kernel)
    .apply_slice(&[f64])

EmaDeviationCorrectedT3Builder::new()
    .apply(&Candles)

EmaDeviationCorrectedT3Builder::new()
    .into_stream()

// Stream
EmaDeviationCorrectedT3Stream::try_new(EmaDeviationCorrectedT3Params)
EmaDeviationCorrectedT3Stream::update(f64) -> Option<(f64, f64)>
EmaDeviationCorrectedT3Stream::reset()

// Batch
EmaDeviationCorrectedT3BatchBuilder::new()
    .period_range(start, end, step)
    .hot_range(start, end, step)
    .t3_mode_range(start, end, step)
    .kernel(Kernel)
    .apply_slice(&[f64])

EmaDeviationCorrectedT3BatchBuilder::new()
    .apply_candles(&Candles, &str)
Error Handling
pub enum EmaDeviationCorrectedT3Error {
    EmptyInputData,
    AllValuesNaN,
    InvalidPeriod { period: usize, data_len: usize },
    InvalidHot { hot: f64 },
    InvalidT3Mode { mode: usize },
    OutputLengthMismatch { expected: usize, got: usize },
    InvalidRangeUsize { start: usize, end: usize, step: usize },
    InvalidRangeF64 { start: f64, end: f64, step: f64 },
    InvalidKernelForBatch(Kernel),
}

Python Bindings

Python exposes a tuple-returning single-run function, a streaming class, and a batch function. The single-run binding returns the corrected line first and the baseline T3 line second. The batch binding returns separate corrected and T3 matrices plus the tested parameter axes.

import numpy as np
from vector_ta import (
    ema_deviation_corrected_t3,
    ema_deviation_corrected_t3_batch,
    EmaDeviationCorrectedT3Stream,
)

data = np.asarray(close_values, dtype=np.float64)

corrected, t3 = ema_deviation_corrected_t3(
    data,
    period=10,
    hot=0.7,
    t3_mode=0,
    kernel="auto",
)

stream = EmaDeviationCorrectedT3Stream(period=10, hot=0.7, t3_mode=0)
print(stream.update(data[-1]))  # returns (corrected, t3) or None

batch = ema_deviation_corrected_t3_batch(
    data,
    period_range=(10, 14, 2),
    hot_range=(0.7, 0.9, 0.1),
    t3_mode_range=(0, 1, 1),
    kernel="auto",
)

print(batch["corrected"].shape, batch["t3"].shape)
print(batch["periods"], batch["hots"], batch["t3_modes"])
print(batch["rows"], batch["cols"])

JavaScript/WASM Bindings

The WASM layer exposes a packed scalar wrapper, a structured batch wrapper, and lower-level allocation and in-place exports. The scalar JavaScript path returns one object with `rows = 2`, `cols = data.length`, and a packed `values` array containing the corrected row first and the T3 row second.

import init, {
  ema_deviation_corrected_t3_js,
  ema_deviation_corrected_t3_batch_js,
} from "/pkg/vector_ta.js";

await init();

const data = new Float64Array(closeValues);

const packed = ema_deviation_corrected_t3_js(data, 10, 0.7, 0);
console.log(packed.values, packed.rows, packed.cols);

const batch = ema_deviation_corrected_t3_batch_js(data, {
  period_range: [10, 14, 2],
  hot_range: [0.7, 0.9, 0.1],
  t3_mode_range: [0, 1, 1],
});

console.log(batch.corrected, batch.t3, batch.periods, batch.hots, batch.t3_modes, batch.rows, batch.cols);

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