pub struct ZScoreNormalizer { /* private fields */ }Expand description
Rolling z-score normalizer over a sliding window of Decimal observations.
Maps each new sample to its z-score: (x - mean) / std_dev. The rolling
window maintains an O(1) mean and variance via incremental sum/sum-of-squares
tracking, with O(W) recompute only when a value is evicted.
Returns 0.0 when the window has fewer than 2 observations (variance is 0).
§Example
use fin_stream::norm::ZScoreNormalizer;
use rust_decimal_macros::dec;
let mut norm = ZScoreNormalizer::new(5).unwrap();
for v in [dec!(10), dec!(20), dec!(30), dec!(40), dec!(50)] {
norm.update(v);
}
// 30 is the mean; normalize returns 0.0
let z = norm.normalize(dec!(30)).unwrap();
assert!((z - 0.0).abs() < 1e-9);Implementations§
Source§impl ZScoreNormalizer
impl ZScoreNormalizer
Sourcepub fn new(window_size: usize) -> Result<Self, StreamError>
pub fn new(window_size: usize) -> Result<Self, StreamError>
Create a new z-score normalizer with the given rolling window size.
§Errors
Returns StreamError::ConfigError if window_size == 0.
Sourcepub fn update(&mut self, value: Decimal)
pub fn update(&mut self, value: Decimal)
Add a new observation to the rolling window.
Evicts the oldest value when the window is full, adjusting running sums
in O(1). No full recompute is needed unless eviction causes sum drift;
the implementation recomputes exactly when necessary via recompute.
Sourcepub fn normalize(&self, value: Decimal) -> Result<f64, StreamError>
pub fn normalize(&self, value: Decimal) -> Result<f64, StreamError>
Normalize value to a z-score using the current window’s mean and std dev.
Returns 0.0 if:
- The window has fewer than 2 observations (std dev undefined).
- The standard deviation is effectively zero (all window values identical).
§Errors
Returns StreamError::NormalizationError if the window is empty.
§Complexity: O(1)
Sourcepub fn mean(&self) -> Option<Decimal>
pub fn mean(&self) -> Option<Decimal>
Current rolling mean of the window, or None if the window is empty.
Sourcepub fn std_dev(&self) -> Option<f64>
pub fn std_dev(&self) -> Option<f64>
Current population standard deviation of the window.
Returns None if the window is empty. Returns Some(0.0) if fewer
than 2 observations are present (undefined variance, treated as zero)
or if all values are identical.
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if no observations have been added since construction or reset.
Sourcepub fn window_size(&self) -> usize
pub fn window_size(&self) -> usize
The configured window size.
Sourcepub fn is_full(&self) -> bool
pub fn is_full(&self) -> bool
Returns true when the window holds exactly window_size observations.
At full capacity the z-score calculation is stable; before this point the window may not be representative of the underlying distribution.
Sourcepub fn sum(&self) -> Option<Decimal>
pub fn sum(&self) -> Option<Decimal>
Running sum of all values currently in the window.
Returns None if the window is empty. Useful for deriving a rolling
mean without calling normalize.
Sourcepub fn variance(&self) -> Option<Decimal>
pub fn variance(&self) -> Option<Decimal>
Current population variance of the window.
Computed as E[X²] − (E[X])² from running sums in O(1). Returns
None if fewer than 2 observations are present (variance undefined).
Sourcepub fn std_dev_f64(&self) -> Option<f64>
pub fn std_dev_f64(&self) -> Option<f64>
Standard deviation of the current window as f64.
Returns None if the window has fewer than 2 observations.
Sourcepub fn variance_f64(&self) -> Option<f64>
pub fn variance_f64(&self) -> Option<f64>
Current window variance as f64 (convenience wrapper around variance).
Returns None if the window has fewer than 2 observations.
Sourcepub fn normalize_batch(
&mut self,
values: &[Decimal],
) -> Result<Vec<f64>, StreamError>
pub fn normalize_batch( &mut self, values: &[Decimal], ) -> Result<Vec<f64>, StreamError>
Feed a slice of values into the window and return z-scores for each.
Each value is first passed through update to advance
the rolling window, then normalized. The output has the same length as
values.
§Errors
Propagates the first StreamError returned by normalize.
Sourcepub fn is_outlier(&self, value: Decimal, z_threshold: f64) -> bool
pub fn is_outlier(&self, value: Decimal, z_threshold: f64) -> bool
Returns true if value is an outlier: its z-score exceeds z_threshold in magnitude.
Returns false when the window has fewer than 2 observations (z-score undefined).
A typical threshold is 2.0 (95th percentile) or 3.0 (99.7th percentile).
Sourcepub fn percentile_rank(&self, value: Decimal) -> Option<f64>
pub fn percentile_rank(&self, value: Decimal) -> Option<f64>
Percentile rank: fraction of window observations that are ≤ value.
Returns None if the window is empty. Range: [0.0, 1.0].
Sourcepub fn running_min(&self) -> Option<Decimal>
pub fn running_min(&self) -> Option<Decimal>
Minimum value seen in the current window.
Returns None when the window is empty.
Sourcepub fn running_max(&self) -> Option<Decimal>
pub fn running_max(&self) -> Option<Decimal>
Maximum value seen in the current window.
Returns None when the window is empty.
Sourcepub fn window_range(&self) -> Option<Decimal>
pub fn window_range(&self) -> Option<Decimal>
Range of values in the current window: running_max − running_min.
Returns None when the window is empty.
Sourcepub fn coefficient_of_variation(&self) -> Option<f64>
pub fn coefficient_of_variation(&self) -> Option<f64>
Coefficient of variation: std_dev / |mean|.
A dimensionless measure of relative dispersion. Returns None when the
window has fewer than 2 observations or when the mean is zero.
Sourcepub fn sample_variance(&self) -> Option<f64>
pub fn sample_variance(&self) -> Option<f64>
Population variance of the current window: std_dev².
Returns None when the window is empty (same conditions as
std_dev).
Sourcepub fn window_mean_f64(&self) -> Option<f64>
pub fn window_mean_f64(&self) -> Option<f64>
Current window mean as f64.
A convenience over calling mean() and then converting to f64.
Returns None when the window is empty.
Sourcepub fn is_near_mean(&self, value: Decimal, sigma_tolerance: f64) -> bool
pub fn is_near_mean(&self, value: Decimal, sigma_tolerance: f64) -> bool
Returns true if value is within sigma_tolerance standard
deviations of the window mean (inclusive).
Equivalent to |z_score(value)| <= sigma_tolerance. Returns false
when the window has fewer than 2 observations (z-score undefined).
Sourcepub fn window_sum(&self) -> Decimal
pub fn window_sum(&self) -> Decimal
Sum of all values currently in the window as Decimal.
Returns Decimal::ZERO on an empty window.
Sourcepub fn window_sum_f64(&self) -> f64
pub fn window_sum_f64(&self) -> f64
Sum of all values currently in the window as f64.
Returns 0.0 on an empty window.
Sourcepub fn window_max_f64(&self) -> Option<f64>
pub fn window_max_f64(&self) -> Option<f64>
Maximum value currently in the window as f64.
Returns None when the window is empty.
Sourcepub fn window_min_f64(&self) -> Option<f64>
pub fn window_min_f64(&self) -> Option<f64>
Minimum value currently in the window as f64.
Returns None when the window is empty.
Sourcepub fn window_span_f64(&self) -> Option<f64>
pub fn window_span_f64(&self) -> Option<f64>
Difference between the window maximum and minimum, as f64.
Returns None if the window is empty.
Sourcepub fn kurtosis(&self) -> Option<f64>
pub fn kurtosis(&self) -> Option<f64>
Excess kurtosis of the window: (Σ((x-mean)⁴/n) / std_dev⁴) - 3.
Returns None if the window has fewer than 4 observations or std dev is zero.
A normal distribution has excess kurtosis of 0; positive values indicate
heavier tails (leptokurtic); negative values indicate lighter tails (platykurtic).
Sourcepub fn is_extreme(&self, value: Decimal, sigma: f64) -> bool
pub fn is_extreme(&self, value: Decimal, sigma: f64) -> bool
Returns true if the z-score of value exceeds sigma in absolute terms.
Convenience wrapper around normalize for alert logic.
Returns false if the normalizer window is empty or std-dev is zero.
Sourcepub fn latest(&self) -> Option<Decimal>
pub fn latest(&self) -> Option<Decimal>
The most recently added value, or None if the window is empty.
Sourcepub fn percentile(&self, value: Decimal) -> Option<f64>
pub fn percentile(&self, value: Decimal) -> Option<f64>
Empirical percentile of value within the current window: fraction of values ≤ value.
Returns a value in [0.0, 1.0]. Returns None if the window is empty.
Sourcepub fn ema_z_score(
value: Decimal,
alpha: f64,
ema_mean: &mut f64,
ema_var: &mut f64,
) -> Option<f64>
pub fn ema_z_score( value: Decimal, alpha: f64, ema_mean: &mut f64, ema_var: &mut f64, ) -> Option<f64>
Stateless EMA z-score helper: updates running ema_mean and ema_var and returns
the z-score (value - ema_mean) / sqrt(ema_var).
alpha ∈ (0, 1] controls smoothing speed (higher = faster adaptation).
Initialize ema_mean = 0.0 and ema_var = 0.0 before first call.
Returns None if value cannot be converted to f64 or variance is still zero.
Sourcepub fn z_score_of_latest(&self) -> Option<f64>
pub fn z_score_of_latest(&self) -> Option<f64>
Z-score of the most recently added value.
Returns None if the window is empty or std-dev is zero.
Sourcepub fn ema_of_z_scores(&self, alpha: f64) -> Option<f64>
pub fn ema_of_z_scores(&self, alpha: f64) -> Option<f64>
Exponential moving average of z-scores for all values in the current window.
alpha is the smoothing factor (0 < alpha ≤ 1). Higher alpha gives more weight
to recent z-scores. Returns None if the window has fewer than 2 observations.
Sourcepub fn add_observation(&mut self, value: Decimal) -> &mut Self
pub fn add_observation(&mut self, value: Decimal) -> &mut Self
Chainable alias for update: feeds value into the window and returns &mut Self.
Sourcepub fn deviation_from_mean(&self, value: Decimal) -> Option<f64>
pub fn deviation_from_mean(&self, value: Decimal) -> Option<f64>
Signed deviation of value from the window mean, as f64.
Returns None if the window is empty.
Sourcepub fn trim_outliers(&self, sigma: f64) -> Vec<Decimal>
pub fn trim_outliers(&self, sigma: f64) -> Vec<Decimal>
Returns a Vec of window values that are within sigma standard deviations of the mean.
Useful for robust statistics after removing extreme outliers. Returns all values if std-dev is zero (no outliers possible), empty vec if window is empty.
Sourcepub fn rolling_zscore_batch(&mut self, values: &[Decimal]) -> Vec<Option<f64>>
pub fn rolling_zscore_batch(&mut self, values: &[Decimal]) -> Vec<Option<f64>>
Batch normalize: returns z-scores for each value as if they were added one-by-one.
Each z-score uses only the window state after incorporating that value.
The internal state is modified; call reset() if you need to restore it.
Returns None entries where normalization fails (window warming up or zero std-dev).
Sourcepub fn rolling_mean_change(&self) -> Option<f64>
pub fn rolling_mean_change(&self) -> Option<f64>
Change in mean between the first half and second half of the current window.
Splits the window in two, computes the mean of each half, and returns
second_half_mean - first_half_mean as f64. Returns None if the
window has fewer than 2 observations.
Sourcepub fn count_positive_z_scores(&self) -> usize
pub fn count_positive_z_scores(&self) -> usize
Count of window values whose z-score is strictly positive (above the mean).
Returns 0 if the window is empty or all values are equal (z-scores are all 0).
Sourcepub fn is_mean_stable(&self, threshold: f64) -> bool
pub fn is_mean_stable(&self, threshold: f64) -> bool
Returns true if the absolute change between first-half and second-half window means
is below threshold. A stable mean indicates the distribution is not trending.
Returns false if the window has fewer than 2 observations.
Sourcepub fn above_threshold_count(&self, z_threshold: f64) -> usize
pub fn above_threshold_count(&self, z_threshold: f64) -> usize
Count of window values whose absolute z-score exceeds z_threshold.
Returns 0 if the window has fewer than 2 observations or std-dev is zero.
Sourcepub fn mad(&self) -> Option<Decimal>
pub fn mad(&self) -> Option<Decimal>
Median Absolute Deviation (MAD) of the current window.
MAD = median(|x_i - median(window)|). Returns None if the window
is empty.
Sourcepub fn robust_z_score(&self, value: Decimal) -> Option<f64>
pub fn robust_z_score(&self, value: Decimal) -> Option<f64>
Robust z-score: (value - median) / MAD.
More resistant to outliers than the standard z-score. Returns None
when the window is empty or MAD is zero.