MACD Wave Signal Pro
Overview
MACD Wave Signal Pro produces six aligned series from OHLC input: diff, dea,
macd_histogram, line_convergence, buy_signal, and
sell_signal. The MACD leg uses fixed periods of 12, 26, and 9 on close, while the wave leg
measures the spread between the average of short simple moving averages and a longer simple moving average on a
weighted mid-price.
The weighted mid-price is computed as (7 * close + open + high + low) / 10. Line convergence is the
average of SMA(6) through SMA(20) on that weighted mid-price minus SMA(40) on the same series. Buy and sell
markers are binary crossover flags based on the relationship between diff and dea.
The indicator uses fixed internal settings, so the public params type is empty and the builder only exposes
kernel control.
Defaults: MACD Wave Signal Pro uses fixed internal periods with no user parameters.
Implementation Examples
Calculate all six MACD Wave Signal Pro outputs from OHLC slices or from candles:
use vector_ta::indicators::macd_wave_signal_pro::{
macd_wave_signal_pro, MacdWaveSignalProInput, MacdWaveSignalProParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let open = vec![100.0, 100.8, 101.5, 102.0, 101.7];
let high = vec![101.2, 101.6, 102.1, 102.8, 102.4];
let low = vec![99.7, 100.2, 100.9, 101.4, 101.0];
let close = vec![100.9, 101.1, 101.8, 102.4, 101.9];
let input = MacdWaveSignalProInput::from_slices(
&open,
&high,
&low,
&close,
MacdWaveSignalProParams,
);
let out = macd_wave_signal_pro(&input)?;
println!("{:?}", out.diff);
println!("{:?}", out.line_convergence);
println!("{:?}", out.buy_signal);
// Candles helper uses the candle OHLC fields directly
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let out = macd_wave_signal_pro(&MacdWaveSignalProInput::with_default_candles(&candles))?; API Reference
Input Methods ▼
MacdWaveSignalProInput::from_candles(&Candles, MacdWaveSignalProParams) -> MacdWaveSignalProInput
MacdWaveSignalProInput::from_slices(&[f64], &[f64], &[f64], &[f64], MacdWaveSignalProParams) -> MacdWaveSignalProInput
MacdWaveSignalProInput::with_default_candles(&Candles) -> MacdWaveSignalProInput Parameters Structure ▼
pub struct MacdWaveSignalProParams;
// Fixed internal settings:
// diff fast EMA = 12
// diff slow EMA = 26
// dea EMA = 9
// long line SMA = 40
// short line SMA range = 6..=20
// weighted mid = (7 * close + open + high + low) / 10
// macd_histogram = 2 * (diff - dea) Output Structure ▼
pub struct MacdWaveSignalProOutput {
pub diff: Vec<f64>,
pub dea: Vec<f64>,
pub macd_histogram: Vec<f64>,
pub line_convergence: Vec<f64>,
pub buy_signal: Vec<f64>,
pub sell_signal: Vec<f64>,
}
// buy_signal / sell_signal are binary marker series:
// 1.0 = crossover triggered on this bar
// 0.0 = no trigger on this bar Builders, Batch Range, and Stream ▼
MacdWaveSignalProBuilder::new()exposeskernel(),apply(),apply_slices(), andinto_stream().MacdWaveSignalProStream::update(open, high, low, close)returnsOption<MacdWaveSignalProPoint>, and the point carries all six output fields.reset()clears all EMA/SMA state and crossover history.get_warmup_period()returns39because the longest fixed lookback is40.MacdWaveSignalProBatchRangeis empty because there is no parameter grid.MacdWaveSignalProBatchBuilder::new()exposeskernel(),apply_slices(), andapply().- Batch output always has
rows = 1and returns the same six flattened row-major vectors pluscombosandcols.
Validation, Warmup & NaNs ▼
- All four OHLC slices must be non-empty and have identical lengths.
- A valid bar requires finite
open,high,low, andclosevalues. - The indicator requires at least
40valid OHLC bars in total, becausemax(40, 26 + 9 - 1) = 40. - Warmup is field-specific:
diffbegins afterfirst_valid + 25,dea,macd_histogram,buy_signal, andsell_signalbegin afterfirst_valid + 33, andline_convergencebegins afterfirst_valid + 39. - Invalid bars reset the streaming state and write
NaNto all six outputs for that bar in slice mode. buy_signalis set to1.0whendiffcrosses abovedea;sell_signalis set to1.0whendiffcrosses belowdea.
Error Handling ▼
use vector_ta::indicators::macd_wave_signal_pro::MacdWaveSignalProError;
match macd_wave_signal_pro(&input) {
Ok(out) => {
println!("{:?}", out.diff);
println!("{:?}", out.sell_signal);
}
Err(MacdWaveSignalProError::EmptyInputData) =>
eprintln!("OHLC input cannot be empty"),
Err(MacdWaveSignalProError::InconsistentSliceLengths { open_len, high_len, low_len, close_len }) =>
eprintln!("length mismatch: open={}, high={}, low={}, close={}", open_len, high_len, low_len, close_len),
Err(MacdWaveSignalProError::AllValuesNaN) =>
eprintln!("all OHLC bars were invalid"),
Err(MacdWaveSignalProError::NotEnoughValidData { needed, valid }) =>
eprintln!("need {} valid bars, only {}", needed, valid),
Err(MacdWaveSignalProError::InvalidKernelForBatch(kernel)) =>
eprintln!("invalid batch kernel: {:?}", kernel),
Err(e) => eprintln!("MACD Wave Signal Pro error: {}", e),
} Python Bindings
Basic Usage ▼
Python exposes macd_wave_signal_pro(open, high, low, close, kernel=None) and returns six NumPy arrays in fixed order.
import numpy as np
from vector_ta import macd_wave_signal_pro
diff, dea, macd_histogram, line_convergence, buy_signal, sell_signal = macd_wave_signal_pro(
open,
high,
low,
close,
) Streaming Real-time Updates ▼
The Python stream class is MacdWaveSignalProStream. It exposes update(), reset(), and a warmup_period getter.
from vector_ta import MacdWaveSignalProStream
stream = MacdWaveSignalProStream()
for o, h, l, c in zip(open, high, low, close):
point = stream.update(o, h, l, c)
if point is not None:
print(point)
print(stream.warmup_period) Batch Processing ▼
macd_wave_signal_pro_batch returns a single-row dict containing all six outputs plus basic shape metadata.
result = macd_wave_signal_pro_batch(open, high, low, close)
diff = result["diff"][0]
dea = result["dea"][0]
macd_histogram = result["macd_histogram"][0]
line_convergence = result["line_convergence"][0]
buy_signal = result["buy_signal"][0]
sell_signal = result["sell_signal"][0]
rows = result["rows"]
cols = result["cols"] JavaScript/WASM Bindings
Basic Usage ▼
WASM exports macd_wave_signal_pro_js(open, high, low, close) and returns an object with six arrays.
import { macd_wave_signal_pro_js } from 'vectorta-wasm';
const out = macd_wave_signal_pro_js(open, high, low, close);
console.log(out.diff);
console.log(out.buy_signal); Memory-Efficient Operations ▼
Use macd_wave_signal_pro_into with six output buffers when you want zero-copy writes into caller-managed WASM memory.
import {
macd_wave_signal_pro_alloc,
macd_wave_signal_pro_free,
macd_wave_signal_pro_into,
memory,
} from 'vectorta-wasm';
const len = close.length;
const openPtr = macd_wave_signal_pro_alloc(len);
const highPtr = macd_wave_signal_pro_alloc(len);
const lowPtr = macd_wave_signal_pro_alloc(len);
const closePtr = macd_wave_signal_pro_alloc(len);
const diffPtr = macd_wave_signal_pro_alloc(len);
const deaPtr = macd_wave_signal_pro_alloc(len);
const macdPtr = macd_wave_signal_pro_alloc(len);
const linePtr = macd_wave_signal_pro_alloc(len);
const buyPtr = macd_wave_signal_pro_alloc(len);
const sellPtr = macd_wave_signal_pro_alloc(len);
new Float64Array(memory.buffer, openPtr, len).set(open);
new Float64Array(memory.buffer, highPtr, len).set(high);
new Float64Array(memory.buffer, lowPtr, len).set(low);
new Float64Array(memory.buffer, closePtr, len).set(close);
macd_wave_signal_pro_into(
openPtr,
highPtr,
lowPtr,
closePtr,
diffPtr,
deaPtr,
macdPtr,
linePtr,
buyPtr,
sellPtr,
len,
);
const diff = new Float64Array(memory.buffer, diffPtr, len).slice();
const dea = new Float64Array(memory.buffer, deaPtr, len).slice();
macd_wave_signal_pro_free(openPtr, len);
macd_wave_signal_pro_free(highPtr, len);
macd_wave_signal_pro_free(lowPtr, len);
macd_wave_signal_pro_free(closePtr, len);
macd_wave_signal_pro_free(diffPtr, len);
macd_wave_signal_pro_free(deaPtr, len);
macd_wave_signal_pro_free(macdPtr, len);
macd_wave_signal_pro_free(linePtr, len);
macd_wave_signal_pro_free(buyPtr, len);
macd_wave_signal_pro_free(sellPtr, len); Batch Processing ▼
WASM batch uses macd_wave_signal_pro_batch_js with an empty config object and returns the same six outputs plus row metadata.
import { macd_wave_signal_pro_batch_js } from 'vectorta-wasm';
const batch = macd_wave_signal_pro_batch_js(open, high, low, close, {});
console.log(batch.rows, batch.cols);
console.log(batch.diff);
console.log(batch.sell_signal); 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)