Leavitt Convolution Acceleration

Parameters: length = 70 | norm_length = 150 | use_norm_hyperbolic = true

Overview

Leavitt Convolution Acceleration produces two aligned outputs: a continuous convolution-acceleration value and a discrete signal state. The implementation projects the source through a rolling linear regression, measures the slope of that projection across a shorter square-root window, normalizes the slope with a rolling mean and standard deviation, and then derives acceleration from the change in the normalized value.

When hyperbolic normalization is enabled, the normalized slope is mapped with a hyperbolic transform and the signal uses the raw acceleration slope. When it is disabled, the normalized slope is mapped with a logistic transform and the signal instead uses the change in acceleration. Candle input defaults to the hlcc4 source, and the builder allows that candle source to be overridden.

Defaults: length = 70, norm_length = 150, use_norm_hyperbolic = true, candle source "hlcc4".

Implementation Examples

Calculate the acceleration and signal series from a slice or from candles:

use vector_ta::indicators::leavitt_convolution_acceleration::{
    leavitt_convolution_acceleration, LeavittConvolutionAccelerationInput,
    LeavittConvolutionAccelerationParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};

let data = vec![100.0, 101.2, 102.4, 101.9, 103.5, 104.1, 103.8, 105.0];
let input = LeavittConvolutionAccelerationInput::from_slice(
    &data,
    LeavittConvolutionAccelerationParams {
        length: Some(70),
        norm_length: Some(150),
        use_norm_hyperbolic: Some(true),
    },
);
let out = leavitt_convolution_acceleration(&input)?;
println!("{:?}", out.conv_acceleration);
println!("{:?}", out.signal);

// Default candles helper uses source = "hlcc4"
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let out = leavitt_convolution_acceleration(
    &LeavittConvolutionAccelerationInput::with_default_candles(&candles),
)?;

API Reference

Input Methods
LeavittConvolutionAccelerationInput::from_candles(&Candles, &str, LeavittConvolutionAccelerationParams) -> LeavittConvolutionAccelerationInput
LeavittConvolutionAccelerationInput::from_slice(&[f64], LeavittConvolutionAccelerationParams) -> LeavittConvolutionAccelerationInput
LeavittConvolutionAccelerationInput::with_default_candles(&Candles) -> LeavittConvolutionAccelerationInput // source = "hlcc4"
Parameters Structure
pub struct LeavittConvolutionAccelerationParams {
    pub length: Option<usize>,
    pub norm_length: Option<usize>,
    pub use_norm_hyperbolic: Option<bool>,
}

// Defaults
// length = 70
// norm_length = 150
// use_norm_hyperbolic = true
Output Structure
pub struct LeavittConvolutionAccelerationOutput {
    pub conv_acceleration: Vec<f64>,
    pub signal: Vec<f64>,
}

// signal values:
//  2.0 = positive acceleration strengthening
//  1.0 = positive acceleration present
//  0.0 = neutral
// -1.0 = negative acceleration present
// -2.0 = negative acceleration strengthening
Builders, Batch Range, and Stream
  • LeavittConvolutionAccelerationBuilder::new() exposes length(), norm_length(), use_norm_hyperbolic(), source(), kernel(), apply(), apply_slice(), and into_stream().
  • LeavittConvolutionAccelerationStream::update(value) returns Option<(f64, f64)> for (conv_acceleration, signal).
  • reset() clears all rolling states and source-history state.
  • LeavittConvolutionAccelerationBatchRange contains length, norm_length, and optional use_norm_hyperbolic.
  • LeavittConvolutionAccelerationBatchBuilder::new() exposes length_range(), length_static(), norm_length_range(), norm_length_static(), use_norm_hyperbolic(), kernel(), apply_slice(), and apply_candles().
  • Batch output is LeavittConvolutionAccelerationBatchOutput with flattened row-major conv_acceleration and signal vectors plus combos, rows, and cols.
Validation, Warmup & NaNs
  • Input must be non-empty and contain at least one finite source value; otherwise the indicator returns EmptyInputData or AllValuesNaN.
  • length and norm_length must both be greater than zero and not exceed the input length.
  • Single-run validation requires at least length + floor(sqrt(length)) + norm_length - 2 finite values from the first valid source onward.
  • Single-output warmup fills values before first_valid + length + floor(sqrt(length)) + norm_length - 3 with NaN.
  • Streaming resets to empty state on non-finite input and returns None until all rolling stages are ready again.
  • When use_norm_hyperbolic = false, normalization uses a logistic transform and the signal slope is the change in acceleration instead of the raw acceleration slope.
Error Handling
use vector_ta::indicators::leavitt_convolution_acceleration::LeavittConvolutionAccelerationError;

match leavitt_convolution_acceleration(&input) {
    Ok(out) => {
        println!("{:?}", out.conv_acceleration);
        println!("{:?}", out.signal);
    }
    Err(LeavittConvolutionAccelerationError::EmptyInputData) =>
        eprintln!("input data cannot be empty"),
    Err(LeavittConvolutionAccelerationError::AllValuesNaN) =>
        eprintln!("all source values were invalid"),
    Err(LeavittConvolutionAccelerationError::InvalidLength { length, data_len }) =>
        eprintln!("invalid length {} for data len {}", length, data_len),
    Err(LeavittConvolutionAccelerationError::InvalidNormLength { norm_length, data_len }) =>
        eprintln!("invalid norm_length {} for data len {}", norm_length, data_len),
    Err(LeavittConvolutionAccelerationError::NotEnoughValidData { needed, valid }) =>
        eprintln!("need {} valid points, only {} available", needed, valid),
    Err(LeavittConvolutionAccelerationError::InvalidKernelForBatch(kernel)) =>
        eprintln!("invalid batch kernel: {:?}", kernel),
    Err(e) => eprintln!("Leavitt Convolution Acceleration error: {}", e),
}

Python Bindings

Basic Usage

Python exposes leavitt_convolution_acceleration(data, length=70, norm_length=150, use_norm_hyperbolic=True, kernel=None) and returns a tuple of NumPy arrays.

import numpy as np
from vector_ta import leavitt_convolution_acceleration

data = np.array([100.0, 101.2, 102.4, 101.9, 103.5, 104.1], dtype=np.float64)
conv_acceleration, signal = leavitt_convolution_acceleration(
    data,
    length=70,
    norm_length=150,
    use_norm_hyperbolic=True,
)
Streaming Real-time Updates

The Python stream class is LeavittConvolutionAccelerationStream. Its update(value) method returns either (conv_acceleration, signal) or None.

from vector_ta import LeavittConvolutionAccelerationStream

stream = LeavittConvolutionAccelerationStream(
    length=70,
    norm_length=150,
    use_norm_hyperbolic=True,
)

for value in feed:
    out = stream.update(value)
    if out is not None:
        conv_acceleration, signal = out
        print(conv_acceleration, signal)
Batch Processing

leavitt_convolution_acceleration_batch returns a dict with both 2D outputs and grid metadata.

import numpy as np
from vector_ta import leavitt_convolution_acceleration_batch

result = leavitt_convolution_acceleration_batch(
    data,
    length_range=(50, 70, 20),
    norm_length_range=(100, 150, 50),
    use_norm_hyperbolic=True,
)

conv_acceleration = result["conv_acceleration"]
signal = result["signal"]
rows = result["rows"]
cols = result["cols"]
lengths = result["lengths"]
norm_lengths = result["norm_lengths"]
use_norm_hyperbolic = result["use_norm_hyperbolic"]

JavaScript/WASM Bindings

Basic Usage

WASM exports leavitt_convolution_acceleration_js(data, length, norm_length, use_norm_hyperbolic) and returns an object with both output arrays.

import { leavitt_convolution_acceleration_js } from 'vectorta-wasm';

const data = new Float64Array([100.0, 101.2, 102.4, 101.9, 103.5, 104.1]);
const out = leavitt_convolution_acceleration_js(data, 70, 150, true);

console.log(out.conv_acceleration);
console.log(out.signal);
Memory-Efficient Operations

Use leavitt_convolution_acceleration_alloc together with ..._into or ..._into_host to write both outputs into a caller-managed buffer of length len * 2.

import {
  leavitt_convolution_acceleration_alloc,
  leavitt_convolution_acceleration_free,
  leavitt_convolution_acceleration_into_host,
  memory,
} from 'vectorta-wasm';

const len = data.length;
const outPtr = leavitt_convolution_acceleration_alloc(len);

leavitt_convolution_acceleration_into_host(data, outPtr, 70, 150, true);

const flat = new Float64Array(memory.buffer, outPtr, len * 2);
const convAcceleration = flat.slice(0, len);
const signal = flat.slice(len, len * 2);

leavitt_convolution_acceleration_free(outPtr, len);
Batch Processing

WASM batch uses leavitt_convolution_acceleration_batch_js with length and normalization ranges and returns both row-major outputs plus combo metadata.

import { leavitt_convolution_acceleration_batch_js } from 'vectorta-wasm';

const batch = leavitt_convolution_acceleration_batch_js(data, {
  length_range: [50, 70, 20],
  norm_length_range: [100, 150, 50],
  use_norm_hyperbolic: true,
});

console.log(batch.conv_acceleration);
console.log(batch.signal);
console.log(batch.rows, batch.cols);
console.log(batch.combos);

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