Smoothed Moving Average (SMMA)

Parameters: period = 7

Overview

The Smoothed Moving Average employs recursive smoothing that begins with a simple average of the first period values and then updates each subsequent point by blending the previous SMMA with new data. SMMA calculates its first value as the arithmetic mean of the initial window, then for each following bar it removes a fraction of the old average and adds a fraction of the new price according to the period length. This recursive formula produces smoother curves than simple moving averages while responding more slowly to price changes, making SMMA particularly effective at filtering out market noise. The indicator closely resembles an exponential moving average with an equivalent period, though SMMA uses a slightly different weighting scheme derived from its recursive initialization. Traders favor SMMA for identifying longer term trends and dynamic support resistance zones, as the smoothing reduces false signals during choppy periods while still tracking major price movements.

Defaults: period = 7 (close as default source).

Implementation Examples

Get started with SMMA in just a few lines:

use vectorta::indicators::smma::{smma, SmmaInput, SmmaParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};

// Using with price data slice
let prices = vec![100.0, 102.0, 101.5, 103.0, 105.0, 104.5];
let params = SmmaParams { period: Some(7) }; // default period = 7
let input = SmmaInput::from_slice(&prices, params);
let result = smma(&input)?;

// Using with Candles data structure
// Quick and simple with default parameters (period=7; source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = SmmaInput::with_default_candles(&candles);
let result = smma(&input)?;

// Access the SMMA values
for value in result.values {
    println!("SMMA: {}", value);
}

API Reference

Input Methods
// From price slice
SmmaInput::from_slice(&[f64], SmmaParams) -> SmmaInput

// From candles with custom source
SmmaInput::from_candles(&Candles, &str, SmmaParams) -> SmmaInput

// From candles with default params (close price, period=7)
SmmaInput::with_default_candles(&Candles) -> SmmaInput
Parameters Structure
#[derive(Debug, Clone)]
pub struct SmmaParams {
    pub period: Option<usize>,
}

impl Default for SmmaParams {
    fn default() -> Self { Self { period: Some(7) } }
}
Output Structure
pub struct SmmaOutput {
    pub values: Vec<f64>, // SMMA values (same length as input)
}
Validation, Warmup & NaNs
  • Input must be non-empty; otherwise SmmaError::EmptyInputData. All-NaN input: SmmaError::AllValuesNaN.
  • period > 0 and period ≤ len; otherwise SmmaError::InvalidPeriod.
  • Requires at least period valid points after the first finite value; otherwise SmmaError::NotEnoughValidData.
  • Warmup: indices [0 .. first + period - 1) are NaN; first computable index is first + period - 1 (seeded by SMA).
  • Streaming returns None until the buffer fills, then yields each update. Subsequent NaNs in data propagate.
Error Handling
use vectorta::indicators::smma::{smma, SmmaError};

match smma(&input) {
    Ok(output) => process_results(output.values),
    Err(SmmaError::EmptyInputData) => eprintln!("input is empty"),
    Err(SmmaError::AllValuesNaN) => eprintln!("all values are NaN"),
    Err(SmmaError::InvalidPeriod { period, data_len }) => {
        eprintln!("invalid period: {} for len {}", period, data_len)
    }
    Err(SmmaError::NotEnoughValidData { needed, valid }) => {
        eprintln!("not enough valid data: needed {}, got {}", needed, valid)
    }
    Err(SmmaError::InvalidKernel { kernel }) => {
        eprintln!("invalid kernel for batch: {:?}", kernel)
    }
    Err(SmmaError::OutputLenMismatch { expected, actual }) => {
        eprintln!("preallocated output mismatch: expected {}, got {}", expected, actual)
    }
}

Python Bindings

Basic Usage

Calculate SMMA using NumPy arrays (default period=7):

import numpy as np
from vectorta import smma

# Prepare price data as NumPy array
prices = np.array([100.0, 101.0, 102.5, 101.8, 103.2, 104.0])

# Calculate SMMA (defaults from library: period=7)
result = smma(prices, period=7)

# Or specify kernel explicitly: 'auto' | 'scalar' | 'avx2' | 'avx512'
result = smma(prices, period=10, kernel="avx2")

print(f"SMMA values: {result}")
Streaming Real-time Updates

Process real-time price updates efficiently:

from vectorta import SmmaStream

# Initialize streaming SMMA calculator
stream = SmmaStream(period=7)

# Process real-time price updates
for price in price_feed:
    smma_value = stream.update(price)
    if smma_value is not None:
        print(f"Current SMMA: {smma_value}")
Batch Processing

Sweep period values in one pass:

import numpy as np
from vectorta import smma_batch

prices = np.array([/* your data */], dtype=np.float64)
results = smma_batch(prices, period_range=(5, 20, 5))

# Access 2D values [rows x cols] and period list
values = results['values']
periods = results['periods']
print(periods, values.shape)
CUDA Acceleration

CUDA helpers are available when built with CUDA + Python features.

import numpy as np
from vectorta import smma_cuda_batch_dev, smma_cuda_many_series_one_param_dev

# Option 1: One series, many parameters (parameter optimization)
prices = np.array([/* your data */], dtype=np.float64)
gpu_out = smma_cuda_batch_dev(prices, period_range=(5, 20, 1), device_id=0)

# Option 2: Many series, one parameter (portfolio/time-major: [T, N])
data_tm = np.array([/* time-major data */], dtype=np.float32)
gpu_out = smma_cuda_many_series_one_param_dev(data_tm, period=7, device_id=0)

JavaScript/WASM Bindings

Basic Usage

Calculate SMMA in JavaScript/TypeScript:

import { smma } from 'vectorta-wasm';

// Price data as Float64Array or regular array
const prices = new Float64Array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5]);

// Calculate SMMA with specified period
const result = smma(prices, 7);

console.log('SMMA values:', result);
Memory-Efficient Operations

Use zero-copy operations for large datasets:

import { smma_alloc, smma_free, smma_into, memory } from 'vectorta-wasm';

const prices = new Float64Array([/* your data */]);
const length = prices.length;

// Allocate WASM memory for input and output
const inPtr = smma_alloc(length);
const outPtr = smma_alloc(length);

// Copy input data into WASM memory
new Float64Array(memory.buffer, inPtr, length).set(prices);

// Compute directly into output buffer (in_ptr, out_ptr, len, period)
smma_into(inPtr, outPtr, length, 7);

// Read results from WASM memory
const smmaValues = new Float64Array(memory.buffer, outPtr, length).slice();

// Free allocated memory
smma_free(inPtr, length);
smma_free(outPtr, length);
Batch Processing

Test multiple period values efficiently:

import { smma_batch, smma_batch_metadata, smma_batch_rows_cols } from 'vectorta-wasm';

const prices = new Float64Array([/* historical prices */]);

// Define period sweep range
const start = 5, end = 20, step = 5;  // 5, 10, 15, 20

// Optional metadata
const periods = smma_batch_metadata(start, end, step); // [5,10,15,20]
const [rows, cols] = smma_batch_rows_cols(start, end, step, prices.length);

// Unified batch API with config object
const results = smma_batch(prices, { period_range: [start, end, step] });

// Results: { values: Float64Array(rows*cols), combos: SmmaParams[], rows, cols }
console.log(rows, cols, results);

Performance Analysis

Comparison:
View:
Loading chart...

AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05

Related Indicators