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() exposes kernel(), apply(), apply_slices(), and into_stream().
  • MacdWaveSignalProStream::update(open, high, low, close) returns Option<MacdWaveSignalProPoint>, and the point carries all six output fields.
  • reset() clears all EMA/SMA state and crossover history.
  • get_warmup_period() returns 39 because the longest fixed lookback is 40.
  • MacdWaveSignalProBatchRange is empty because there is no parameter grid.
  • MacdWaveSignalProBatchBuilder::new() exposes kernel(), apply_slices(), and apply().
  • Batch output always has rows = 1 and returns the same six flattened row-major vectors plus combos and cols.
Validation, Warmup & NaNs
  • All four OHLC slices must be non-empty and have identical lengths.
  • A valid bar requires finite open, high, low, and close values.
  • The indicator requires at least 40 valid OHLC bars in total, because max(40, 26 + 9 - 1) = 40.
  • Warmup is field-specific: diff begins after first_valid + 25, dea, macd_histogram, buy_signal, and sell_signal begin after first_valid + 33, and line_convergence begins after first_valid + 39.
  • Invalid bars reset the streaming state and write NaN to all six outputs for that bar in slice mode.
  • buy_signal is set to 1.0 when diff crosses above dea; sell_signal is set to 1.0 when diff crosses below dea.
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

Comparison:
View:
Placeholder data (no recorded benchmarks for this indicator)

Across sizes, Rust CPU runs about 1.14× faster than Tulip C in this benchmark.

Loading chart...

AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU)

Related Indicators