Goertzel Cycle Composite Wave
max_period = 120 | start_at_cycle = 1 | use_top_cycles = 2 | bar_to_calculate = 1 | detrend_mode = hodrick_prescott_detrending Overview
Goertzel Cycle Composite Wave is a spectral cycle tool that scans a rolling price sample for dominant periodic components, ranks those cycles by amplitude, and then reconstructs a composite wave from the strongest selected cycles. Before the scan, the input window can be smoothed or detrended with Hodrick-Prescott, zero-lag, or regression-based preprocessing so the cycle extraction focuses on oscillatory structure rather than raw trend.
The indicator is configurable enough to behave as either a broad composite-cycle reader or a stricter significance-filtered tool. Optional Bartels filtering can reject statistically weak cycles, the cycle list can be sorted by Bartels significance, and the final wave can use cosine or sine reconstruction, squared or raw amplitudes, and optional noise subtraction from the remaining lower-ranked cycles.
Defaults: Goertzel Cycle Composite Wave uses `max_period = 120`, `start_at_cycle = 1`, `use_top_cycles = 2`, `bar_to_calculate = 1`, `detrend_mode = "hodrick_prescott_detrending"`, `filter_bartels = false`, `squared_amp = true`, `use_cosine = true`, `subtract_noise = false`, and `use_cycle_strength = true`.
Implementation Examples
Compute the composite cycle wave from a price slice or from candle closes.
use vector_ta::indicators::goertzel_cycle_composite_wave::{
goertzel_cycle_composite_wave,
GoertzelCycleCompositeWaveInput,
GoertzelCycleCompositeWaveParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let close = vec![100.0, 101.1, 100.4, 102.0, 101.3, 103.2, 102.5];
let output = goertzel_cycle_composite_wave(&GoertzelCycleCompositeWaveInput::from_slice(
&close,
GoertzelCycleCompositeWaveParams::default(),
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = goertzel_cycle_composite_wave(
&GoertzelCycleCompositeWaveInput::with_default_candles(&candles),
)?;
println!("latest wave = {:?}", output.values.last());
println!("series length = {}", candle_output.values.len()); API Reference
Input Methods ▼
// From candles with an explicit source
GoertzelCycleCompositeWaveInput::from_candles(&Candles, &str, GoertzelCycleCompositeWaveParams)
-> GoertzelCycleCompositeWaveInput
// From a raw slice
GoertzelCycleCompositeWaveInput::from_slice(&[f64], GoertzelCycleCompositeWaveParams)
-> GoertzelCycleCompositeWaveInput
// From candles with default source and parameters
GoertzelCycleCompositeWaveInput::with_default_candles(&Candles)
-> GoertzelCycleCompositeWaveInput Parameters Structure ▼
pub struct GoertzelCycleCompositeWaveParams {
pub max_period: Option<usize>,
pub start_at_cycle: Option<usize>,
pub use_top_cycles: Option<usize>,
pub bar_to_calculate: Option<usize>,
pub detrend_mode: Option<GoertzelDetrendMode>,
pub dt_zl_per1: Option<usize>,
pub dt_zl_per2: Option<usize>,
pub dt_hp_per1: Option<usize>,
pub dt_hp_per2: Option<usize>,
pub dt_reg_zl_smooth_per: Option<usize>,
pub hp_smooth_per: Option<usize>,
pub zlma_smooth_per: Option<usize>,
pub filter_bartels: Option<bool>,
pub bart_no_cycles: Option<usize>,
pub bart_smooth_per: Option<usize>,
pub bart_sig_limit: Option<usize>,
pub sort_bartels: Option<bool>,
pub squared_amp: Option<bool>,
pub use_cosine: Option<bool>,
pub subtract_noise: Option<bool>,
pub use_cycle_strength: Option<bool>,
} Output Structure ▼
pub struct GoertzelCycleCompositeWaveOutput {
pub values: Vec<f64>,
} Validation, Warmup & NaNs ▼
- The input series must be non-empty and contain at least one finite value.
- Core positive parameters such as
start_at_cycle,use_top_cycles, and the smoothing lengths must all be greater than0. - Hodrick-Prescott periods that drive HP smoothing or detrending must be at least
2. - The indicator requires a contiguous valid run large enough to cover the entire rolling sample implied by
max_period,bar_to_calculate, and Bartels settings. - One-shot and batch outputs are NaN-prefixed until the full sample window is available.
- Streaming resets on non-finite input and restarts its rolling sample warmup.
- Batch mode validates the range axes and rejects unsupported kernels through
InvalidKernelForBatch.
Builder, Streaming & Batch APIs ▼
// Builder
GoertzelCycleCompositeWaveBuilder::new()
.params(GoertzelCycleCompositeWaveParams)
.max_period(usize)
.start_at_cycle(usize)
.use_top_cycles(usize)
.kernel(Kernel)
.apply(&Candles)
GoertzelCycleCompositeWaveBuilder::new()
.apply_slice(&[f64])
GoertzelCycleCompositeWaveBuilder::new()
.into_stream()
// Stream
GoertzelCycleCompositeWaveStream::try_new(GoertzelCycleCompositeWaveParams)
GoertzelCycleCompositeWaveStream::update(f64) -> Option<f64>
GoertzelCycleCompositeWaveStream::reset()
GoertzelCycleCompositeWaveStream::get_warmup_period() -> usize
// Batch
GoertzelCycleCompositeWaveBatchBuilder::new()
.kernel(Kernel)
.max_period_range((usize, usize, usize))
.start_at_cycle_range((usize, usize, usize))
.use_top_cycles_range((usize, usize, usize))
.params(GoertzelCycleCompositeWaveParams)
.apply_slice(&[f64]) Error Handling ▼
pub enum GoertzelCycleCompositeWaveError {
EmptyInputData,
AllValuesNaN,
InvalidParameter { name: &'static str, value: usize },
NotEnoughValidData { needed: usize, valid: usize },
OutputLengthMismatch { expected: usize, got: usize },
InvalidRange { start: usize, end: usize, step: usize },
InvalidKernelForBatch(Kernel),
MismatchedOutputLen { dst_len: usize, expected_len: usize },
InvalidInput { msg: String },
InvalidDetrendMode(String),
} Python Bindings
Python exposes a scalar price-series function, a streaming class, and a batch sweep. The scalar path returns one NumPy composite-wave array. Streaming returns one floating-point wave value or `None`, while batch returns the flattened matrix plus the tested `max_period`, `start_at_cycle`, and `use_top_cycles` combinations together with output dimensions.
import numpy as np
from vector_ta import (
goertzel_cycle_composite_wave,
goertzel_cycle_composite_wave_batch,
GoertzelCycleCompositeWaveStream,
)
data = np.asarray(close_values, dtype=np.float64)
values = goertzel_cycle_composite_wave(
data,
max_period=120,
start_at_cycle=1,
use_top_cycles=2,
detrend_mode="hodrick_prescott_detrending",
kernel="auto",
)
stream = GoertzelCycleCompositeWaveStream(
max_period=96,
start_at_cycle=1,
use_top_cycles=3,
detrend_mode="zero_lag_detrending",
)
print(stream.update(data[-1]))
batch = goertzel_cycle_composite_wave_batch(
data,
max_period_range=(80, 120, 20),
start_at_cycle_range=(1, 2, 1),
use_top_cycles_range=(1, 3, 1),
detrend_mode="hodrick_prescott_detrending",
kernel="auto",
)
print(batch["values"].shape)
print(batch["max_periods"])
print(batch["use_top_cycles"]) JavaScript/WASM Bindings
The WASM layer exposes a config-driven scalar function, a batch function, and raw allocation and into-buffer helpers. The scalar binding returns a single composite-wave array. The batch binding returns the flattened values matrix plus the tested parameter combinations and matrix dimensions.
import init, {
goertzel_cycle_composite_wave_js,
goertzel_cycle_composite_wave_batch_js,
} from "@vectoralpha/vector_ta";
await init();
const values = goertzel_cycle_composite_wave_js(close, {
max_period: 120,
start_at_cycle: 1,
use_top_cycles: 2,
detrend_mode: "hodrick_prescott_detrending",
filter_bartels: false,
});
console.log(values);
const batch = goertzel_cycle_composite_wave_batch_js(close, {
max_period_range: [80, 120, 20],
start_at_cycle_range: [1, 2, 1],
use_top_cycles_range: [1, 3, 1],
base: {
detrend_mode: "hodrick_prescott_detrending",
filter_bartels: true,
bart_sig_limit: 55,
},
});
console.log(batch.values);
console.log(batch.combos);
console.log(batch.rows, batch.cols); 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)