Linear Regression Intercept (LINEARREG_INTERCEPT)
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 > 0andperiod ≤ len(data); otherwiseLinearRegInterceptError::InvalidPeriod.- Requires at least
periodvalid points after the first finite value; otherwiseLinearRegInterceptError::NotEnoughValidData. - Indices before
first_valid + period - 1areNaN. Forperiod=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
Across sizes, Rust CPU runs about 1.02× slower than Tulip C in this benchmark.
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.