Deep Dive5 min

How we compute VWAP across venues

Our aggregation is simple enough to publish in full. Below is the exact function that runs on every exchange tick — it's what produces the numbers you see everywhere else on this site. No hidden weighting, no magic constants, no proprietary model.

recalculateVWAP — runs on every tick● live in production
function recalculateVWAP(symbol) {
  const sources = exchangePrices[symbol];
  if (!sources) return;

  // Drop any venue whose last tick is older than 60 seconds.
  const entries = Object.entries(sources).filter(
    ([, d]) => d.price > 0 && Date.now() - d.timestamp < 60_000
  );
  if (entries.length === 0) return;

  let totalWeight = 0, weightedSum = 0, totalVolume = 0, priceSum = 0;

  for (const [, data] of entries) {
    const w = data.volume || 1;
    weightedSum += data.price * w;   // VWAP numerator
    totalWeight  += w;               // VWAP denominator
    totalVolume  += data.volume || 0;
    priceSum     += data.price;      // simple mean input
  }

  const vwap = weightedSum / totalWeight;
  const mean = priceSum / entries.length;

  // Exchange feeds report 24h volume in base currency (coin units).
  // Multiply by VWAP to express in USD notional.
  const volumeUsd = totalVolume * vwap;

  // ... store { price: mean, vwap, volume24h: volumeUsd, ... }
}

Inputs

Persistent outbound WebSocket connections to Binance, Coinbase, Kraken (v2), and OKX. Each connector normalises its venue's ticker schema into { price, volume, timestamp } per symbol.

Aggregation

On every tick we recompute two numbers per symbol:

  • price — simple arithmetic mean across live venues. Useful as a sanity check against the weighted number.
  • vwapΣ(price_i × volume_i) / Σ(volume_i) across live venues.

Staleness rejection

A venue's tick is excluded from the aggregate if it's older than 60 seconds. A venue whose WebSocket disconnects drops out of the weighted sum immediately on close event.

Volume expressed in USD

Every venue reports 24h volume in base currency (coin units). We multiply by VWAP to give a USD-notional number. This means cross-venue volume is summed — which over-counts activity that touches multiple venues, but matches the convention CoinGecko and CMC use.

What we don't do yet

  • Outlier rejection beyond staleness — if a single venue's price goes wild, it's included. Adding MAD-based rejection is on the roadmap.
  • Signed quotes — every tick will ship with an ed25519 signature in the paid tier.
  • Per-venue tick broadcast — the free WS feed currently emits aggregated numbers only.
Explainer — no market claims.More intel →