Volume Weighted Average Price (VWAP)

Parameters: anchor = 1d

Overview

Volume Weighted Average Price (VWAP) calculates the average price weighted by trading volume within specified time anchors, serving as a key benchmark for institutional execution quality and intraday fair value. The indicator multiplies each price by its corresponding volume, sums these products across the anchor period, then divides by total volume to produce the volume-weighted mean. Unlike simple moving averages, VWAP gives greater importance to prices where substantial trading occurred, reflecting true market consensus during active periods. Traders reset VWAP at anchor boundaries such as daily opens, 4-hour sessions, or monthly starts, creating fresh reference levels that adapt to each new trading period. When price trades above VWAP, it suggests bullish sentiment with buyers willing to pay premium prices; conversely, prices below VWAP indicate bearish pressure. The implementation supports flexible anchor specifications from minutes to months, with the default daily anchor aligning with standard institutional practices. Many algorithms use VWAP as a target price, attempting to achieve fills near this volume-weighted benchmark to minimize market impact.

When using candle data, this module accepts any price source string via from_candles(..., source) and defaults to hlc3 in with_default_candles.

Implementation Examples

Compute VWAP from raw arrays or candle data:

use vectorta::indicators::vwap::{vwap, VwapInput, VwapParams};
use vectorta::utilities::data_loader::{Candles, read_candles_from_csv};

// From raw slices (timestamps: ms since epoch)
let timestamps = vec![/* i64 timestamps as f64 in files; here i64 in Rust */ 1633046400000_i64, 1633046460000, 1633046520000];
let volumes = vec![1200.0, 800.0, 1500.0];
let prices  = vec![100.0, 101.0, 100.5];
let params = VwapParams { anchor: Some("1d".to_string()) };
let input = VwapInput::from_slice(&timestamps, &volumes, &prices, params);
let out = vwap(&input)?;
for v in out.values { println!("VWAP: {}", v); }

// From candles (defaults: source = "hlc3", anchor = "1d")
let candles: Candles = read_candles_from_csv("data/sample.csv")?;
let input = VwapInput::with_default_candles(&candles);
let out = vwap(&input)?;

API Reference

Input Methods
// From raw slices (timestamps ms as i64)
VwapInput::from_slice(&[i64], &[f64], &[f64], VwapParams) -> VwapInput

// From candles with custom source (e.g., "close", "hlc3")
VwapInput::from_candles(&Candles, &str, VwapParams) -> VwapInput

// From candles plus external price vector
VwapInput::from_candles_plus_prices(&Candles, &[f64], VwapParams) -> VwapInput

// Default candles (source = "hlc3", anchor = "1d")
VwapInput::with_default_candles(&Candles) -> VwapInput
Parameters Structure
pub struct VwapParams {
    pub anchor: Option<String>, // Default: "1d"
}
Output Structure
pub struct VwapOutput {
    pub values: Vec<f64>, // VWAP per input index
}
Validation, Warmup & NaNs
  • timestamps.len == prices.len == volumes.len else VwapError::MismatchTimestampsPricesVolumes.
  • anchor must contain a positive number and one unit; units: m, h, d, M. Uppercase H/D normalized.
  • On each anchor boundary, accumulators reset; value is vol_price_sum/volume_sum if volume_sum > 0, otherwise NaN.
  • Month anchors use calendar-aware bucketing; invalid timestamps yield VwapError::MonthConversionError.
  • Streaming: VwapStream::update returns Some(vwap) when volume_sum > 0, otherwise None.
Error Handling
use vectorta::indicators::vwap::{vwap, VwapInput, VwapParams, VwapError};

match vwap(&input) {
    Ok(output) => process(output.values),
    Err(VwapError::MismatchTimestampsPricesVolumes { timestamps, prices, volumes }) => {
        eprintln!("Length mismatch: ts={}, prices={}, vols={}", timestamps, prices, volumes);
    }
    Err(VwapError::MismatchPricesVolumes { prices, volumes }) => {
        eprintln!("Out slice size mismatch: prices={}, dst={}", prices, volumes);
    }
    Err(VwapError::NoData) => eprintln!("No data provided"),
    Err(VwapError::ParseAnchorError { msg }) => eprintln!("Anchor parse error: {}", msg),
    Err(VwapError::UnsupportedAnchorUnit { unit_char }) => eprintln!("Unsupported unit: {}", unit_char),
    Err(VwapError::MonthConversionError { ts_ms }) => eprintln!("Month conversion failed for {}", ts_ms),
}

Python Bindings

Basic Usage

Compute VWAP from timestamped volume and price arrays:

import numpy as np
from vectorta import vwap

# Arrays: timestamps (ms, int64), volumes/prices (float64)
timestamps = np.array([1633046400000, 1633046460000, 1633046520000], dtype=np.int64)
volumes    = np.array([1200.0, 800.0, 1500.0], dtype=np.float64)
prices     = np.array([100.0, 101.0, 100.5], dtype=np.float64)

# Default anchor is "1d"; kernel can be 'auto' or 'scalar'
values = vwap(timestamps, volumes, prices, anchor="1d", kernel="auto")
print(values)
Streaming Real-time Updates

One call per tick; returns None until volume_sum > 0 in the current anchor:

from vectorta import VwapStream

stream = VwapStream(anchor="1d")
for ts, price, vol in tick_feed:
    v = stream.update(ts, price, vol)
    if v is not None:
        print("VWAP:", v)
Batch Parameter Sweep

Compute many anchors at once and inspect rows:

import numpy as np
from vectorta import vwap_batch

timestamps = np.array([...], dtype=np.int64)
volumes    = np.array([...], dtype=np.float64)
prices     = np.array([...], dtype=np.float64)

res = vwap_batch(timestamps, volumes, prices, anchor_range=("1d", "3d", 1), kernel="auto")
print(res['values'].shape)  # (rows, cols)
print(res['anchors'])       # ["1d", "2d", "3d"]
CUDA Acceleration

If built with CUDA, a device API is available:

# Requires build with Python + CUDA features
from vectorta import vwap_cuda_batch_dev

res_dev = vwap_cuda_batch_dev(
    timestamps, volumes, prices,
    anchor_range=("1d", "3d", 1),
    device_id=0
)
# Returns a device-backed array wrapper (f32); see DeviceArrayF32Py

JavaScript/WASM Bindings

Basic Usage

Compute VWAP in JavaScript/TypeScript with timestamp, volume, and price arrays:

import { vwap_js } from 'vectorta-wasm';

const timestamps = new Float64Array([1633046400000, 1633046460000, 1633046520000]);
const volumes    = new Float64Array([1200, 800, 1500]);
const prices     = new Float64Array([100.0, 101.0, 100.5]);

// Anchor defaults to "1d"; kernels: 'auto' | 'scalar' | 'scalar_batch'
const values = vwap_js(timestamps, volumes, prices, '1d', 'auto');
console.log(values);
Memory-Efficient Operations

Use vwap_into with manual allocation:

import { vwap_alloc, vwap_free, vwap_into, memory } from 'vectorta-wasm';

const len = prices.length;
const tsPtr = vwap_alloc(len);
const volPtr = vwap_alloc(len);
const prPtr = vwap_alloc(len);
const outPtr = vwap_alloc(len);

new Float64Array(memory.buffer, tsPtr, len).set(timestamps);
new Float64Array(memory.buffer, volPtr, len).set(volumes);
new Float64Array(memory.buffer, prPtr, len).set(prices);

// Args: ts_ptr, vol_ptr, pr_ptr, out_ptr, len, anchor
vwap_into(tsPtr, volPtr, prPtr, outPtr, len, '1d');
const out = new Float64Array(memory.buffer, outPtr, len).slice();

vwap_free(tsPtr, len); vwap_free(volPtr, len); vwap_free(prPtr, len); vwap_free(outPtr, len);
Batch Processing

Enumerate anchors and compute all series:

import { vwap_batch, vwap_batch_metadata_js } from 'vectorta-wasm';

const anchors = vwap_batch_metadata_js('1d', '3d', 1); // ['1d','2d','3d']
const packed = vwap_batch(timestamps, volumes, prices, '1d', '3d', 1);
// 'packed' returns a flat array of size rows*len and metadata via anchors
// Reshape as needed for your UI

Performance Analysis

Comparison:
View:
Loading chart...

AMD Ryzen 9 9950X (CPU) | NVIDIA RTX 4090 (GPU) | Benchmarks: 2026-01-05

Related Indicators