Donchian Channel Width
period = 20 Overview
Donchian Channel Width is the simplest possible read on how wide the current Donchian channel has become. For each bar, the indicator finds the highest high and the lowest low inside the rolling lookback window, then subtracts the lower boundary from the upper boundary. The output is therefore the raw channel span in price units, not a normalized percentage.
That makes the series useful when you want a direct volatility-style expansion and contraction read without separately plotting the full upper and lower channel lines. Rising values mean the recent trading range is widening. Falling values mean the channel is compressing. Because the implementation works directly from high and low data, it reacts to the actual extremes inside the window rather than to closes alone.
Defaults: Donchian Channel Width uses `period = 20`.
Implementation Examples
Compute the rolling channel span from high and low slices or from candle data.
use vector_ta::indicators::donchian_channel_width::{
donchian_channel_width,
DonchianChannelWidthInput,
DonchianChannelWidthParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let output = donchian_channel_width(&DonchianChannelWidthInput::from_slices(
&high,
&low,
DonchianChannelWidthParams { period: Some(20) },
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = donchian_channel_width(
&DonchianChannelWidthInput::with_default_candles(&candles)
)?;
println!("latest width = {:?}", output.values.last());
println!("series length = {}", candle_output.values.len()); API Reference
Input Methods ▼
// From candles
DonchianChannelWidthInput::from_candles(
&Candles,
DonchianChannelWidthParams,
) -> DonchianChannelWidthInput
// From high/low slices
DonchianChannelWidthInput::from_slices(
&[f64],
&[f64],
DonchianChannelWidthParams,
) -> DonchianChannelWidthInput
// From candles with default parameters
DonchianChannelWidthInput::with_default_candles(&Candles)
-> DonchianChannelWidthInput Parameters Structure ▼
pub struct DonchianChannelWidthParams {
pub period: Option<usize>, // default 20
} Output Structure ▼
pub struct DonchianChannelWidthOutput {
pub values: Vec<f64>,
} Validation, Warmup & NaNs ▼
- High and low inputs must both be non-empty and have identical lengths.
periodmust be greater than zero and no larger than the input length.- The longest contiguous run where both high and low are finite must be at least
periodbars. - Warmup lasts for
period - 1bars, which is also what the streaming API reports throughget_warmup_period(). - Invalid high/low pairs break the valid segment. In streaming mode they reset the internal state and return
None. - The output is the raw channel span
highest_high - lowest_low, not a percentage or centerline-relative value. - Destination slices for in-place APIs must match the input length exactly, and batch mode rejects invalid integer ranges or unsupported kernels.
Builder, Streaming & Batch APIs ▼
// Builder
DonchianChannelWidthBuilder::new()
.period(usize)
.kernel(Kernel)
.apply_slices(&[f64], &[f64])
DonchianChannelWidthBuilder::new()
.apply(&Candles)
DonchianChannelWidthBuilder::new()
.into_stream()
// Stream
DonchianChannelWidthStream::try_new(DonchianChannelWidthParams)
DonchianChannelWidthStream::update(high: f64, low: f64) -> Option<f64>
DonchianChannelWidthStream::reset()
DonchianChannelWidthStream::get_warmup_period() -> usize
// Batch
DonchianChannelWidthBatchBuilder::new()
.period_range(start, end, step)
.period_static(usize)
.kernel(Kernel)
.apply_slices(&[f64], &[f64])
DonchianChannelWidthBatchBuilder::new()
.apply_candles(&Candles) Error Handling ▼
pub enum DonchianChannelWidthError {
EmptyInputData,
InputLengthMismatch { high_len: usize, low_len: usize },
AllValuesNaN,
InvalidPeriod { period: usize, data_len: usize },
NotEnoughValidData { needed: usize, valid: usize },
OutputLengthMismatch { expected: usize, got: usize },
InvalidRange { start: usize, end: usize, step: usize },
InvalidKernelForBatch(Kernel),
MismatchedOutputLen { dst_len: usize, expected_len: usize },
InvalidInput { msg: String },
} Python Bindings
Python exposes an array-returning single-run function, a streaming class, and a batch function. The single-run binding returns one NumPy array of channel widths. Batch returns the width matrix plus the tested periods and the final rows and cols shape.
import numpy as np
from vector_ta import (
donchian_channel_width,
donchian_channel_width_batch,
DonchianChannelWidthStream,
)
high = np.asarray(high_values, dtype=np.float64)
low = np.asarray(low_values, dtype=np.float64)
values = donchian_channel_width(
high,
low,
period=20,
kernel="auto",
)
stream = DonchianChannelWidthStream(20)
print(stream.update(high[-1], low[-1]))
batch = donchian_channel_width_batch(
high,
low,
period_range=(10, 50, 10),
kernel="auto",
)
print(batch["periods"], batch["rows"], batch["cols"]) JavaScript/WASM Bindings
The WASM layer exposes a direct array-returning single-run wrapper, an object-returning batch wrapper, and lower-level allocation and in-place exports. The standard JavaScript path returns the width array, while the batch wrapper returns the flattened values matrix, tested combos, and the rows and cols shape.
import init, {
donchian_channel_width_js,
donchian_channel_width_batch_js,
} from "/pkg/vector_ta.js";
await init();
const high = new Float64Array(highValues);
const low = new Float64Array(lowValues);
const values = donchian_channel_width_js(high, low, 20);
console.log(values);
const batch = donchian_channel_width_batch_js(high, low, {
period_range: [10, 50, 10],
});
console.log(batch.values, batch.combos, batch.rows, batch.cols); CUDA Bindings (Rust)
Additional details for the CUDA bindings can be found inside the VectorTA repository.
Performance Analysis
Across sizes, Rust CPU runs about 1.14× faster than Tulip C in this benchmark.
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU)