Back To Top
Experience the Future of Intelligent Investing Today
We present a way to measure how far price moves from where most volume actually traded and whether that move was normal or extreme.
Not just price versus moving average. Not just volume spikes. Something adaptive. Something that reacts when the market stretches too far, too fast.
The oscillator presented here blends volume, price, and volatility into a single signal.
It builds a rolling volume-weighted average price, then measures how far price pulls away from that anchor, scaled by recent volatility.
When price accelerates away from its volume-weighted anchor, the oscillator responds. When it snaps back, the signal softens.
In this guide, we’ll discuss:
This oscillator measures how far price moves from its recent volume-weighted average — and whether that move is significant, based on recent behavior.
At the center is VWAP: the volume-weighted average price. It’s not just a simple moving average. It anchors price to volume to show where most trading activity occurred. The formula looks like this:
This gives more weight to prices that traded on higher volume. So, if most of the day’s volume clustered around a certain price, that level pulls the VWAP closer to it.
In this oscillator, we calculate VWAP using a rolling window. But instead of updating it every bar, we refresh it every few bars — for example, every 10. This gives the profile time to form while staying responsive to change.
Next, we measure how much price typically deviates from this VWAP during the lookback period. This isn’t a standard deviation. It’s a volume-weighted average of absolute deviations, calculated like this:
This tells us how “normal” it is for price to stray from the VWAP, based on both recent volatility and volume distribution. That deviation acts as a scale for the oscillator.
Now we compute the raw oscillator:
The idea is simple:
Finally, we smooth this signal with an exponential moving average. This makes it readable without killing the reactivity.
We start by loading daily price and volume data for a specific ticker. In this case, it’s ASML.AS
, but you can swap in any symbol supported by Yahoo Finance.
The dataset spans from January 2022 to December 2025. Once downloaded, we standardize the column names to keep things consistent across the analysis. Specifically:
This keeps the calculations clean later on, especially when referencing columns inside rolling windows or visualizations.
Here’s the setup code:
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
plt.style.use("dark_background")
# Step 1: Data Download & Preprocessing
TICKER = "ASML.AS" # Stock symbol
START_DATE = "2022-01-01"
END_DATE = "2025-12-31"
# Download daily data
df = yf.download(TICKER, start=START_DATE, end=END_DATE, interval="1d")
if isinstance(df.columns, pd.MultiIndex):
df.columns = df.columns.get_level_values(0)
df.dropna(inplace=True)
# Create standard column names for ease of use
df["Price"] = df["Close"]
df["Vol"] = df["Volume"]
df["Date"] = df.index
We start with a rolling lookback window — for example, the last 50 bars. Within that window, we compute the VWAP.
Next, we calculate a volume-weighted deviation from that VWAP. This tells us how far, on average, price tends to move away from the VWAP during the lookback period.
It’s calculated as:
Unlike standard deviation, this method weights each absolute price deviation by its volume share. That means larger trades have a bigger influence on the deviation scale.
Newsletter