Random Walk Index

Parameters: length = 14

Overview

Random Walk Index asks whether recent price movement is stronger than what a random-walk process would be expected to produce over the same number of bars. VectorTA calculates separate high and low series by comparing the current high and low against historical extremes, then normalizing that distance with an ATR estimate scaled by the square root of the lookback.

The result is a two-line trend-strength study rather than a single oscillator. Higher high-line readings indicate upside movement with more directional persistence than a random drift, while higher low-line readings indicate the same on the downside. VectorTA supports candle input, explicit high-low-close slices, streaming updates, and a one-axis batch sweep over the length parameter.

Defaults: `length = 14`.

Implementation Examples

Run the indicator from candles or from explicit high, low, and close slices.

use vector_ta::indicators::random_walk_index::{
    random_walk_index,
    RandomWalkIndexInput,
    RandomWalkIndexParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};

let direct = random_walk_index(&RandomWalkIndexInput::from_slices(
    &high,
    &low,
    &close,
    RandomWalkIndexParams {
        length: Some(14),
    },
))?;

let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let from_candles = random_walk_index(&RandomWalkIndexInput::with_default_candles(&candles))?;

println!("rwi high = {:?}", direct.high.last());
println!("rwi low = {:?}", from_candles.low.last());

API Reference

Input Methods
RandomWalkIndexInput::from_candles(&Candles, RandomWalkIndexParams)
    -> RandomWalkIndexInput

RandomWalkIndexInput::from_slices(&[f64], &[f64], &[f64], RandomWalkIndexParams)
    -> RandomWalkIndexInput

RandomWalkIndexInput::with_default_candles(&Candles)
    -> RandomWalkIndexInput
Parameters Structure
pub struct RandomWalkIndexParams {
    pub length: Option<usize>, // default 14
}
Output Structure
pub struct RandomWalkIndexOutput {
    pub high: Vec<f64>,
    pub low: Vec<f64>,
}
Validation & Warmup
  • High, low, and close slices must all be non-empty, equal in length, and contain at least one valid triple.
  • length must be greater than 0 and no larger than the data length.
  • The vector path requires at least length valid bars after the first usable triple.
  • Warmup begins at first_valid + length - 1, so earlier entries remain NaN.
  • The stream path returns (NaN, NaN) until enough data has accumulated.
  • Batch mode validates the length sweep and rejects non-batch kernels.
Builder, Streaming & Batch APIs
RandomWalkIndexBuilder::new()
    .length(usize)
    .kernel(Kernel)
    .apply(&Candles)
    .apply_slices(&[f64], &[f64], &[f64])
    .into_stream()

RandomWalkIndexStream::try_new(params)
stream.update(high, low, close) -> (f64, f64)

RandomWalkIndexBatchBuilder::new()
    .length_range((start, end, step))
    .kernel(Kernel)
    .apply_candles(&Candles)
    .apply_slices(&[f64], &[f64], &[f64])

Python Bindings

Python exposes a scalar function returning two NumPy arrays, a streaming class returning the latest high and low RWI values, and a batch helper that returns reshaped matrices plus the resolved length axis.

from vector_ta import (
    random_walk_index,
    random_walk_index_batch,
    RandomWalkIndexStream,
)

single = random_walk_index(high, low, close, length=14)

stream = RandomWalkIndexStream(length=14)
point = stream.update(high[-1], low[-1], close[-1])

batch = random_walk_index_batch(
    high,
    low,
    close,
    length_range=(10, 20, 5),
)

print(single["high"][-1], single["low"][-1])
print(batch["lengths"])

JavaScript/WASM Bindings

The WASM layer exposes object-returning scalar and batch helpers plus allocation and into-buffer functions for caller-managed memory.

import init, {
  random_walk_index_js,
  random_walk_index_batch_js,
  random_walk_index_alloc,
  random_walk_index_free,
  random_walk_index_into,
  random_walk_index_batch_into,
} from "vector-ta-wasm";

await init();

const single = random_walk_index_js(high, low, close, 14);

const batch = random_walk_index_batch_js(high, low, close, {
  length_range: [10, 20, 5],
});

const ptrHigh = random_walk_index_alloc(high.length);
const ptrLow = random_walk_index_alloc(low.length);
const ptrClose = random_walk_index_alloc(close.length);
const ptrOutHigh = random_walk_index_alloc(close.length);
const ptrOutLow = random_walk_index_alloc(close.length);
random_walk_index_into(ptrHigh, ptrLow, ptrClose, ptrOutHigh, ptrOutLow, close.length, 14);
random_walk_index_free(ptrHigh, high.length);
random_walk_index_free(ptrLow, low.length);
random_walk_index_free(ptrClose, close.length);
random_walk_index_free(ptrOutHigh, close.length);
random_walk_index_free(ptrOutLow, close.length);

console.log(single.high, single.low, 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