Linear Regression Intercept (LINEARREG_INTERCEPT)

Parameters: period = 14

Overview

The Linear Regression Intercept provides the theoretical "fair value" price at the current moment by calculating where the best fit regression line intersects the present time, creating a dynamic equilibrium level that adapts to changing market conditions while filtering out noise. This intercept represents the regression line's endpoint value, essentially showing where price should theoretically be if it followed the average trend perfectly over the lookback period without any deviation or volatility. When actual price trades above the intercept, it signals short term overbought conditions relative to the regression trend, while price below the intercept indicates oversold conditions ripe for mean reversion trades. The indicator acts as a sophisticated moving average that uses statistical best fit rather than simple averaging, providing cleaner signals because it considers the entire price structure over the period rather than just weighting individual values. Swing traders use the intercept as a dynamic support and resistance level, entering long positions when price bounces off the rising intercept line and shorting when price fails at a declining intercept. The mathematical rigor of least squares regression ensures the intercept represents the statistically optimal trend estimate, making it particularly valuable for systematic trading strategies that require precise, reproducible entry and exit levels based on mathematical rather than subjective analysis.

Implementation Examples

Compute Linear Regression Intercept in a few lines:

use vectorta::indicators::linearreg_intercept::{linearreg_intercept, LinearRegInterceptInput, LinearRegInterceptParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};

// From a price slice
let prices = vec![100.0, 102.0, 101.5, 103.0, 105.0, 104.5];
let params = LinearRegInterceptParams { period: Some(14) };
let input = LinearRegInterceptInput::from_slice(&prices, params);
let result = linearreg_intercept(&input)?;

// From Candles with defaults (period=14, source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = LinearRegInterceptInput::with_default_candles(&candles);
let result = linearreg_intercept(&input)?;

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

API Reference

Input Methods
// From price slice
LinearRegInterceptInput::from_slice(&[f64], LinearRegInterceptParams) -> LinearRegInterceptInput

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

// From candles with defaults (source="close", period=14)
LinearRegInterceptInput::with_default_candles(&Candles) -> LinearRegInterceptInput
Parameters Structure
#[derive(Debug, Clone)]
pub struct LinearRegInterceptParams {
    pub period: Option<usize>, // Default: 14
}
Output Structure
#[derive(Debug, Clone)]
pub struct LinearRegInterceptOutput {
    pub values: Vec<f64>, // fitted value at last bar per window; NaN during warmup
}
Validation, Warmup & NaNs
  • period > 0 and period ≤ len(data); otherwise LinearRegInterceptError::InvalidPeriod.
  • Requires at least period valid points after the first finite value; otherwise LinearRegInterceptError::NotEnoughValidData.
  • Indices before first_valid + period - 1 are NaN. For period=1, values pass through after the first finite input.
  • Empty slice → LinearRegInterceptError::InputDataSliceEmpty; all-NaN input → LinearRegInterceptError::AllValuesNaN.
Error Handling
use vectorta::indicators::linearreg_intercept::{linearreg_intercept, LinearRegInterceptError};

match linearreg_intercept(&input) {
    Ok(output) => process(output.values),
    Err(LinearRegInterceptError::InputDataSliceEmpty) =>
        eprintln!("Input data slice is empty"),
    Err(LinearRegInterceptError::AllValuesNaN) =>
        eprintln!("All input values are NaN"),
    Err(LinearRegInterceptError::InvalidPeriod { period, data_len }) =>
        eprintln!("Invalid period: {} (data_len={})", period, data_len),
    Err(LinearRegInterceptError::NotEnoughValidData { needed, valid }) =>
        eprintln!("Need {} valid points, found {}", needed, valid),
    Err(LinearRegInterceptError::OutputLengthMismatch { dst, src }) =>
        eprintln!("Destination len {} != source len {}", dst, src),
}

Python Bindings

Basic Usage

Compute Linear Regression Intercept from NumPy arrays (default period=14):

import numpy as np
from vectorta import linearreg_intercept

prices = np.array([100.0, 101.5, 103.0, 102.2, 104.7], dtype=float)

# Defaults
out = linearreg_intercept(prices, period=14)

# Optional kernel: "auto", "avx2", "avx512"
out = linearreg_intercept(prices, period=20, kernel="auto")

print(out[-5:])
Streaming Real-time Updates

Update an LRI stream per tick:

from vectorta import LinearRegInterceptStream

stream = LinearRegInterceptStream(14)
for price in price_feed:
    v = stream.update(price)
    if v is not None:
        handle(v)
Batch Parameter Sweep

Test multiple periods:

import numpy as np
from vectorta import linearreg_intercept_batch

prices = np.array([...], dtype=float)
res = linearreg_intercept_batch(
    prices,
    period_range=(5, 30, 5),
    kernel="auto",
)

# res is a dict: values (flat), combos, rows, cols
print(res["rows"], res["cols"])
CUDA Acceleration

CUDA support for Linear Regression Intercept is coming soon. APIs will mirror other CUDA-enabled indicators.

# Coming soon: CUDA-accelerated Linear Regression Intercept
# from vectorta import linearreg_intercept_cuda_batch, linearreg_intercept_cuda_many_series_one_param
# import numpy as np

# # Option 1: One Series, Many Parameters
# res = linearreg_intercept_cuda_batch(
#     data=prices,
#     period_range=(5, 30, 1),
#     device_id=0,
# )

# # Option 2: Many Series, One Parameter Set
# data_tm = np.array([...])  # [T, N]
# res = linearreg_intercept_cuda_many_series_one_param(
#     data_tm=data_tm,
#     period=14,
#     device_id=0,
# )

JavaScript/WASM Bindings

Basic Usage

Calculate Linear Regression Intercept in JavaScript/TypeScript:

import { linearreg_intercept_js } from 'vectorta-wasm';

const prices = new Float64Array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5]);
const period = 14;
const result = linearreg_intercept_js(prices, period);
console.log('LRI values:', result);
Memory-Efficient Operations

Use zero-copy operations for large datasets:

import { linearreg_intercept_alloc, linearreg_intercept_free, linearreg_intercept_into, memory } from 'vectorta-wasm';

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

const inPtr = linearreg_intercept_alloc(len);
const outPtr = linearreg_intercept_alloc(len);

new Float64Array(memory.buffer, inPtr, len).set(prices);

// Args: in_ptr, out_ptr, len, period
linearreg_intercept_into(inPtr, outPtr, len, 14);

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

linearreg_intercept_free(inPtr, len);
linearreg_intercept_free(outPtr, len);

console.log(values.slice(-5));
Batch Processing

Compute multiple periods in a single call:

import { linearreg_intercept_batch } from 'vectorta-wasm';

const prices = new Float64Array([/* historical prices */]);
const config = { period_range: [5, 30, 5] }; // start, end, step

const out = linearreg_intercept_batch(prices, config);
// out: { values: Float64Array, combos: Array, rows: number, cols: number }
console.log(out.rows, out.cols);

Performance Analysis

Comparison:
View:

Across sizes, Rust CPU runs about 1.02× slower than Tulip C in this benchmark.

Loading chart...

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

CUDA note

In our benchmark workload, the Rust CPU implementation is faster than CUDA for this indicator. Prefer the Rust/CPU path unless your workload differs.

Related Indicators