Corrected Moving Average
period = 35 Overview
Corrected Moving Average begins with a standard rolling mean, but it does not simply return that SMA line. Once enough samples are available, the algorithm compares the previous corrected value against the current rolling mean and measures that difference against the rolling variance. That comparison produces an adaptive gain factor, which determines how aggressively the corrected line should move back toward the current mean.
In quiet conditions, where the rolling variance is small relative to the difference between the old corrected value and the current mean, the line can respond more quickly. When the local variance already explains most of that distance, the correction becomes gentler. The result is a one-line smoother that keeps the interpretability of a moving average while reacting more selectively than a plain SMA.
Defaults: Corrected Moving Average uses `period = 35`.
Implementation Examples
Compute the corrected average from a slice or from a candle field.
use vector_ta::indicators::moving_averages::corrected_moving_average::{
corrected_moving_average,
CorrectedMovingAverageInput,
CorrectedMovingAverageParams,
};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let close = vec![100.0, 100.8, 101.6, 101.1, 102.4, 102.0, 103.1];
let output = corrected_moving_average(&CorrectedMovingAverageInput::from_slice(
&close,
CorrectedMovingAverageParams { period: Some(35) },
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_output = corrected_moving_average(
&CorrectedMovingAverageInput::with_default_candles(&candles)
)?;
println!("latest corrected value = {:?}", output.values.last());
println!("series length = {}", candle_output.values.len()); API Reference
Input Methods ▼
// From candles and a named source field
CorrectedMovingAverageInput::from_candles(
&Candles,
&str,
CorrectedMovingAverageParams,
) -> CorrectedMovingAverageInput
// From a raw slice
CorrectedMovingAverageInput::from_slice(&[f64], CorrectedMovingAverageParams)
-> CorrectedMovingAverageInput
// From candles with default parameters
CorrectedMovingAverageInput::with_default_candles(&Candles)
-> CorrectedMovingAverageInput Parameters Structure ▼
pub struct CorrectedMovingAverageParams {
pub period: Option<usize>, // default 35
} Output Structure ▼
pub struct CorrectedMovingAverageOutput {
pub values: Vec<f64>,
} Validation, Warmup & NaNs ▼
- The input slice must be non-empty and contain at least one finite value.
periodmust be greater than zero and no larger than the input length.- The longest contiguous finite run must be at least
periodbars or the function returnsNotEnoughValidData. - Warmup lasts for
period - 1bars, which is also what the streaming API reports throughget_warmup_period(). - Streaming resets its rolling statistics and previous corrected value when it sees a non-finite input.
- Destination slices for in-place APIs must match the input length exactly.
- Batch mode rejects invalid integer ranges and unsupported kernels.
Builder, Streaming & Batch APIs ▼
// Builder
CorrectedMovingAverageBuilder::new()
.period(usize)
.kernel(Kernel)
.apply_slice(&[f64])
CorrectedMovingAverageBuilder::new()
.apply(&Candles)
CorrectedMovingAverageBuilder::new()
.into_stream()
// Stream
CorrectedMovingAverageStream::try_new(CorrectedMovingAverageParams)
CorrectedMovingAverageStream::update(f64) -> Option<f64>
CorrectedMovingAverageStream::reset()
CorrectedMovingAverageStream::get_warmup_period() -> usize
// Batch
CorrectedMovingAverageBatchBuilder::new()
.period_range(start, end, step)
.period_static(usize)
.kernel(Kernel)
.apply_slice(&[f64]) Error Handling ▼
pub enum CorrectedMovingAverageError {
EmptyInputData,
AllValuesNaN,
InvalidPeriod { period: usize, data_len: usize },
NotEnoughValidData { needed: usize, valid: usize },
OutputLengthMismatch { expected: usize, got: usize },
InvalidRange { start: usize, end: usize, step: usize },
InvalidKernelForBatch(Kernel),
} Python Bindings
Python exposes an array-returning single-run function, a streaming class, and a batch function. The single-run binding returns one NumPy array of corrected moving-average values. Batch returns a values matrix plus the tested periods and the final rows and cols shape.
import numpy as np
from vector_ta import (
corrected_moving_average,
corrected_moving_average_batch,
CorrectedMovingAverageStream,
)
data = np.asarray(close_values, dtype=np.float64)
values = corrected_moving_average(
data,
period=35,
kernel="auto",
)
stream = CorrectedMovingAverageStream(35)
print(stream.update(data[-1]))
batch = corrected_moving_average_batch(
data,
period_range=(20, 50, 5),
kernel="auto",
)
print(batch["periods"], batch["rows"], batch["cols"]) JavaScript/WASM Bindings
The WASM layer exposes a direct array-returning single-run wrapper, an object-returning batch wrapper, and lower-level allocation and in-place exports. The standard JavaScript path returns the corrected-average array, while the batch wrapper returns the flattened values matrix, tested combos, and the rows and cols shape.
import init, {
corrected_moving_average_js,
corrected_moving_average_batch_js,
} from "/pkg/vector_ta.js";
await init();
const data = new Float64Array(closeValues);
const values = corrected_moving_average_js(data, 35);
console.log(values);
const batch = corrected_moving_average_batch_js(data, {
period_range: [20, 50, 5],
});
console.log(batch.values, batch.combos, 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)
Related Indicators
Arnaud Legoux Moving Average
Moving average indicator
Buff Averages
Technical analysis indicator
Compound Ratio Moving Average (CoRa Wave)
Moving average indicator
Centered Weighted Moving Average
Moving average indicator
Double Exponential Moving Average
Moving average indicator
Ehlers Distance Coefficient Filter
Moving average indicator