trading2026-08-10Β·6 minΒ·18/145

VWAP Mean Reversion Backtest on BTC/USDT: An Execution Tool, Not a Signal

Institutions use VWAP to execute without moving the market. Retail turned it into a mean-reversion strategy β€” and on real hourly BTC/USDT it backtests +73.20% at zero cost but -99.52% with realistic fees. Python code, charts, and why.

VWAP Mean Reversion Backtest on BTC/USDT (2023, hourly, real fees)

Institutions use VWAP so their orders don't get front-run β€” it's an execution benchmark, a way to say "don't pay more than the average price." I used it at 3am to try to buy dips, which is like using a Swiss railway timetable to decide where to drive. VWAP is a great tool being traded as a strategy, and on crypto it turns into a fee furnace. Strategy Lab #12.

What session VWAP is

VWAP = volume-weighted average price since the start of the session:

$$VWAP = \frac{\sum (typical_price \times volume)}{\sum volume}$$

It's the price at which all volume "should" average out today. For a large institutional order, it's the benchmark: beat it and you're a good executer. For a retail signal, my rule was:

  • Buy when price dips below the session VWAP and crosses back above it.
  • Sell when price crosses back below.

The theory: mean reversion to the session average. The reality on BTC: 24/7 sessions reset every midnight UTC, and hourly candles cross that line constantly. This traded 975 times in 2023 β€” 1,949 individual legs.

Results

StrategyCategoryTotal returnCAGRMaxDDSharpeTrades
vwapmeanrev-37.36%-37.45%-51.65%-1.30975

VWAP mean reversion vs buy & hold (2023, hourly, BTC/USDT)

The cost story is the whole story

ScenarioCost/legTotal returnMaxDDSharpeTrades
naive (zero cost)0.00%+73.20%-17.05%1.87975
taker fee 0.05%/leg0.05%-34.65%-50.53%-1.17975
+ funding 0.01%/8h0.05%-37.36%-51.65%-1.30975
+ slippage 10bp/leg0.15%-91.10%-91.72%-7.26975
+ slippage 25bp/leg0.30%-99.52%-99.53%-15.50975

VWAP cost scenarios (2023, hourly, BTC/USDT)

+73.20% β†’ -99.52%. Let's do the arithmetic the way the account does: 1,949 legs Γ— 0.05% taker = roughly 97% of your capital, spent in fees alone, before slippage. No strategy β€” mean reversion or otherwise β€” has an edge big enough to sit on top of that. The naive Sharpe of 1.87 is one of the best in this entire series, which is exactly why this is one of the most dangerous naive backtests I can show you.

Buy and hold comparison

StrategyTotal returnCAGRMaxDDSharpe
vwap-37.36%-37.45%-51.65%-1.30
buy & hold+154.94%+155.62%-21.74%2.42

What this does NOT prove

  • VWAP isn't a bad thing β€” it's the wrong job. Used as a filter or an execution benchmark in a larger system, it has a real place. What fails here is the retail translation "buy under VWAP" as a standalone hourly signal.
  • 24/7 markets break the daily-session assumption VWAP was built on. On stocks with clean trading hours the same rule behaves differently β€” a proper cross-market follow-up.
  • One symbol, one year, one definition (session = UTC day). But the turnover lesson is again the robust one: 975 round trips means the backtest is the fee schedule.

Code

from backtest_base import fetch, backtest_signal, metrics

df = fetch("BTCUSDT", "binance", "2023-01-01", "2023-12-31", "1h")
tp = (df["high"] + df["low"] + df["close"]) / 3
vol = df["volume"]
day = df.index.normalize()                       # session = UTC day
vwap = tp.mul(vol).groupby(day).cumsum() / vol.groupby(day).cumsum()

enter = ((df["close"] > vwap) & (df["close"].shift(1) <= vwap.shift(1))).fillna(False)
exit_ = (df["close"] < vwap).fillna(False)
signal = stateful_position(enter, exit_)

res = backtest_signal(df, signal, cost_per_leg=0.0005,
                      funding_per_bar=0.0001 / 8.0)
print(metrics(res, 8760))

Reproduce it

cd blog-drafts/scripts
python backtest_base.py --strategy vwap --symbol BTCUSDT --interval 1h \
    --start 2023-01-01 --end 2023-12-31 --fee 0.0005 --funding 0.0000125

Data: Binance public API, hourly OHLCV, 8,735 bars. The tables above reproduce exactly from this command.

This is a backtest on historical data, not investment advice. Past performance does not predict future results.