Advance/Decline Line (ADL)

Overview

The Advance/Decline Line is one of the simplest breadth tools in technical analysis: it cumulatively sums each period's net breadth reading and turns that sequence into a running participation line. When the line rises alongside price, breadth is broadly supporting the move. When price keeps advancing while the line flattens or rolls over, participation is thinning and the move is becoming more selective.

In the VectorTA implementation, the core input is a single numeric stream. Used classically, that stream should already be your net advance-minus-decline series. The candle helper is also available, but it simply cumulates the chosen candle field rather than deriving market breadth on its own. Non-finite values break the cumulative segment and cause the next valid value to start a fresh running total.

Defaults: Advance/Decline Line uses no configurable parameters.

Implementation Examples

Feed the indicator a precomputed breadth series, or use a candle field when you explicitly want a cumulative line of that source.

use vector_ta::indicators::advance_decline_line::{
    advance_decline_line,
    AdvanceDeclineLineInput,
    AdvanceDeclineLineParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};

let breadth = vec![12.0, -5.0, 18.0, 7.0, -9.0, 4.0];

let output = advance_decline_line(
    &AdvanceDeclineLineInput::from_slice(&breadth, AdvanceDeclineLineParams)
)?;

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

println!("ADL values: {:?}", output.values);
println!("Latest candle cumulative value: {:?}", candle_output.values.last());

API Reference

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

// From a precomputed breadth slice
AdvanceDeclineLineInput::from_slice(&[f64], AdvanceDeclineLineParams)
    -> AdvanceDeclineLineInput

// From candles with the default source field
AdvanceDeclineLineInput::with_default_candles(&Candles)
    -> AdvanceDeclineLineInput
Parameters Structure
pub struct AdvanceDeclineLineParams;

// No configurable parameters.
Output Structure
pub struct AdvanceDeclineLineOutput {
    pub values: Vec<f64>,
}
Validation, Warmup & NaNs
  • An empty slice returns EmptyInputData.
  • If every input value is non-finite, the function returns AllValuesNaN.
  • Warmup is zero after the first finite value, because the line starts accumulating immediately.
  • Leading non-finite values are preserved as NaN in the output.
  • Any non-finite value inside the series writes NaN at that index and resets the cumulative segment, so the next finite value starts a fresh running total.
  • Batch mode only accepts batch-capable kernels in advance_decline_line_batch_with_kernel; otherwise it returns InvalidKernelForBatch.
Builder, Streaming & Batch APIs
// Builder
AdvanceDeclineLineBuilder::new()
    .kernel(Kernel)
    .apply_slice(&[f64])

AdvanceDeclineLineBuilder::new()
    .kernel(Kernel)
    .apply(&Candles, &str)

AdvanceDeclineLineBuilder::new()
    .into_stream()

// Stream
AdvanceDeclineLineStream::try_new()
AdvanceDeclineLineStream::update(f64) -> Option<f64>
AdvanceDeclineLineStream::get_warmup_period() -> usize

// Batch
AdvanceDeclineLineBatchBuilder::new()
    .kernel(Kernel)
    .apply_slice(&[f64])

AdvanceDeclineLineBatchBuilder::new()
    .apply_candles(&Candles, &str)
Error Handling
pub enum AdvanceDeclineLineError {
    EmptyInputData,
    AllValuesNaN,
    OutputLengthMismatch { expected: usize, got: usize },
    InvalidRange { start: String, end: String, step: String },
    InvalidKernelForBatch(Kernel),
}

Python Bindings

Python exposes a single-run function, a streaming class, and a batch function. The single-run call returns one NumPy array of cumulative values. Batch returns a dictionary with a single 2D values matrix plus rows and cols, since there are no parameter sweeps. The streaming class returns the updated cumulative value whenever the input is finite and resets on non-finite values.

import numpy as np
from vector_ta import (
    advance_decline_line,
    advance_decline_line_batch,
    AdvanceDeclineLineStream,
)

data = np.asarray([12.0, -5.0, 18.0, 7.0, -9.0, 4.0], dtype=np.float64)

values = advance_decline_line(data, kernel="auto")
print(values)

batch = advance_decline_line_batch(data, kernel="auto")
print(batch["values"], batch["rows"], batch["cols"])

stream = AdvanceDeclineLineStream()
for value in data:
    print(stream.update(value))

JavaScript/WASM Bindings

The WASM layer offers both the simple JavaScript wrapper and the raw pointer-based functions. The easiest entry point is advance_decline_line_js, which returns a typed array of cumulative values. If you need to manage buffers directly, the module also exposes allocation, free, and in-place functions for both single-run and batch paths.

import init, {
  advance_decline_line_js,
  advance_decline_line_batch_js,
} from "/pkg/vector_ta.js";

await init();

const data = new Float64Array([12, -5, 18, 7, -9, 4]);

const values = advance_decline_line_js(data);
console.log(values);

const batch = advance_decline_line_batch_js(data, {});
console.log(batch.values, 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