AlphaTrend (AT)

Parameters: coeff = 1 | period = 14 | no_volume =

Overview

AlphaTrend generates dynamic support and resistance levels that adapt to market conditions by combining ATR based volatility bands with momentum filters from either MFI or RSI. The indicator constructs upper and lower bands around price using ATR multiplied by a coefficient, then selects which band becomes the active trend line based on whether momentum exceeds 50. When MFI or RSI rises above 50, AlphaTrend switches to the lower band as support; below 50, it flips to the upper band as resistance. This creates a trailing stop loss line that tightens during strong trends and loosens during consolidations. Traders use AlphaTrend to identify trend direction when price crosses the line, ride trends with the line as a dynamic stop, and spot potential reversals when price repeatedly tests but fails to break through. The indicator outputs both the current trend line and a two bar lagged version, allowing confirmation of crossover signals.

Implementation Examples

Compute AlphaTrend from OHLCV candles or raw slices:

use vectorta::indicators::alphatrend::{alphatrend, AlphaTrendInput, AlphaTrendParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};

// From OHLCV slices (MFI by default; set no_volume=true to use RSI)
let open = vec![/* ... */];
let high = vec![/* ... */];
let low = vec![/* ... */];
let close = vec![/* ... */];
let volume = vec![/* ... */];
let params = AlphaTrendParams { coeff: Some(1.0), period: Some(14), no_volume: Some(false) };
let input = AlphaTrendInput::from_slices(&open, &high, &low, &close, &volume, params);
let out = alphatrend(&input)?; // out.k1 (current), out.k2 (lagged by 2)

// From Candles with defaults (coeff=1.0, period=14, no_volume=false)
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = AlphaTrendInput::with_default_candles(&candles);
let out = alphatrend(&input)?;

// Access values
println!("k1_last = {:?}, k2_last = {:?}", out.k1.last(), out.k2.last());

API Reference

Input Methods
// From candles (OHLCV)
AlphaTrendInput::from_candles(&Candles, AlphaTrendParams) -> AlphaTrendInput

// From raw OHLCV slices
AlphaTrendInput::from_slices(&[f64], &[f64], &[f64], &[f64], &[f64], AlphaTrendParams) -> AlphaTrendInput

// With defaults (coeff=1.0, period=14, no_volume=false)
AlphaTrendInput::with_default_candles(&Candles) -> AlphaTrendInput
Parameters Structure
pub struct AlphaTrendParams {
    pub coeff: Option<f64>,   // Default: 1.0 (must be > 0)
    pub period: Option<usize>,// Default: 14 (>= 1)
    pub no_volume: Option<bool>, // Default: false (use MFI)
}
Output Structure
pub struct AlphaTrendOutput {
    pub k1: Vec<f64>, // Current AlphaTrend line
    pub k2: Vec<f64>, // AlphaTrend lagged by 2 bars
}
Validation, Warmup & NaNs
  • len > 0; otherwise AlphaTrendError::EmptyInputData.
  • All slices must match length; otherwise AlphaTrendError::InconsistentDataLengths.
  • First finite close index must exist; otherwise AlphaTrendError::AllValuesNaN.
  • period > 0 and period ≤ len; otherwise AlphaTrendError::InvalidPeriod.
  • Need at least period valid points after the first finite close; otherwise AlphaTrendError::NotEnoughValidData.
  • coeff > 0 and finite; otherwise AlphaTrendError::InvalidCoeff.
  • Warmup: k1[0..first+period-1] are NaN; k2 additionally lags by 2 bars (NaN until warmup+2).
  • Momentum errors propagate as AlphaTrendError::RsiError / AlphaTrendError::MfiError.
Error Handling
use vectorta::indicators::alphatrend::{alphatrend, AlphaTrendError};

match alphatrend(&input) {
    Ok(output) => {
        use_results(output.k1, output.k2);
    }
    Err(AlphaTrendError::EmptyInputData) => handle("empty input"),
    Err(AlphaTrendError::AllValuesNaN) => handle("all NaN"),
    Err(AlphaTrendError::InvalidPeriod { period, data_len }) => handle(&format!("invalid period: {} (len={})", period, data_len)),
    Err(AlphaTrendError::NotEnoughValidData { needed, valid }) => handle(&format!("needed {}, had {}", needed, valid)),
    Err(AlphaTrendError::InconsistentDataLengths) => handle("inconsistent lengths"),
    Err(AlphaTrendError::InvalidCoeff { coeff }) => handle(&format!("invalid coeff: {}", coeff)),
    Err(AlphaTrendError::RsiError { msg }) => handle(&format!("RSI failed: {}", msg)),
    Err(AlphaTrendError::MfiError { msg }) => handle(&format!("MFI failed: {}", msg)),
}

Python Bindings

Compute AlphaTrend
import numpy as np
from vectorta import alphatrend

# OHLCV arrays (float64)
open = np.array([...], dtype=float)
high = np.array([...], dtype=float)
low = np.array([...], dtype=float)
close = np.array([...], dtype=float)
volume = np.array([...], dtype=float)

# coeff=1.0, period=14, no_volume=False (uses MFI); kernel can be "auto", "scalar", "avx2", "avx512"
k1, k2 = alphatrend(open, high, low, close, volume, coeff=1.0, period=14, no_volume=False, kernel="auto")
print(k1[-5:], k2[-5:])
Streaming Real-time Updates

Streaming API exists but update currently returns None (implementation pending).

from vectorta import AlphaTrendStream

stream = AlphaTrendStream(coeff=1.0, period=14, no_volume=False)
for h, l, c, v in ohlcv_stream:
    res = stream.update(h, l, c, v)
    if res is not None:
        k1, k2 = res
        print(k1, k2)
Batch Parameter Optimization
import numpy as np
from vectorta import alphatrend_batch

open = np.array([...], dtype=float)
high = np.array([...], dtype=float)
low = np.array([...], dtype=float)
close = np.array([...], dtype=float)
volume = np.array([...], dtype=float)

coeff_range = (1.0, 2.0, 0.5)   # 1.0, 1.5, 2.0
period_range = (10, 20, 5)      # 10, 15, 20

result = alphatrend_batch(open, high, low, close, volume, coeff_range, period_range, no_volume=False, kernel="auto")
print(result["k1"].shape, result["k2"].shape)  # (rows, len), (rows, len)
print(result["rows"], result["cols"])

JavaScript/WASM Bindings

Basic Usage

Compute AlphaTrend in JS/TS; result flattens k1 then k2 with metadata.

import { alphatrend_js } from 'vectorta-wasm';

const open = new Float64Array([...]);
const high = new Float64Array([...]);
const low = new Float64Array([...]);
const close = new Float64Array([...]);
const volume = new Float64Array([...]);

const js = alphatrend_js(open, high, low, close, volume, 1.0, 14, false);
// js = { values: Float64Array, rows: 2, cols: N }
const N = js.cols;
const k1 = js.values.slice(0, N);
const k2 = js.values.slice(N, 2*N);
Memory-Efficient Operations

Use flat alloc and in-place compute for [k1, k2]:

import { alphatrend_alloc_flat, alphatrend_free_flat, alphatrend_into_flat, memory } from 'vectorta-wasm';

const N = close.length;
const outPtr = alphatrend_alloc_flat(N); // capacity for 2*N doubles

alphatrend_into_flat(openPtr, highPtr, lowPtr, closePtr, volumePtr, outPtr, N, 1.0, 14, false);
const buf = new Float64Array(memory.buffer);
const base = outPtr / Float64Array.BYTES_PER_ELEMENT;
const k1 = buf.slice(base, base + N);
const k2 = buf.slice(base + N, base + 2*N);

alphatrend_free_flat(outPtr, N);
Batch Processing
import { alphatrend_batch_js } from 'vectorta-wasm';

const coeffStart = 1.0, coeffEnd = 2.0, coeffStep = 0.5;
const periodStart = 10, periodEnd = 20, periodStep = 5;
const js = alphatrend_batch_js(open, high, low, close, volume, coeffStart, coeffEnd, coeffStep, periodStart, periodEnd, periodStep, false);
// js = { values: Float64Array, combos: AlphaTrendParams[], rows: 2*combos, cols: N }
const N = js.cols;
// For combo r, values are laid out as [k1_r..., k2_r...] contiguous (block size = 2*N)
const r = 0;
const base = r * 2 * N;
const k1_r = js.values.slice(base, base + N);
const k2_r = js.values.slice(base + N, base + 2*N);

CUDA Acceleration

CUDA Support

CUDA support for AlphaTrend is coming soon.

Performance Analysis

Comparison:
View:
Loading chart...

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

Related Indicators