SGF
period = 21 | poly_order = 2 Overview
SGF is an endpoint Savitzky-Golay smoother. It builds coefficients for the requested window and polynomial order, applies those weights to each rolling slice, and emits the fitted value at the current bar rather than a centered value that would require future samples.
That makes the indicator useful as a smooth moving-average-style trend line with less lag than a plain average, while still preserving local curvature. The stream path uses the same endpoint weights and starts returning values once the effective window is filled.
Defaults: `period = 21` and `poly_order = 2`.
Implementation Examples
Run SGF on candle closes or any direct numeric slice.
use vector_ta::indicators::moving_averages::sgf::{sgf, SgfInput, SgfParams};
use vector_ta::utilities::data_loader::{Candles, read_candles_from_csv};
let out = sgf(&SgfInput::from_slice(
&close,
SgfParams {
period: Some(21),
poly_order: Some(2),
},
))?;
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let candle_out = sgf(&SgfInput::with_default_candles(&candles))?;
println!("last sgf = {:?}", out.values.last());
println!("candle sgf = {:?}", candle_out.values.last()); API Reference
Input Methods ▼
SgfInput::from_candles(&Candles, "close", SgfParams) -> SgfInput
SgfInput::from_slice(&[f64], SgfParams) -> SgfInput
SgfInput::with_default_candles(&Candles) -> SgfInput Parameters Structure ▼
pub struct SgfParams {
pub period: Option<usize>, // default 21
pub poly_order: Option<usize>, // default 2
} Output Structure ▼
pub struct SgfOutput {
pub values: Vec<f64>,
} Validation, Warmup & NaNs ▼
- The input slice must not be empty and must contain at least one finite value.
periodmust resolve to an odd effective period of at least3and no larger than the available data length.poly_ordermust stay strictly below the effective period.- The direct and batch paths require at least
effective_periodvalid bars after the first finite value. - The stream path returns
Noneuntil the effective period has filled its ring buffer. - Batch mode rejects non-batch kernels and validates both
periodandpoly_ordersweep ranges.
Builder, Streaming & Batch APIs ▼
SgfBuilder::new()
.period(usize)
.poly_order(usize)
.kernel(Kernel)
.apply(&Candles)
.apply_slice(&[f64])
.into_stream()
SgfStream::try_new(params)
stream.update(f64) -> Option<f64>
SgfBatchBuilder::new()
.kernel(Kernel)
.period_range(start, end, step)
.period_static(value)
.poly_order_range(start, end, step)
.poly_order_static(value)
.apply_slice(&[f64])
.apply_candles(&Candles, "close") Python Bindings
Python exposes one scalar function, one stream class, and one batch helper. The scalar path returns one NumPy
array, the stream returns either one floating-point value or None, and the batch helper returns a
dictionary containing the value matrix plus the expanded period and polynomial-order axes.
from vector_ta import sgf, sgf_batch, SgfStream
values = sgf(close, period=21, poly_order=2)
stream = SgfStream(period=21, poly_order=2)
point = stream.update(close[-1])
batch = sgf_batch(
close,
period_range=(15, 31, 2),
poly_order_range=(1, 3, 1),
)
print(batch["values"].shape)
print(batch["periods"])
print(batch["poly_orders"]) JavaScript/WASM Bindings
The WASM layer exposes a scalar helper, a config-driven batch helper, and low-level allocation and into-buffer APIs. The high-level batch call returns rows, cols, values, and parameter combos, while the low-level batch path writes one flattened matrix and returns the number of parameter rows.
import init, {
sgf_js,
sgf_batch,
sgf_alloc,
sgf_free,
sgf_into,
sgf_batch_into,
} from "vector-ta-wasm";
await init();
const values = sgf_js(close, 21, 2);
const batch = sgf_batch(close, {
period_range: [15, 31, 2],
poly_order_range: [1, 3, 1],
}); CUDA Bindings (Rust)
Additional details for the CUDA bindings can be found inside the VectorTA repository.
Performance Analysis
Across sizes, Rust CPU runs about 1.14× faster than Tulip C in this benchmark.
AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU)