Moving Average (MA) Dispatcher
ma_type = ema | period = 20 Overview
The MA dispatcher serves as a centralized entry point for accessing dozens of moving average implementations through a single unified interface, routing computation requests to specialized algorithms based on the specified ma_type string. Rather than importing and calling individual MA functions directly, traders pass an identifier like "sma", "ema", "wma", "hma", "kama", "jma", or "alma" along with a period parameter, and the dispatcher automatically selects and executes the appropriate calculation engine. This pattern simplifies strategy development by providing consistent syntax across all moving average types while preserving each algorithm's unique characteristics, from the lag reduction of Hull Moving Average to the adaptive behavior of Kaufman's Adaptive Moving Average or the Gaussian distribution smoothing of ALMA. Certain moving averages require specific data inputs beyond simple price series, such as FRAMA needing high/low ranges for fractal calculations, VWMA requiring volume for weighting, or VWAP using full OHLC data with volume for intraday anchoring. The dispatcher validates these requirements at runtime and returns clear error messages when a selected ma_type cannot operate on the provided data variant, ensuring robust error handling across diverse input scenarios.
Implementation Examples
Compute a selected moving average from prices or candles:
use vectorta::indicators::moving_averages::ma::{ma, ma_with_kernel, MaData};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
use vectorta::utilities::enums::Kernel;
// Slice input: EMA(20)
let prices = vec![100.0, 102.0, 101.5, 103.0, 105.0, 104.5];
let ema20 = ma("ema", MaData::Slice(&prices), 20)?;
// Candle input: KAMA(30) on close
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let kama30 = ma("kama", MaData::Candles { candles: &candles, source: "close" }, 30)?;
// Explicit kernel selection (e.g., AVX2)
let wma14 = ma_with_kernel("wma", MaData::Slice(&prices), 14, Kernel::Avx2)?; API Reference
Input Methods ▼
// From price slice
ma("ema", MaData::Slice(&prices), 20) -> Result<Vec<f64>, Box<dyn Error>>
// From candles with custom source (e.g., "close")
ma("kama", MaData::Candles { candles: &candles, source: "close" }, 30)
// Streaming creation
ma_stream("sma", 50) -> Result<MaStream, Box<dyn Error>> Parameters ▼
// Function signatures
pub fn ma(ma_type: &str, data: MaData, period: usize) -> Result<Vec<f64>, Box<dyn Error>>
pub fn ma_with_kernel(ma_type: &str, data: MaData, period: usize, kernel: Kernel) -> Result<Vec<f64>, Box<dyn Error>>
// Data enum
pub enum MaData<'a> {
Candles { candles: &'a Candles, source: &'a str },
Slice(&'a [f64]),
} Output ▼
// Values vector, same length as input
type MaOutput = Vec<f64>; Validation, Warmup & NaNs ▼
ma_typemust match a supported identifier. Unknown types:mareturns an error;ma_jsandma_streamfall back tosma.period > 0is typically required; specific validation and warmup depend on the selected MA implementation.- Some variants require specific inputs: e.g.,
frama(high/low),vwma/vwap(volume),vpwma(volume-weighted). - Output length matches input; leading values may be
NaNuntil warmup completes, depending on the implementation. - Streaming yields
Noneuntil sufficient data accumulates; volume-capable streams useupdate_with_volume(price, volume).
Error Handling ▼
use vectorta::indicators::moving_averages::ma::{ma, ma_with_kernel, MaData};
// Unknown type (ma): returns Err(Box<dyn Error>) with message
if let Err(e) = ma("unknown", MaData::Slice(&prices), 20) {
eprintln!("Error: {}", e);
}
// Special requirements (examples from dispatcher):
// - "frama" => "frama requires high/low data, use the indicator directly"
// - "ehlers_pma" => "ehlers_pma returns dual outputs, use the indicator directly"
// - "tradjema" => "tradjema requires high/low/close data, use the indicator directly"
// - "uma" => "uma requires volume data, use the indicator directly"
// - "volume_adjusted_ma" => "volume_adjusted_ma requires volume data, use the indicator directly"
// - "vwma" (ma_with_kernel, slice): "VWMA requires candle data with volume"
// Note: ma_js/ma_stream default to SMA for unknown ma_type; core ma() returns an error. Python Bindings
Use the unified dispatcher from Python:
import numpy as np
from vectorta import ma
prices = np.array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5], dtype=float)
# EMA(20) via dispatcher; optional kernel: "auto", "scalar", "avx2", "avx512"
ema20 = ma(prices, 'ema', 20, kernel='auto')
print(ema20.shape, ema20[:5]) JavaScript/WASM
Basic Usage ▼
import { ma } from 'vectorta-wasm';
const prices = new Float64Array([100, 102, 101.5, 103, 105, 104.5]);
// Choose type and period
const ema20 = ma(prices, 'ema', 20);
const kama30 = ma(prices, 'kama', 30);
console.log('EMA20:', ema20); CUDA
CUDA support for MA dispatcher is coming soon.
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)