Sine Weighted Moving Average (SINWMA)

Parameters: period = 14

Overview

The Sine Weighted Moving Average applies weights derived from a sine wave to create a smoothed average that emphasizes central values while de-emphasizing the edges. SINWMA calculates weights using the sine function evaluated at evenly spaced points across the period, producing a bell shaped distribution that peaks in the middle and tapers smoothly toward zero at both ends. The normalization ensures all weights sum to one, maintaining proper scaling while the symmetric weighting pattern reduces lag compared to simple moving averages. This sine windowing technique originates from signal processing where it minimizes spectral leakage and edge discontinuities. Traders appreciate SINWMA for its smooth curves that respond quickly to genuine price changes while filtering out noise more effectively than linear weighted or exponential moving averages. The indicator works particularly well for identifying trend direction without the choppy behavior common in simpler averaging methods, making it useful for both support and resistance identification and crossover strategies.

Implementation Examples

Compute SINWMA from a price slice or candles:

use vectorta::indicators::sinwma::{sinwma, SinWmaInput, SinWmaParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};

// From a price slice
let prices = vec![100.0, 102.0, 101.5, 103.0, 105.0, 104.5];
let params = SinWmaParams { period: Some(14) };
let input = SinWmaInput::from_slice(&prices, params);
let result = sinwma(&input)?;

// From Candles with defaults (period=14, source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = SinWmaInput::with_default_candles(&candles);
let result = sinwma(&input)?;

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

API Reference

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

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

// From candles with defaults (period=14, source="close")
SinWmaInput::with_default_candles(&Candles) -> SinWmaInput

// Compute
sinwma(&SinWmaInput) -> Result<SinWmaOutput, SinWmaError>
sinwma_with_kernel(&SinWmaInput, Kernel) -> Result<SinWmaOutput, SinWmaError>

// Zero-copy into preallocated output
sinwma_into_slice(&mut [f64], &SinWmaInput, Kernel) -> Result<(), SinWmaError>
Parameters Structure
pub struct SinWmaParams {
    pub period: Option<usize>, // Default: 14
}
Output Structure
pub struct SinWmaOutput {
    pub values: Vec<f64>, // Sine-weighted moving average values
}
Validation, Warmup & NaNs
  • period > 0 and period ≤ data.len(); otherwise SinWmaError::InvalidPeriod.
  • Requires at least period valid points after the first finite input; else SinWmaError::NotEnoughValidData.
  • If all inputs are NaN, returns SinWmaError::AllValuesNaN.
  • Weights are normalized; if the sine sum is effectively zero, returns SinWmaError::ZeroSumSines.
  • Warmup: indices before first_valid + period - 1 are NaN. Streaming returns None until filled.
Error Handling
use vectorta::indicators::sinwma::{sinwma, SinWmaError};

match sinwma(&input) {
    Ok(output) => process(output.values),
    Err(SinWmaError::EmptyInputData) =>
        eprintln!("Input data is empty"),
    Err(SinWmaError::AllValuesNaN) =>
        eprintln!("All input values are NaN"),
    Err(SinWmaError::InvalidPeriod { period, data_len }) =>
        eprintln!("Invalid period {} for data length {}", period, data_len),
    Err(SinWmaError::NotEnoughValidData { needed, valid }) =>
        eprintln!("Need {} valid points, only {}", needed, valid),
    Err(SinWmaError::ZeroSumSines { sum_sines }) =>
        eprintln!("Sum of sines too small: {}", sum_sines),
}

Python Bindings

Basic Usage

Calculate SINWMA using NumPy arrays (default period=14):

import numpy as np
from vectorta import sinwma

prices = np.array([100.0, 102.0, 101.5, 103.0, 105.0])

# Defaults (period=14)
result = sinwma(prices, period=14)

# Specify kernel for performance ("auto", "scalar", "avx2", "avx512")
result = sinwma(prices, period=20, kernel="avx2")

print(result)
Streaming Real-time Updates
from vectorta import SinWmaStream

stream = SinWmaStream(period=14)
for price in price_feed:
    val = stream.update(price)
    if val is not None:
        handle_value(val)
Batch Parameter Optimization
import numpy as np
from vectorta import sinwma_batch

prices = np.array([...], dtype=float)

# (start, end, step) for period
res = sinwma_batch(prices, period_range=(5, 30, 5))
values = res['values']  # shape: [num_periods, len(prices)]
periods = res['periods']
print(values.shape, periods)
CUDA Acceleration

CUDA-enabled Python APIs (when built with CUDA support):

# Requires vectorta built with CUDA + Python features
from vectorta import sinwma_cuda_batch_dev, sinwma_cuda_many_series_one_param_dev
import numpy as np

# One series, many parameters (device_id optional)
prices_f32 = np.array([...], dtype=np.float32)
res = sinwma_cuda_batch_dev(prices_f32, period_range=(5, 30, 1), device_id=0)

# Many series (time-major), one parameter
data_tm = np.array([...], dtype=np.float32)  # shape [T, N]
dev = sinwma_cuda_many_series_one_param_dev(data_tm, period=14, device_id=0)

JavaScript / WASM

Memory-Efficient Operations

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

import { sinwma_alloc, sinwma_free, sinwma_into, memory } from 'vectorta-wasm';

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

const inPtr = sinwma_alloc(length);
const outPtr = sinwma_alloc(length);

new Float64Array(memory.buffer, inPtr, length).set(prices);

// Args: in_ptr, out_ptr, len, period
sinwma_into(inPtr, outPtr, length, 14);

const values = new Float64Array(memory.buffer, outPtr, length).slice();

sinwma_free(inPtr, length);
sinwma_free(outPtr, length);

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

Test multiple periods efficiently in the browser:

import { sinwma_batch_js, sinwma_batch_metadata_js } from 'vectorta-wasm';

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

const periodStart = 5, periodEnd = 30, periodStep = 5; // 5,10,15,20,25,30

// Get metadata about period combinations
const periods = sinwma_batch_metadata_js(periodStart, periodEnd, periodStep);
const numCombos = periods.length;

// Compute all combinations (flat array)
const flat = sinwma_batch_js(prices, periodStart, periodEnd, periodStep);

// Reshape into matrix [rows x cols]
const rows = numCombos, cols = prices.length;
const matrix: number[][] = [];
for (let r = 0; r < rows; r++) {
  const start = r * cols;
  matrix.push(flat.slice(start, start + cols));
}

console.log('Periods:', periods);
console.log('First combo values:', matrix[0]);

Performance Analysis

Comparison:
View:
Loading chart...

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

Related Indicators