VWAP strategy in Python

VWAP is the intraday fair-value benchmark traders watch, here is a VWAP strategy in Python, backtested on intraday bars.

What is VWAP?

The volume-weighted average price (VWAP) is the average price over a period, weighted by volume. Institutions use it as an execution benchmark and a fair-value reference: trading above VWAP is read as intraday strength, below it as weakness.

A VWAP strategy uses that reference as a directional filter or a reversion anchor. Here we use it as a trend filter, holding long only while price trades above VWAP, the simplest, most common application.

The logic

Manifold-BT exposes VWAP as a built-in column, so no manual computation is needed. We compare the close to VWAP on every bar.

The rule is a clean intraday filter: long whenever the close is above VWAP, flat whenever it slips below. It keeps you on the strong side of the session and out during weakness.

VWAP in Python

Here is the full strategy in the Manifold-BT expression DSL. It imports manifoldbt, builds the signal, configures realistic execution, and runs the backtest against Rust.

vwap.py
import manifoldbt as mbt
from manifoldbt.indicators import close, vwap
from manifoldbt.helpers import time_range, Slippage, Interval

# Long while price trades above the volume-weighted average price
strategy = (
    mbt.Strategy.create("vwap_trend")
    .signal("vwap", vwap)
    .size(mbt.when(close > vwap, 1.0, 0.0))
)

start, end = time_range("2024-01-01", "2026-01-01")
config = mbt.BacktestConfig(
    universe={"binance": ["BTCUSDT"]},
    time_range_start=start,
    time_range_end=end,
    bar_interval=Interval.minutes(15),
    initial_capital=10_000,
    fees=mbt.FeeConfig.binance_perps(),
    slippage=Slippage.fixed_bps(2),
    warmup_bars=1,
)
store = mbt.ingest(provider="binance", symbol="BTCUSDT", symbol_id=1,
                   interval="15m", start="2024-01-01T00:00:00Z",
                   end="2026-01-01T00:00:00Z")
result = mbt.run(strategy, config, store)
print(result.summary())
mbt.plot.tearsheet(result, show=True)

Backtest it with Manifold-BT

VWAP strategies are intraday by nature, so we run 15-minute bars. At this frequency fees and slippage dominate the outcome, which is exactly why a realistic execution model is non-negotiable here.

Treat this as a building block: VWAP works best combined with a second signal (a momentum or volatility filter) rather than alone. Add a confirming signal and re-backtest to see the effect on the trade count and Sharpe.

Backtest configuration
Universe{"binance": ["BTCUSDT"]}
Bar interval15m
FeesFeeConfig.binance_perps()
Slippagefixed 2 bps
Warmup1 bar
Sample tearsheet (illustrative, not a forecast)
Total return+19.7%
Sharpe0.84
Max drawdown-12.1%
Win rate49%
Trades1,304

Frequently asked questions

Is VWAP a good indicator for intraday trading?

VWAP is a widely watched intraday fair-value benchmark, useful as a trend filter or a reversion anchor. It works best combined with a second signal rather than alone, and at intraday frequency fees and slippage dominate the result.

How do you calculate VWAP in Python?

VWAP is the cumulative volume-weighted average price over the session. Manifold-BT exposes it as a built-in column, so you compare the close to vwap directly without computing it by hand.

Keep reading

Run your first backtest

Install Manifold-BT and reproduce the backtest above in seconds. The Rust core runs years of bars sub-second so you can sweep parameters instead of waiting.

$pip install manifoldbt