Ehlers Linear Extrapolation Predictor

Parameters: high_pass_length = 125 | low_pass_length = 12 | gain = 0.7 | bars_forward = 5 (0–10) | signal_mode = predict_filter_crosses

Overview

Ehlers Linear Extrapolation Predictor is built to compare a smoothed filter line with a short forward projection of that same filtered structure. The source series is first high-pass filtered to remove slower trend content, then smoothed with Hann-style weights. From that smoothed history the indicator projects a predictor line several bars forward and scales it by the chosen gain. That creates a pair of lines: the present-time filter and the forward-looking prediction.

VectorTA exposes more than just those two lines. It also emits a signed state, plus explicit go_long and go_short flags based on the selected signal interpretation mode. The default mode watches for predictor-versus-filter crosses, while the alternate modes compare either the predictor or the filter to the zero line. That makes this page part waveform tool, part rule-driven signal generator.

Defaults: Ehlers Linear Extrapolation Predictor uses `high_pass_length = 125`, `low_pass_length = 12`, `gain = 0.7`, `bars_forward = 5`, `signal_mode = "predict_filter_crosses"`, and defaults candle input to `close`.

Implementation Examples

Compute the predictor line, filter line, state, and entry flags from a slice or a candle source.

use vector_ta::indicators::ehlers_linear_extrapolation_predictor::{
    ehlers_linear_extrapolation_predictor,
    EhlersLinearExtrapolationPredictorInput,
    EhlersLinearExtrapolationPredictorParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};

let output = ehlers_linear_extrapolation_predictor(
    &EhlersLinearExtrapolationPredictorInput::from_slice(
        &close,
        EhlersLinearExtrapolationPredictorParams::default(),
    )
)?;

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

println!("prediction = {:?}", output.prediction.last());
println!("filter = {:?}", output.filter.last());
println!("go_long = {:?}", candle_output.go_long.last());

API Reference

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

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

// From candles with default parameters
EhlersLinearExtrapolationPredictorInput::with_default_candles(&Candles)
    -> EhlersLinearExtrapolationPredictorInput
Parameters Structure
pub struct EhlersLinearExtrapolationPredictorParams {
    pub high_pass_length: Option<usize>, // default 125
    pub low_pass_length: Option<usize>,  // default 12
    pub gain: Option<f64>,               // default 0.7
    pub bars_forward: Option<usize>,     // default 5
    pub signal_mode: Option<String>,     // default "predict_filter_crosses"
}
Output Structure
pub struct EhlersLinearExtrapolationPredictorOutput {
    pub prediction: Vec<f64>,
    pub filter: Vec<f64>,
    pub state: Vec<f64>,
    pub go_long: Vec<f64>,
    pub go_short: Vec<f64>,
}
Validation, Warmup & NaNs
  • The input slice must be non-empty and contain at least one finite value.
  • high_pass_length and low_pass_length must be greater than zero.
  • gain must be finite.
  • bars_forward must stay within the implementation limit of 0..=10.
  • signal_mode must be one of predict_filter_crosses, predict_middle_crosses, or filter_middle_crosses.
  • Warmup lasts for low_pass_length + 11 bars.
  • Streaming resets on non-finite input and returns None until warmup completes again.
Builder, Streaming & Batch APIs
// Builder
EhlersLinearExtrapolationPredictorBuilder::new()
    .high_pass_length(usize)
    .low_pass_length(usize)
    .gain(f64)
    .bars_forward(usize)
    .signal_mode(&str)?
    .kernel(Kernel)
    .apply_slice(&[f64])

EhlersLinearExtrapolationPredictorBuilder::new()
    .apply(&Candles, &str)

EhlersLinearExtrapolationPredictorBuilder::new()
    .into_stream()

// Stream
EhlersLinearExtrapolationPredictorStream::try_new(
    EhlersLinearExtrapolationPredictorParams
)
EhlersLinearExtrapolationPredictorStream::update(f64)
    -> Option<(f64, f64, f64, f64, f64)>
EhlersLinearExtrapolationPredictorStream::get_warmup_period() -> usize

// Batch
EhlersLinearExtrapolationPredictorBatchBuilder::new()
    .high_pass_length_range(start, end, step)
    .low_pass_length_range(start, end, step)
    .gain_range(start, end, step)
    .bars_forward_range(start, end, step)
    .signal_mode(&str)?
    .kernel(Kernel)
    .apply_slice(&[f64])

EhlersLinearExtrapolationPredictorBatchBuilder::new()
    .apply_candles(&Candles, &str)
Error Handling
pub enum EhlersLinearExtrapolationPredictorError {
    EmptyInputData,
    AllValuesNaN,
    InvalidHighPassLength { high_pass_length: usize },
    InvalidLowPassLength { low_pass_length: usize },
    InvalidGain { gain: f64 },
    InvalidBarsForward { bars_forward: usize },
    InvalidSignalMode { signal_mode: String },
    NotEnoughValidData { needed: usize, valid: usize },
    OutputLengthMismatch {
        expected: usize,
        prediction_got: usize,
        filter_got: usize,
        state_got: usize,
        go_long_got: usize,
        go_short_got: usize,
    },
    InvalidRange { start: String, end: String, step: String },
    InvalidKernelForBatch(Kernel),
}

Python Bindings

Python exposes a five-array single-run function, a streaming class, and a batch function. The single-run binding returns prediction, filter, state, go_long, and go_short arrays. Batch returns matrices for all five outputs together with the tested parameter grids.

import numpy as np
from vector_ta import (
    ehlers_linear_extrapolation_predictor,
    ehlers_linear_extrapolation_predictor_batch,
    EhlersLinearExtrapolationPredictorStream,
)

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

prediction, filter_, state, go_long, go_short = ehlers_linear_extrapolation_predictor(
    data,
    high_pass_length=125,
    low_pass_length=12,
    gain=0.7,
    bars_forward=5,
    signal_mode="predict_filter_crosses",
    kernel="auto",
)

stream = EhlersLinearExtrapolationPredictorStream(
    high_pass_length=125,
    low_pass_length=12,
    gain=0.7,
    bars_forward=5,
    signal_mode="predict_filter_crosses",
)
print(stream.update(data[-1]))
print(stream.warmup_period)

batch = ehlers_linear_extrapolation_predictor_batch(
    data,
    high_pass_length_range=(80, 125, 45),
    low_pass_length_range=(10, 14, 2),
    gain_range=(0.7, 0.9, 0.2),
    bars_forward_range=(3, 5, 2),
    signal_mode="predict_filter_crosses",
    kernel="auto",
)

print(batch["signal_modes"], batch["rows"], batch["cols"])

JavaScript/WASM Bindings

The WASM layer exposes an object-returning single-run helper, pointer-oriented in-place exports, and a batch helper that returns all five output matrices together with parameter metadata. The single-run helper returns named arrays for prediction, filter, state, go_long, and go_short.

import init, {
  ehlers_linear_extrapolation_predictor_js,
  ehlers_linear_extrapolation_predictor_batch_js,
} from "/pkg/vector_ta.js";

await init();

const data = new Float64Array(closeValues);

const single = ehlers_linear_extrapolation_predictor_js(
  data,
  125,
  12,
  0.7,
  5,
  "predict_filter_crosses",
);
console.log(single.prediction, single.filter, single.go_long);

const batch = ehlers_linear_extrapolation_predictor_batch_js(data, {
  high_pass_length_range: [80, 125, 45],
  low_pass_length_range: [10, 14, 2],
  gain_range: [0.7, 0.9, 0.2],
  bars_forward_range: [3, 5, 2],
  signal_mode: "predict_filter_crosses",
});

console.log(batch.prediction, batch.filter, batch.signal_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