Skip to content

Volume Profile

Family: Flow surveillance

What it computes

Emits VolumeProfileTick ticks carrying total_volume, poc_price, vah, val, buckets_used, buckets[(rank, price_bucket, volume)] off stock trade tape.

Available on the live, historical, and replay drives.

Methodology

Per-price-bucket volume distribution with Point of Control + Dalton-Jones-Dalton (1990) value-area envelope per Steidlmayer (1986) Market Profile.

See the methodology overview for the citation index.

Inputs

Stock trade tape.

Key outputs

Total_volume, poc_price, vah, val, buckets_used, buckets[(rank, price_bucket, volume)]. The full field set is in the tick table below.

Output schema (VolumeProfileTick)

The field / type / description table below is regenerated from the VolumeProfileTick 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 (interned).
datei32Trading-session date (YYYYMMDD) at emission time.
ms_of_dayi32Milliseconds since midnight at emission time.
total_volumeu64Total volume inside the rolling window.
poc_pricef64Point of Control — the price-bucket lower bound carrying the maximum volume. NaN when the window is empty.
vahf64Value-area high — the upper price boundary of the value_area_fraction (default 70%) volume envelope around the POC. NaN when the window is empty.
valf64Value-area low — the lower price boundary of the value-area envelope. NaN when the window is empty.
buckets_usedi32Unique bucket count contributing to the profile.
bucketsVec<VolumeBucketRow>Top-N buckets by volume, descending. Bounded by top_n_buckets.

Configuration (VolumeProfileParams)

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

FieldTypeDescription
contractsSecurityFilterContracts the subscription tracks.
conditionsConditionPolicyTrade-condition admission policy.
venuesExchangeFilterExchange / venue admission policy.
bucket_sizef64Per-bucket price width in dollars. Defaults to [DEFAULT_BUCKET_SIZE] (0.05).
window_msi32Rolling-window horizon in milliseconds. Defaults to [DEFAULT_WINDOW_MS] (300_000 ms).
min_emit_interval_msi32Minimum interval between per-symbol emissions in milliseconds. Defaults to [DEFAULT_MIN_EMIT_INTERVAL_MS] (1_000 ms).
top_n_bucketsu32Maximum ladder depth — the top-N buckets by volume publish on every tick. Defaults to [DEFAULT_TOP_N_BUCKETS] (32).
value_area_fractionf64Value-area fraction in (0, 1]. Defaults to [DEFAULT_VALUE_AREA_FRACTION] (0.70).

Example

Python

python
import kairos_thetadata as kt

client = kt.Client.connect(kt.Credentials.from_env())

def on_event(row):
    print(row)

sub = client.live().volume_profile(["QQQ"]).on_event(on_event)
sub.wait(timeout_seconds=60.0)

TypeScript

typescript
import { Client, Credentials } from "kairos-thetadata";

const client = await Client.connect(Credentials.fromEnv());

await client
  .live()
  .volumeProfile(["QQQ"])
  .onEvent((tick) => {
    console.log(tick);
  });

Rust

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

use kairos::{Client, VolumeProfileRow};

# fn run() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::connect(("me@example.com", "secret"))?;

let sub = client
    .live()
    .volume_profile(["QQQ"])
    .on_event(|row: &VolumeProfileRow| println!("poc_price={} total_volume={}", row.poc_price, row.total_volume))?;
// ... later ...
sub.unsubscribe();
# Ok(())
# }

Proprietary. All rights reserved.