Skip to content

VolumeAnomaly

What it computes

Z-score-based volume-anomaly detector over daily stock volume. The analytic maintains a rolling N-day baseline per symbol; on session rollover it fires one tick carrying:

  • today_volume
  • rolling_mean
  • rolling_stddev
  • z_score = (today_volume − rolling_mean) / rolling_stddev
  • multiple = today_volume / rolling_mean

Methodology

Sample z-score against a rolling N-day mean / stddev baseline. The default window is 20 trading days; configurable per spec via VolumeAnomalyParams::window_days. Methodology parity with Bloomberg AVOL / Refinitiv VOL_RATIO.

Inputs

  • Stock TradeTick (accumulates today's volume).
  • A rolling N-day baseline accumulator seeded from engine daily-close cache at boot.

Output schema (VolumeAnomalyTick)

The field / type / description table below is regenerated from the VolumeAnomalyTick Rust source by docs-site/scripts/inject-doc-tables.ts on every npm run docs:build. Do not hand-edit between the sentinels.

FieldTypeDescription
symbolArc<str>Underlying symbol.
datei32Session date that just closed (YYYYMMDD).
today_volumeu64Total admitted volume for the just-closed session (shares).
rolling_meanf64Rolling-window arithmetic mean of daily volumes before today. NaN until the baseline has at least one daily observation.
rolling_stddevf64Rolling-window sample standard deviation of daily volumes. NaN until the baseline has at least two observations.
z_scoref64(today_volume - rolling_mean) / rolling_stddev. NaN if either of the baseline components is NaN or stddev == 0.
multiplef64today_volume / rolling_mean. NaN if baseline mean is NaN or 0.
is_unusualboolz_score >= spec.z_score_threshold. false when z_score is NaN.
warmingbooltrue while the rolling baseline is not yet established — the first session-rollover per symbol has no prior daily observation, so rolling_mean / rolling_stddev / z_score / multiple are NaN. Consumers gate on this flag instead of NaN-probing every statistical field; today_volume is always valid.

Configuration (VolumeAnomalyRequest)

Regenerated from the VolumeAnomalyRequest Rust source — see the note above.

FieldTypeDescription
contractsSecurityFilterContracts the subscription tracks. Stocks only.
baseline_daysusizeDaily-baseline window. Default 22 (one month of trading days).
z_score_thresholdf64z_score >= threshold flags the day as unusual. Default 2.0 (≈ 97.5th percentile under a normal-distribution assumption).
conditionsConditionPolicyTrade-condition admission policy.
venuesExchangeFilterExchange / venue admission policy.

Operational characteristics

  • Per-tick latency. O(1) — single volume accumulator update.
  • Allocation discipline. Baseline window is a pre-sized RollingWindow; no hot-path allocations.
  • Emission cadence. One emission per (symbol, session-rollover).
  • Replay parity. Deterministic given identical input tick order.

Example

rust
// Cargo.toml:
//   kairos = "0.1"

use kairos::{Client, VolumeAnomalyRow};

let client = Client::connect(("me@example.com", "secret"))?;

let sub = client
    .live()
    .volume_anomaly(["QQQ"])
    .baseline_days(30)
    .z_score_threshold(3.0)
    .on_event(|row: &VolumeAnomalyRow| println!("z_score={} multiple={}", row.z_score, row.multiple))?;
// ... later ...
sub.unsubscribe();

Proprietary. All rights reserved.