Slope Adaptive Moving Average (SAMA)
length = 200 | maj_length = 14 | min_length = 6 Overview
The Slope Adaptive Moving Average dynamically adjusts its responsiveness by measuring where current price falls within a recent high to low range. SAMA computes the highest and lowest prices over an extended lookback period, then determines price position as a ratio within that range to derive an adaptive smoothing factor. When price trades near range extremes, the indicator blends toward a faster minor exponential moving average to capture trend acceleration, while prices in the middle of the range shift toward a slower major EMA for stability. This position based adaptation allows SAMA to respond quickly during breakouts and trending moves while remaining smooth during consolidation phases. The calculation normalizes the position ratio and interpolates between two EMA alpha values, producing a single adaptive moving average that naturally adjusts to market structure. Traders use SAMA for dynamic support and resistance that adapts to volatility, with the indicator staying close to price during trends and widening distance during ranges.
Implementation Examples
Get started with SAMA using slices or candles:
use vectorta::indicators::moving_averages::sama::{sama, SamaInput, SamaParams};
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 = SamaParams { length: Some(200), maj_length: Some(14), min_length: Some(6) };
let input = SamaInput::from_slice(&prices, params);
let out = sama(&input)?;
// From candles with defaults (source="close")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = SamaInput::with_default_candles(&candles);
let out = sama(&input)?;
for v in out.values { println!("SAMA: {}", v); } API Reference
Input Methods ▼
// From price slice
SamaInput::from_slice(&[f64], SamaParams) -> SamaInput
// From candles with custom source
SamaInput::from_candles(&Candles, &str, SamaParams) -> SamaInput
// From candles with default params (close prices; 200/14/6)
SamaInput::with_default_candles(&Candles) -> SamaInput Parameters Structure ▼
pub struct SamaParams {
pub length: Option<usize>, // Default: 200
pub maj_length: Option<usize>, // Default: 14
pub min_length: Option<usize>, // Default: 6
} Output Structure ▼
pub struct SamaOutput {
pub values: Vec<f64>, // Adaptive MA values
} Validation, Warmup & NaNs ▼
length > 0,maj_length > 0,min_length > 0. Alsolength + 1 ≤ data.len()orSamaError::InvalidPeriod.- Requires at least one valid sample after the first finite value; otherwise
SamaError::NotEnoughValidData. - Indices before the first finite input are
NaN. First finite output is seeded to the first finite price (Pine‑compatible warmup). - Batch mode:
NaNinputs at indexiproduceNaNati. Streaming:update(NaN)leaves state unchanged and returns the current value if initialized.
Error Handling ▼
use vectorta::indicators::moving_averages::sama::{sama, SamaError};
match sama(&input) {
Ok(output) => process(output.values),
Err(SamaError::EmptyInputData) => eprintln!("empty input"),
Err(SamaError::AllValuesNaN) => eprintln!("all values are NaN"),
Err(SamaError::InvalidPeriod { period, data_len }) => {
eprintln!("invalid period: {} for data_len {}", period, data_len)
}
Err(SamaError::NotEnoughValidData { needed, valid }) => {
eprintln!("need {} data points, only {} valid", needed, valid)
}
} Python Bindings
Basic Usage ▼
Calculate SAMA using NumPy arrays (length, maj_length, min_length are required):
import numpy as np
from vectorta import sama
prices = np.array([100.0, 102.0, 101.5, 103.0, 105.0, 104.5])
# Specify parameters explicitly; choose kernel optionally ("auto", "avx2", ...)
values = sama(prices, length=200, maj_length=14, min_length=6, kernel="auto")
print(values) Streaming Real-time Updates ▼
from vectorta import SamaStream
stream = SamaStream(length=200, maj_length=14, min_length=6)
for price in feed:
value = stream.update(price)
if value is not None:
print("SAMA:", value) Batch Parameter Optimization ▼
import numpy as np
from vectorta import sama_batch
prices = np.array([...])
results = sama_batch(
prices,
length_range=(100, 300, 50),
maj_length_range=(10, 20, 2),
min_length_range=(4, 12, 2),
kernel="auto",
)
# Results is a dict-like object with 'values', 'combos', 'rows', 'cols'
print(results["rows"], results["cols"]) CUDA Acceleration ▼
CUDA support for SAMA is currently under development. The API will follow the same pattern as other CUDA-enabled indicators.
# Coming soon: CUDA-accelerated SAMA calculations
# from vectorta import sama_cuda_batch, sama_cuda_many_series_one_param
# import numpy as np
#
# # One series, many parameter combinations
# results = sama_cuda_batch(
# data=prices,
# length_range=(100, 300, 1),
# maj_length_range=(10, 20, 1),
# min_length_range=(4, 12, 1),
# device_id=0,
# )
#
# # Many series, one parameter set
# out = sama_cuda_many_series_one_param(
# data_tm=portfolio_data, # [T, N]
# length=200, maj_length=14, min_length=6,
# device_id=0,
# ) JavaScript/WASM Bindings
Basic Usage ▼
Calculate SAMA in JavaScript/TypeScript:
import { sama_js } from 'vectorta-wasm';
const prices = new Float64Array([100, 102, 101.5, 103, 105, 104.5]);
const values = sama_js(prices, 200, 14, 6);
console.log('SAMA:', values); Memory-Efficient Operations ▼
Use zero-copy operations for large datasets:
import { sama_alloc, sama_free, sama_into, memory } from 'vectorta-wasm';
const prices = new Float64Array([/* your data */]);
const len = prices.length;
const inPtr = sama_alloc(len);
const outPtr = sama_alloc(len);
new Float64Array(memory.buffer, inPtr, len).set(prices);
sama_into(inPtr, outPtr, len, 200, 14, 6);
const out = new Float64Array(memory.buffer, outPtr, len).slice();
sama_free(inPtr, len);
sama_free(outPtr, len); Batch Processing ▼
Test multiple combinations using unified batch API:
import { sama_batch } from 'vectorta-wasm';
const prices = new Float64Array([/* historical prices */]);
const config = {
length_range: [100, 300, 50],
maj_length_range: [10, 20, 2],
min_length_range: [4, 12, 2],
};
const result = sama_batch(prices, config);
// result = { values: Float64Array(flat), combos: SamaParams[], rows, cols }
console.log(result.rows, result.cols); Performance Analysis
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05