Sine Weighted Moving Average (SINWMA)
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 > 0andperiod ≤ data.len(); otherwiseSinWmaError::InvalidPeriod.- Requires at least
periodvalid points after the first finite input; elseSinWmaError::NotEnoughValidData. - If all inputs are
NaN, returnsSinWmaError::AllValuesNaN. - Weights are normalized; if the sine sum is effectively zero, returns
SinWmaError::ZeroSumSines. - Warmup: indices before
first_valid + period - 1areNaN. Streaming returnsNoneuntil 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
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