Kaufman Efficiency Ratio (ER)
period = 5 Overview
The Kaufman Efficiency Ratio measures market noise by comparing the straight line distance between two price points against the actual path traveled, producing values from 0 (pure noise) to 1 (perfect trend). The calculation divides net price change over a period by the sum of all absolute price changes, revealing whether movement occurs smoothly or erratically. When ER approaches 1, price advances directly with minimal retracements, signaling strong trending conditions ideal for trend following strategies. Conversely, ER values near 0 indicate choppy, directionless markets where prices oscillate heavily, suggesting range trading or sitting aside. Traders particularly value ER for adaptive systems since it quantifies the signal to noise ratio in price action, allowing dynamic adjustment of indicators, position sizing, and stop losses based on market efficiency. The ratio excels at filtering whipsaw trades by distinguishing genuine trends from noisy sideways action that produces false breakouts.
Implementation Examples
Compute ER from a slice or candles:
use vectorta::indicators::er::{er, ErInput, ErParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using with a price slice
let prices = vec![100.0, 102.0, 101.0, 104.0, 106.0, 107.0];
let params = ErParams { period: Some(5) }; // Default = 5
let input = ErInput::from_slice(&prices, params);
let result = er(&input)?;
// Using with Candles data structure (defaults: source="close", period=5)
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = ErInput::with_default_candles(&candles);
let result = er(&input)?;
// Access the ER values (0.0..=1.0)
for value in result.values {
println!("ER: {}", value);
} API Reference
Input Methods ▼
// From price slice
ErInput::from_slice(&[f64], ErParams) -> ErInput
// From candles with custom source
ErInput::from_candles(&Candles, &str, ErParams) -> ErInput
// From candles with defaults (close, period=5)
ErInput::with_default_candles(&Candles) -> ErInput Parameters Structure ▼
pub struct ErParams {
pub period: Option<usize>, // Default: 5
} Output Structure ▼
pub struct ErOutput {
pub values: Vec<f64>, // ER values in [0.0, 1.0]
} Validation, Warmup & NaNs ▼
period > 0andperiod ≤ len; elseErError::InvalidPeriod.- Requires at least
periodvalid points after first finite value; elseErError::NotEnoughValidData. - Indices before
first + period − 1areNaN(warmup prefix). - Empty slice →
ErError::EmptyInputData; all-NaN →ErError::AllValuesNaN. er_into_slice: output slice length must match input; elseErError::OutputLenMismatch.- Streaming:
ErStream::updatereturnsNoneuntil the period buffer fills; then returnsSome(f64)per update.
Error Handling ▼
use vectorta::indicators::er::{er, ErError};
match er(&input) {
Ok(output) => process(output.values),
Err(ErError::EmptyInputData) => eprintln!("No data provided"),
Err(ErError::AllValuesNaN) => eprintln!("All input values are NaN"),
Err(ErError::InvalidPeriod { period, data_len }) => {
eprintln!("Invalid period: {} (len={})", period, data_len);
}
Err(ErError::NotEnoughValidData { needed, valid }) => {
eprintln!("Not enough valid data: needed={}, valid={}", needed, valid);
}
Err(ErError::OutputLenMismatch { dst_len, data_len }) => {
eprintln!("Output length mismatch: dst_len={}, data_len={}", dst_len, data_len);
}
} Python Bindings
Basic Usage ▼
Calculate ER in Python (NumPy arrays supported):
import numpy as np
from vectorta import er
prices = np.array([100.0, 102.0, 101.0, 104.0, 106.0, 107.0], dtype=np.float64)
# period defaults to library default (5) if not set by upstream wrapper
values = er(prices, period=5, kernel="auto")
print(values) # numpy.ndarray[float64] Streaming Real-time Updates ▼
Incremental ER with warmup-aware output:
from vectorta import ErStream
stream = ErStream(period=5)
for price in price_feed:
value = stream.update(price)
if value is not None:
print(f"ER: {value}") Batch Parameter Range ▼
Evaluate many period values efficiently:
import numpy as np
from vectorta import er_batch
prices = np.array([...], dtype=np.float64)
# (start, end, step)
period_range = (5, 20, 5)
res = er_batch(prices, period_range, kernel="auto")
# res is a dict with keys: values (rows x cols), periods, rows, cols
print(res["values"].shape)
print(res["periods"]) CUDA Acceleration ▼
CUDA support for ER is currently under development. The API will align with other CUDA-enabled indicators in this project.
# Coming soon: CUDA-accelerated ER calculations
# from vectorta import er_cuda_batch, er_cuda_many_series_one_param JavaScript/WASM Bindings
Basic Usage ▼
Calculate ER in JavaScript/TypeScript:
import { er_js } from 'vectorta-wasm';
const prices = new Float64Array([100, 102, 101, 104, 106, 107]);
const result = er_js(prices, 5); // period=5
console.log('ER values:', result); Memory-Efficient Operations ▼
Use zero-copy operations for large datasets:
import { er_alloc, er_free, er_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const len = prices.length;
const inPtr = er_alloc(len);
const outPtr = er_alloc(len);
new Float64Array(memory.buffer, inPtr, len).set(prices);
// Args: in_ptr, out_ptr, len, period
er_into(inPtr, outPtr, len, 5);
const erValues = new Float64Array(memory.buffer, outPtr, len).slice();
er_free(inPtr, len);
er_free(outPtr, len);
console.log('ER values:', erValues); Batch Processing ▼
Test multiple period values efficiently:
import { er_batch } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
// Unified batch API returns values matrix + combos metadata
const config = { period_range: [5, 20, 5] }; // [start, end, step]
const result = er_batch(prices, config);
// result: { values: number[], combos: { period: number|null }[], rows, cols }
console.log('rows x cols =', result.rows, 'x', result.cols);
console.log('first combo period =', result.combos[0].period);
// Reshape flat values into 2D [rows][cols]
const matrix: number[][] = [];
for (let r = 0; r < result.rows; r++) {
const start = r * result.cols;
matrix.push(result.values.slice(start, start + result.cols));
}
console.log('ER(row0) sample:', matrix[0].slice(0, 8)); Performance Analysis
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05