Symmetric Weighted Moving Average (SWMA)

Parameters: period = 5

Overview

The Symmetric Weighted Moving Average creates a triangular weighting pattern that emphasizes central values within the lookback window while tapering weights toward both edges. SWMA assigns the highest weight to the middle bar of the period, then progressively reduces weights symmetrically as bars move toward either the beginning or end of the window. This triangular distribution produces smooth curves that balance responsiveness with lag reduction, as the central emphasis captures current market conditions without over-weighting the most recent bar. The symmetric nature ensures equal treatment of past and future relative to the center, making SWMA particularly effective at identifying turning points with minimal phase shift. Traders appreciate the indicator for its smooth appearance that avoids the jumpiness of exponentially weighted methods while responding faster than simple moving averages, creating reliable dynamic support and resistance levels that work well across multiple timeframes.

Defaults: period = 5.

Implementation Examples

Get started with SWMA in just a few lines:

use vectorta::indicators::moving_averages::swma::{swma, SwmaInput, SwmaParams};
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 = SwmaParams { period: Some(5) };
let input = SwmaInput::from_slice(&prices, params);
let result = swma(&input)?;

// Using with Candles data structure (default source = "close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = SwmaInput::with_default_candles(&candles);
let result = swma(&input)?;

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

API Reference

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

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

// From candles with default params (source = "close", period=5)
SwmaInput::with_default_candles(&Candles) -> SwmaInput
Parameters Structure
#[derive(Debug, Clone)
pub struct SwmaParams {
    pub period: Option<usize>, // Default: 5
}
Output Structure
pub struct SwmaOutput {
    pub values: Vec<f64>, // SWMA values
}
Validation, Warmup & NaNs
  • period > 0 and period ≤ data.len(); else SwmaError::InvalidPeriod { period, data_len }.
  • Must have at least period valid values after the first finite; else SwmaError::NotEnoughValidData { needed, valid }.
  • Leading NaNs are skipped to the first finite input; outputs before first + period - 1 are NaN.
  • Empty input: SwmaError::EmptyInputData. All values NaN: SwmaError::AllValuesNaN.
  • swma_into_slice: output length must equal input length; size mismatch returns SwmaError::InvalidPeriod.
Error Handling
use vectorta::indicators::moving_averages::swma::{swma, SwmaError};

match swma(&input) {
    Ok(output) => process_results(output.values),
    Err(SwmaError::EmptyInputData) => handle_empty(),
    Err(SwmaError::AllValuesNaN) => handle_all_nan(),
    Err(SwmaError::InvalidPeriod { period, data_len }) => handle_bad_period(period, data_len),
    Err(SwmaError::NotEnoughValidData { needed, valid }) => handle_insufficient(needed, valid),
}

Python Bindings

Quick Start
import numpy as np
from vectorta import swma

prices = np.array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5], dtype=np.float64)
values = swma(prices, period=5)
print(values)
Streaming
from vectorta import SwmaStream

stream = SwmaStream(period=5)
for price in [100, 101, 102, 103, 104, 105]:
    v = stream.update(float(price))
    if v is not None:
        handle(v)
Batch Processing
import numpy as np
from vectorta import swma_batch

prices = np.array([...], dtype=np.float64)
result = swma_batch(prices, period_range=(3, 20, 1))

print(result['values'].shape)  # (num_periods, len(prices))
print(result['periods'])

CUDA Acceleration

Python (Device Arrays)

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

# Option 1: One Series, Many Parameters (optimization)
from vectorta import swma_cuda_batch_dev
import numpy as np

prices = np.array([...], dtype=np.float64)
dev = swma_cuda_batch_dev(prices, period_range=(3, 64, 1), device_id=0)
# 'dev' is a device-backed array wrapper (float32).
# Option 2: Many Series, One Parameter Set (portfolio)
from vectorta import swma_cuda_many_series_one_param_dev
import numpy as np

# Time-major input [T, N] as float32
data_tm = np.array([...], dtype=np.float32)
dev = swma_cuda_many_series_one_param_dev(data_tm, period=5, device_id=0)

JavaScript/WASM Bindings

Basic Usage

Calculate SWMA in JavaScript/TypeScript:

import { swma_js } 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 SWMA with specified period
const result = swma_js(prices, 5);

// Result is a Float64Array
console.log('SWMA values:', result);

async function calculateSWMA(prices: Float64Array): Promise<Float64Array> {
  try {
    return swma_js(prices, 5);
  } catch (error) {
    console.error('SWMA calculation failed:', error);
    throw error;
  }
}
Memory-Efficient Operations

Use zero-copy operations for better performance with large datasets:

import { swma_alloc, swma_free, swma_into, memory } from 'vectorta-wasm';

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

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

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

// Calculate SWMA directly into allocated memory
// Args: in_ptr, out_ptr, len, period
swma_into(inPtr, outPtr, length, 5);

// Read results from WASM memory (slice() to copy out)
const swmaValues = new Float64Array(memory.buffer, outPtr, length).slice();

// Free allocated memory when done
swma_free(inPtr, length);
swma_free(outPtr, length);

console.log('SWMA values:', swmaValues);
Batch Processing

Test multiple period values efficiently:

import { swma_batch_js, swma_batch_metadata_js } from 'vectorta-wasm';

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

// Define parameter sweep for period
const start = 3, end = 20, step = 1;

// Get metadata about parameter combinations
const metadata = swma_batch_metadata_js(start, end, step);
const numCombos = metadata.length; // one value per period

// Calculate all combinations
const results = swma_batch_js(prices, start, end, step);

// Results is a flat array: [combo1_values..., combo2_values..., ...]
const resultMatrix: Float64Array[] = [];
for (let i = 0; i < numCombos; i++) {
  const row = results.slice(i * prices.length, (i + 1) * prices.length);
  resultMatrix.push(row);
}

// Access specific parameter combination results
const period = metadata[0];
const swmaValues = resultMatrix[0];

Performance Analysis

Comparison:
View:
Loading chart...

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

Related Indicators