True Range Adjusted EMA (TRADJEMA)
length = 40 | mult = 10 (1–25) Overview
True Range Adjusted Exponential Moving Average dynamically adapts its smoothing characteristics based on current market volatility conditions. The indicator measures True Range for each bar and normalizes it within a rolling lookback window, then scales the EMA smoothing factor proportionally to create a volatility responsive average. When markets become more volatile, the smoothing factor increases to make the average more reactive to price changes, allowing it to track rapid moves more closely. Conversely, during quiet periods with low volatility, the factor contracts to filter out noise and provide a steadier trend signal. This adaptive behavior makes TRADJEMA particularly valuable for traders who need a single indicator that automatically adjusts to changing market conditions without manual parameter optimization. Default settings use a 40 period lookback window with a volatility multiplier of 10.0, calibrated to provide balanced adaptation across diverse market environments.
Implementation Examples
Calculate TRADJEMA from OHLC candles or explicit high/low/close slices:
use vectorta::indicators::moving_averages::tradjema::{
TradjemaParams, TradjemaInput, tradjema,
};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using with OHLC slices
let high = vec![..];
let low = vec![..];
let close = vec![..];
let params = TradjemaParams { length: Some(40), mult: Some(10.0) };
let input = TradjemaInput::from_slices(&high, &low, &close, params);
let out = tradjema(&input)?;
// Using with Candles (defaults: length=40, mult=10.0)
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = TradjemaInput::with_default_candles(&candles);
let out = tradjema(&input)?;
// Access values
for v in out.values { println!("{}", v); } API Reference
Input Methods ▼
// From candles (uses high/low/close internally)
TradjemaInput::from_candles(&Candles, TradjemaParams) -> TradjemaInput
// From explicit OHLC slices
TradjemaInput::from_slices(&[f64], &[f64], &[f64], TradjemaParams) -> TradjemaInput
// With defaults (length=40, mult=10.0)
TradjemaInput::with_default_candles(&Candles) -> TradjemaInput Parameters Structure ▼
pub struct TradjemaParams {
pub length: Option<usize>, // Default: 40
pub mult: Option<f64>, // Default: 10.0
} Output Structure ▼
pub struct TradjemaOutput {
pub values: Vec<f64>, // TR-adjusted EMA values
} Validation, Warmup & NaNs ▼
length ≥ 2andlength ≤ data_len; otherwiseTradjemaError::InvalidLength.- OHLC arrays must have equal length; otherwise
TradjemaError::MissingData. - There must be at least
lengthvalid points after the first finite close; otherwiseTradjemaError::NotEnoughValidData. multmust be finite and> 0.0; otherwiseTradjemaError::InvalidMult.- Leading invalid inputs: indices before
first + length - 1areNaN; first finite output occurs at warmup.
Error Handling ▼
use vectorta::indicators::moving_averages::tradjema::{tradjema, TradjemaError};
match tradjema(&input) {
Ok(output) => process(output.values),
Err(TradjemaError::EmptyInputData) => eprintln!("Input data is empty"),
Err(TradjemaError::AllValuesNaN) => eprintln!("All values are NaN"),
Err(TradjemaError::MissingData) => eprintln!("OHLC length mismatch"),
Err(TradjemaError::InvalidLength { length, data_len }) =>
eprintln!("Invalid length {} for data_len {}", length, data_len),
Err(TradjemaError::NotEnoughValidData { needed, valid }) =>
eprintln!("Need {} valid points, only {}", needed, valid),
Err(TradjemaError::InvalidMult { mult }) =>
eprintln!("Invalid mult: {} (must be > 0 and finite)", mult),
} Python Bindings
Basic Usage ▼
Compute TRADJEMA from NumPy arrays (OHLC):
import numpy as np
from vectorta import tradjema
high = np.array([...], dtype=float)
low = np.array([...], dtype=float)
close = np.array([...], dtype=float)
# Defaults: length=40, mult=10.0
values = tradjema(high, low, close, 40, 10.0)
# Custom kernel
values = tradjema(high, low, close, 30, 8.0, kernel="auto") Batch Processing ▼
Sweep parameter grids and analyze combinations:
import numpy as np
from vectorta import tradjema_batch
high = np.array([...], dtype=float)
low = np.array([...], dtype=float)
close = np.array([...], dtype=float)
res = tradjema_batch(
high, low, close,
length_range=(20, 60, 10),
mult_range=(5.0, 15.0, 2.5),
kernel="auto"
)
# Results
vals = res["values"] # shape: (rows, len(close))
lengths = res["lengths"] # list of tested lengths (per row)
mults = res["mults"] # list of tested mults (per row)
print(vals.shape, len(lengths), len(mults)) CUDA Acceleration ▼
Available when built with python + cuda features:
from vectorta import (
tradjema_cuda_batch_dev,
tradjema_cuda_many_series_one_param_dev,
)
import numpy as np
# One series, many parameter combinations (device arrays returned)
rows = tradjema_cuda_batch_dev(
high.astype('float32'),
low.astype('float32'),
close.astype('float32'),
length_range=(20, 60, 10),
mult_range=(5.0, 15.0, 2.5),
device_id=0
)
# Many series, one parameter set (time-major [T, N] f32)
high_tm, low_tm, close_tm = ... # np.ndarray[T, N] float32
dev_arr = tradjema_cuda_many_series_one_param_dev(
high_tm, low_tm, close_tm,
length=40, mult=10.0,
device_id=0
) JavaScript/WASM Bindings
Basic Usage ▼
Compute TRADJEMA from OHLC arrays:
import { tradjema_js } from 'vectorta-wasm';
const high = new Float64Array([/* ... */]);
const low = new Float64Array([/* ... */]);
const close = new Float64Array([/* ... */]);
// length=40, mult=10.0
const values = tradjema_js(high, low, close, 40, 10.0); Memory-Efficient Operations ▼
Use zero-copy compute into preallocated WASM memory:
import { tradjema_alloc, tradjema_free, tradjema_into, memory } from 'vectorta-wasm';
const n = close.length;
const hPtr = tradjema_alloc(n);
const lPtr = tradjema_alloc(n);
const cPtr = tradjema_alloc(n);
const outPtr = tradjema_alloc(n);
new Float64Array(memory.buffer, hPtr, n).set(high);
new Float64Array(memory.buffer, lPtr, n).set(low);
new Float64Array(memory.buffer, cPtr, n).set(close);
// Compute directly into WASM buffer
tradjema_into(hPtr, lPtr, cPtr, outPtr, n, 40, 10.0);
const out = new Float64Array(memory.buffer, outPtr, n).slice();
// Free
tradjema_free(hPtr, n); tradjema_free(lPtr, n);
tradjema_free(cPtr, n); tradjema_free(outPtr, n); Performance Analysis
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.