Williams Accumulation/Distribution (WAD)
Overview
Larry Williams developed the Accumulation/Distribution indicator in the 1970s to measure buying and selling pressure using pure price action without requiring volume data, making it universally applicable across all markets. The indicator accumulates values based on the relationship between consecutive closes and their true ranges, adding positive values when price closes higher than the previous bar and negative values when it closes lower. Williams specifically designed this indicator to identify divergences between price action and internal market strength, believing that distribution occurs when price makes new highs but the indicator fails to confirm them. His remarkable trading success, including turning $10,000 into over $1,100,000 in the 1987 World Cup Championship of Futures Trading, lent credibility to his technical analysis methods. Unlike the volume-based Chaikin Accumulation/Distribution, Williams' version focuses solely on price relationships, using true high and true low calculations that can reveal hidden weakness or strength when price extremes don't align with indicator extremes. Traders primarily watch for divergences where price makes new highs or lows that WAD fails to confirm, signaling potential reversals as smart money accumulates during apparent weakness or distributes during apparent strength.
Implementation Examples
Compute WAD from slices or candles:
use vectorta::indicators::wad::{wad, WadError, WadInput, WadParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// From high/low/close slices
let high = vec![10.0, 11.0, 11.0, 12.0];
let low = vec![ 9.0, 9.0, 10.0, 10.0];
let close= vec![ 9.5, 10.5, 10.5, 11.5];
let input = WadInput::from_slices(&high, &low, &close);
let out = wad(&input)?; // WadOutput { values: Vec<f64> }
// From candles (defaults to high/low/close sources)
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = WadInput::from_candles(&candles);
let out = wad(&input)?; API Reference
Input Methods ▼
// From candles (uses high/low/close)
WadInput::from_candles(&Candles) -> WadInput
// From explicit high/low/close slices
WadInput::from_slices(&[f64], &[f64], &[f64]) -> WadInput
// Convenience (same as from_candles)
WadInput::with_default_candles(&Candles) -> WadInput Parameters Structure ▼
pub struct WadParams; // No parameters Output Structure ▼
pub struct WadOutput {
pub values: Vec<f64>, // cumulative WAD values
} Validation, Warmup & NaNs ▼
- Inputs must be non-empty and equal length; otherwise
WadError::EmptyData. - If all values in any of the three inputs are
NaN→WadError::AllValuesNaN. - Warmup:
values[0] = 0.0; accumulation starts at index 1 using the previous close. - Kernel:
wad(...)usesKernel::Auto; builders allowKernel::Scalar,Avx2,Avx512(if compiled). - Streaming:
WadStream::update(h,l,c)returns the cumulative value each tick; first update returns0.0.
Error Handling ▼
use vectorta::indicators::wad::{wad, WadError, WadInput};
match wad(&input) {
Ok(output) => process_results(output.values),
Err(WadError::EmptyData) => eprintln!("wad: empty or mismatched input"),
Err(WadError::AllValuesNaN) => eprintln!("wad: all inputs are NaN"),
Err(WadError::InvalidKernel) => eprintln!("wad: invalid batch kernel for batch API"),
} Python Bindings
Basic Usage ▼
import numpy as np
from vectorta import wad
high = np.array([10.0, 11.0, 11.0, 12.0], dtype=float)
low = np.array([ 9.0, 9.0, 10.0, 10.0], dtype=float)
close= np.array([ 9.5, 10.5, 10.5, 11.5], dtype=float)
# One-shot calculation (kernel optional: 'auto', 'scalar', 'avx2', 'avx512' if available)
values = wad(high, low, close, kernel='auto')
print(values) Streaming ▼
import numpy as np
from vectorta import WadStream
stream = WadStream()
for h, l, c in zip(high, low, close):
val = stream.update(h, l, c)
handle(val) Batch ▼
import numpy as np
from vectorta import wad_batch
res = wad_batch(high, low, close, kernel='auto')
# res is a dict with 'values' shaped [1, len]
values = res['values'][0] # first/only row
print(values) CUDA Acceleration ▼
If built with CUDA support, a device API is available:
import numpy as np
from vectorta import wad_cuda_dev
# Float32 inputs recommended for device APIs
high32 = high.astype(np.float32)
low32 = low.astype(np.float32)
close32= close.astype(np.float32)
dev_arr = wad_cuda_dev(high32, low32, close32, device_id=0)
# dev_arr is a device-backed array wrapper; transfer or use per your pipeline JavaScript/WASM Bindings
Basic Usage ▼
Compute WAD in JavaScript/TypeScript:
import { wad_js } from 'vectorta-wasm';
const high = new Float64Array([/* ... */]);
const low = new Float64Array([/* ... */]);
const close= new Float64Array([/* ... */]);
const values = wad_js(high, low, close);
console.log('WAD:', values); Memory-Efficient Operations ▼
Use zero-copy into/alloc for large datasets:
import { wad_alloc, wad_free, wad_into, memory } from 'vectorta-wasm';
const len = close.length;
const highPtr = wad_alloc(len);
const lowPtr = wad_alloc(len);
const closePtr= wad_alloc(len);
const outPtr = wad_alloc(len);
new Float64Array(memory.buffer, highPtr, len).set(high);
new Float64Array(memory.buffer, lowPtr, len).set(low);
new Float64Array(memory.buffer, closePtr,len).set(close);
// Args: high_ptr, low_ptr, close_ptr, out_ptr, len
wad_into(highPtr, lowPtr, closePtr, outPtr, len);
const values = new Float64Array(memory.buffer, outPtr, len).slice();
wad_free(highPtr, len); wad_free(lowPtr, len);
wad_free(closePtr, len); wad_free(outPtr, len); Batch Processing ▼
Unified batch API (returns a flat array and matrix dims):
import { wad_batch_unified_js } from 'vectorta-wasm';
// Unified batch call (no parameters for WAD)
const res = wad_batch_unified_js(high, low, close, {});
// res: { values: number[], rows: number, cols: number }
// For WAD, rows = 1; reshape as needed
const matrix = [] as number[][];
for (let r = 0; r < res.rows; r++) {
const start = r * res.cols;
matrix.push(res.values.slice(start, start + res.cols));
}
console.log('WAD row:', matrix[0]); Performance Analysis
Across sizes, Rust CPU runs about 2.86× faster than Tulip C in this benchmark.
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05
CUDA note
In our benchmark workload, the Rust CPU implementation is faster than CUDA for this indicator. Prefer the Rust/CPU path unless your workload differs.
Related Indicators
Accumulation/Distribution
Technical analysis indicator
Accumulation/Distribution Oscillator
Technical analysis indicator
Balance of Power
Technical analysis indicator
Chaikin Flow Oscillator
Technical analysis indicator
Elder Force Index
Technical analysis indicator
Ease of Movement
Technical analysis indicator