Simple Moving Average (SMA)
period = 9 Overview
The Simple Moving Average computes the arithmetic mean of the most recent period values to produce a smoothed line that reveals underlying trend direction. SMA treats all values within the window equally, summing them and dividing by the period length to calculate each point. As new data arrives, the oldest value drops from the window while the newest enters, creating a rolling average that follows price with consistent lag. This equal weighting makes SMA the most straightforward and interpretable moving average, though it responds slowly to sudden price changes since extreme values carry the same weight as moderate ones. Traders use SMA extensively for identifying support and resistance levels, with longer periods like 50 and 200 days marking major trend lines that institutions watch closely. The indicator works well for confirming trend direction through price crosses and generating signals when faster SMAs cross slower ones, providing clear and objective entry and exit points that form the foundation of many technical trading strategies.
Implementation Examples
Compute SMA from a slice or candles:
use vectorta::indicators::sma::{sma, SmaInput, SmaParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};
// Using with a price slice
let prices = vec![100.0, 102.0, 101.5, 103.0, 105.0, 104.5];
let params = SmaParams { period: Some(9) };
let input = SmaInput::from_slice(&prices, params);
let result = sma(&input)?;
// Using with Candles (default: source="close", period=9)
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = SmaInput::with_default_candles(&candles);
let result = sma(&input)?;
// Access values
for value in result.values {
println!("SMA: {}", value);
} API Reference
Input Methods ▼
// From price slice
SmaInput::from_slice(&[f64], SmaParams) -> SmaInput
// From candles with custom source
SmaInput::from_candles(&Candles, &str, SmaParams) -> SmaInput
// From candles with default params (source="close", period=9)
SmaInput::with_default_candles(&Candles) -> SmaInput Parameters Structure ▼
pub struct SmaParams {
pub period: Option<usize>, // Default: 9
} Output Structure ▼
pub struct SmaOutput {
pub values: Vec<f64>, // SMA values
} Validation, Warmup & NaNs ▼
period > 0andperiod ≤ data.len(); otherwiseSmaError::InvalidPeriod.- If all inputs are
NaN:SmaError::AllValuesNaN. - First finite index =
first; require at leastperiodvalid points afterfirst, elseSmaError::NotEnoughValidData. - Warmup: indices
[0 .. first+period-2]areNaN; first valid output atfirst+period-1. - Zero‑copy API
sma_into_slicechecks output length; mismatch yieldsSmaError::OutputLenMismatch.
Error Handling ▼
use vectorta::indicators::sma::{sma, SmaError};
match sma(&input) {
Ok(output) => process_results(output.values),
Err(SmaError::EmptyData) => eprintln!("empty data"),
Err(SmaError::InvalidPeriod { period, data_len }) =>
eprintln!("invalid period: {} (data_len={})", period, data_len),
Err(SmaError::NotEnoughValidData { needed, valid }) =>
eprintln!("not enough valid data: needed={}, valid={}", needed, valid),
Err(SmaError::AllValuesNaN) => eprintln!("all inputs are NaN"),
Err(SmaError::OutputLenMismatch { expected, got }) =>
eprintln!("output length mismatch: expected={}, got={}", expected, got),
} Python Bindings
Basic Usage ▼
Calculate SMA using NumPy arrays:
import numpy as np
from vectorta import sma, sma_batch, SmaStream
prices = np.asarray([100.0, 102.0, 101.5, 103.0, 105.0, 104.5], dtype=float)
# Basic
values = sma(prices, period=9, kernel="auto")
print(values)
# Batch sweep (start, end, step)
out = sma_batch(prices, period_range=(5, 30, 5), kernel="auto")
print(out["values"].shape) # (num_periods, len(prices))
print(out["periods"]) Streaming Real-time Updates ▼
O(1) update complexity with internal state:
from vectorta import SmaStream
stream = SmaStream(period=9)
for price in price_feed:
y = stream.update(float(price))
if y is not None:
print(y) CUDA Acceleration ▼
Available when built with CUDA support:
import numpy as np
from vectorta import sma_cuda_batch_dev, sma_cuda_many_series_one_param_dev
# Device batch: single series, many periods (f32 input for GPU efficiency)
prices_f32 = np.asarray([/* your data */], dtype=np.float32)
dev_buf, meta = sma_cuda_batch_dev(prices_f32, period_range=(5, 30, 5), device_id=0)
print(meta["periods"]) # periods used
# Many series (time-major [T, N]), one parameter set
data_tm = np.asarray([/* T x N */], dtype=np.float32)
dev_buf2 = sma_cuda_many_series_one_param_dev(data_tm, period=20, device_id=0) JavaScript/WASM Bindings
Basic Usage ▼
Calculate SMA in JavaScript/TypeScript:
import { sma_js } from 'vectorta-wasm';
const prices = new Float64Array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5]);
const result = sma_js(prices, 9); // period=9
console.log('SMA values:', result); Memory-Efficient Operations ▼
Use zero-copy operations for large datasets:
import { sma_alloc, sma_free, sma_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const n = prices.length;
const inPtr = sma_alloc(n);
const outPtr = sma_alloc(n);
new Float64Array(memory.buffer, inPtr, n).set(prices);
// in_ptr, out_ptr, len, period
sma_into(inPtr, outPtr, n, 9);
const out = new Float64Array(memory.buffer, outPtr, n).slice();
console.log('SMA:', out);
sma_free(inPtr, n);
sma_free(outPtr, n); Batch Processing ▼
Test multiple periods efficiently:
import { sma_batch_js, sma_batch_metadata_js } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
const start = 5, end = 30, step = 5; // 5,10,15,20,25,30
const periods = sma_batch_metadata_js(start, end, step);
const flat = sma_batch_js(prices, start, end, step);
const numCombos = periods.length;
const rows: number[][] = [];
for (let i = 0; i < numCombos; i++) {
const off = i * prices.length;
rows.push(Array.from(flat.slice(off, off + prices.length)));
} Performance Analysis
Across sizes, Rust CPU runs about 2.04× faster than Tulip C in this benchmark.
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05
Related Indicators
Arnaud Legoux Moving Average
Moving average 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
Ehlers Error-Correcting EMA (ECEMA)
Moving average indicator