Linear Regression Angle (LRA)
period = 14 Overview
The Linear Regression Angle transforms the abstract concept of trend slope into intuitive degrees that traders can instantly visualize, where steep positive angles reveal powerful uptrends while negative angles expose bearish momentum, creating a universal language for trend strength across all markets and timeframes. By fitting a least squares regression line through recent price data and converting its slope to degrees using arctangent, the indicator produces values typically ranging from -45° to +45° during normal trends, with extreme readings beyond these levels signaling unsustainable price acceleration. Angles above 30° indicate strong bullish momentum where prices rise faster than sustainable norms, suggesting either trend continuation opportunities or approaching exhaustion depending on duration. Conversely, angles below -30° reveal intense selling pressure that often marks either capitulation bottoms or the acceleration phase of downtrends. The genius of expressing trends in degrees rather than raw slope values lies in the immediate visual understanding it provides, as traders intuitively grasp that a 45° angle represents prices rising one unit for each time unit, while 0° shows pure sideways movement. Momentum traders particularly value this indicator for timing entries during angle acceleration phases and exits when angles flatten, as changes in angle steepness often precede actual price reversals by revealing when trends lose their directional conviction.
Implementation Examples
Get LRA in a few lines:
use vectorta::indicators::linearreg_angle::{linearreg_angle, Linearreg_angleInput, Linearreg_angleParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using with a price slice
let prices = vec![100.0, 101.0, 102.5, 101.8, 103.2, 104.1];
let params = Linearreg_angleParams { period: Some(14) };
let input = Linearreg_angleInput::from_slice(&prices, params);
let result = linearreg_angle(&input)?;
// Using with Candles (defaults: period=14, source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = Linearreg_angleInput::with_default_candles(&candles);
let result = linearreg_angle(&input)?;
// Access the angle values (degrees)
for angle in result.values { println!("angle: {}°", angle); } API Reference
Input Methods ▼
// From price slice
Linearreg_angleInput::from_slice(&[f64], Linearreg_angleParams) -> Linearreg_angleInput
// From candles with custom source
Linearreg_angleInput::from_candles(&Candles, &str, Linearreg_angleParams) -> Linearreg_angleInput
// From candles with default params (close prices, period=14)
Linearreg_angleInput::with_default_candles(&Candles) -> Linearreg_angleInput Parameters Structure ▼
pub struct Linearreg_angleParams {
pub period: Option<usize>, // Default: 14
} Output Structure ▼
pub struct Linearreg_angleOutput {
pub values: Vec<f64>, // Angles in degrees (NaN during warmup)
} Validation, Warmup & NaNs ▼
period ≥ 2;period ≤ data.len().- Must have at least
periodvalid values after the first finite input; otherwiseLinearreg_angleError::NotEnoughValidData. - Indices before
first + period − 1areNaN(warmup). - Angle values are typically within
[−90°, 90°]; constant data produces ~0°. Linearreg_angleError::EmptyDatawhen input is empty;AllValuesNaNwhen no finite values.
Error Handling ▼
use vectorta::indicators::linearreg_angle::{linearreg_angle, Linearreg_angleError};
match linearreg_angle(&input) {
Ok(output) => handle(output.values),
Err(Linearreg_angleError::EmptyData) =>
eprintln!("Input data is empty"),
Err(Linearreg_angleError::AllValuesNaN) =>
eprintln!("All values are NaN"),
Err(Linearreg_angleError::InvalidPeriod { period, data_len }) =>
eprintln!("Invalid period {} for length {}", period, data_len),
Err(Linearreg_angleError::NotEnoughValidData { needed, valid }) =>
eprintln!("Need {} valid points, only {} available", needed, valid),
Err(Linearreg_angleError::OutputLengthMismatch { expected, actual }) =>
eprintln!("Into-slice expected {}, got {}", expected, actual),
Err(e) => eprintln!("LRA error: {}", e),
} Python Bindings
Basic Usage ▼
Calculate LRA using NumPy arrays (default period=14):
import numpy as np
from vectorta import linearreg_angle
prices = np.array([100.0, 101.0, 102.5, 101.8, 103.2, 104.1])
# Default period (14)
angles = linearreg_angle(prices)
# Custom parameters and kernel
angles = linearreg_angle(prices, period=20, kernel="avx2")
print(angles) # NumPy array of degrees Streaming Real-time Updates ▼
from vectorta import Linearreg_angleStream
stream = Linearreg_angleStream(period=14)
for price in price_feed:
angle = stream.update(price)
if angle is not None:
print(f"angle: {angle}°") Batch Parameter Optimization ▼
Test multiple periods efficiently:
import numpy as np
from vectorta import linearreg_angle_batch
prices = np.array([...], dtype=float)
# period_range = (start, end, step)
res = linearreg_angle_batch(prices, period_range=(5, 30, 5), kernel="auto")
print(res['values'].shape) # (rows, cols)
print(res['periods']) # list of tested periods CUDA Acceleration ▼
CUDA support for Linear Regression Angle is currently under development.
JavaScript / WASM
Basic Setup ▼
import { linearreg_angle_js } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const period = 14;
const angles = linearreg_angle_js(prices, period);
console.log('angles (deg):', angles); Memory-Efficient Operations ▼
Use zero-copy style APIs for large arrays:
import { linearreg_angle_alloc, linearreg_angle_free, linearreg_angle_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const n = prices.length;
const inPtr = linearreg_angle_alloc(n);
const outPtr = linearreg_angle_alloc(n);
new Float64Array(memory.buffer, inPtr, n).set(prices);
// Args: in_ptr, out_ptr, len, period
linearreg_angle_into(inPtr, outPtr, n, 14);
const out = new Float64Array(memory.buffer, outPtr, n).slice();
linearreg_angle_free(inPtr, n);
linearreg_angle_free(outPtr, n);
console.log(out); Batch Processing ▼
Sweep multiple periods via a config object:
import { linearreg_angle_batch_js } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
const config = { period_range: [5, 30, 5] };
const res = linearreg_angle_batch_js(prices, config);
// Response: { values: Float64Array, combos: [{ period: 5 }, ...], rows, cols }
const { values, combos, rows, cols } = res;
// Reshape flat values into row-major matrix
const matrix: number[][] = [];
for (let r = 0; r < rows; r++) {
const start = r * cols;
matrix.push(Array.from(values.slice(start, start + cols)));
}
// Map row index -> period
const periods = combos.map(c => c.period);
console.log(periods, matrix[0]); Performance Analysis
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05