VWAP strategy: does it work? Backtested on the top 10 coins
Weak. We ran the VWAP rule on the top 10 coins at once, each with an equal share of the account, as Hyperliquid perpetuals with fees, slippage and funding paid, and it made money on the portfolio in at least one run, but no run cleared our bar. The textbook version, 4h, long and short, returned -55.9% with a Sharpe of -0.94, against -7.7% for holding all 10 coins. Its best single coin was UNI 1d, long and short, with a Sharpe of 0.23.
Data through 2026-09-29 on Hyperliquid perpetuals, net of fees, slippage and funding
The rule run across the top 10 coins, equal weight (a pinned list): BTC, ETH, SOL, XRP, NEAR, ENA, UNI, DOGE, SUI and TAO.
| long only | long and short | |
|---|---|---|
| 4h | 0.19 | -0.94 |
| 1d | 0.26 | -0.61 |
Sharpe of each portfolio run. Green cleared our bar, amber came close, and the outlined square is the textbook rule. Holding all 10 coins had a Sharpe of 0.42. Net of fees, slippage and funding.
The VWAP rules we tested
VWAP, the volume-weighted average price, is the average price weighted by how much traded at each level: where most of the business actually happened. Traders treat price far from VWAP as stretched and expect the stretch to ease. Below are the exact rules the backtest ran. Signals are read when a bar closes and orders fill at that close. The grade is over the long and short version, and the results show the other direction too. Every portfolio run trades the top 10 coins at once, each with 10% of the account. The coins are a fixed list (BTC, ETH, SOL, XRP, NEAR, ENA, UNI, DOGE, SUI and TAO), pinned for the whole test and the same on every page. The list is pinned rather than picked at each point in time because some large coins listed partway through the window and have no data for its start. Under the rules is the strategy itself, block by block. Fork it to change it and run your own backtest.
- Entry
- VWAP is the volume-weighted average of the typical price (high + low + close) / 3 over the last 50 bars. Take the gap between the close and VWAP and express it as a z-score against that gap's own last 50 bars. Buy when the z-score is at or below -2; short when it is at or above +2.
- Exit
- Close the long when the z-score is back at or above 0 (the gap is back to its 50-bar average), and the short when it is at or below 0.
- Sizing
- Each of the ten coins trades its own signal and opens each trade at 1/10 of the account. While a trade is open, if its share of the account drifts more than 25% from that tenth, it is trimmed or topped up back to the edge of that range. No stop.
The coins: The 10 Hyperliquid perps with the most traded dollar volume in the 90 days to 2026-09-29, among perps that traded for the whole test window, pinned: the same 10 coins are held for the whole test.
Not tested: session-anchored VWAP (this test uses a rolling VWAP); the New York session VWAP (09:30 is not on a 4h or 1d bar grid); intra-bar fills.
The strategy behind the portfolio at 4h, long and short, block by block.
Opens it in Keel as your own draft, to change and backtest.
Configuration
Globals(target_timeframe="4h")
Universe(mode="manual", symbols=["BTC", "ETH", "SOL", "XRP", "NEAR", "ENA", "UNI", "DOGE", "SUI", "TAO"], market="perp", resolved=["BTC", "ETH", "SOL", "XRP", "NEAR", "ENA", "UNI", "DOGE", "SUI", "TAO"], resolved_at="2026-07-06T00:00:00Z")
Execution(rebalance="buffered", buffer_threshold=0.25, buffer_mode="relative", rebalance_method="to_edge")
Pipeline([
PriceDataLoader(),
Store("ohlcv"),
{"fast": [ExtractSeries(series_name="close")], "slow": [VWAP(window=50)]},
Crossover(),
RollingZScoreTransform(window=50),
Store("z"),
{
"long_in": [Load("z"), BelowThresholdFilter(threshold=-2.0, inclusive=True), Store("long_in")],
"short_in": [Load("z"), AboveThresholdFilter(threshold=2.0, inclusive=True), Store("short_in")],
"long_out": [Load("z"), AboveThresholdFilter(threshold=0.0, inclusive=True), Store("long_out")],
"short_out": [Load("z"), BelowThresholdFilter(threshold=0.0, inclusive=True), Store("short_out")],
},
{"fast": [Load("long_in")], "slow": [Load("short_in")]},
Crossover(),
ThresholdCross(upper=0.5, lower=-0.5, mode="symmetric"),
Store("entries"),
TradeManager(entries="entries", prices="ohlcv"),
{
"long_exit": [{"a": [IsLong()], "b": [Load("long_out")]}, MaskAnd(), Exit()],
"short_exit": [{"a": [IsShort()], "b": [Load("short_out")]}, MaskAnd(), Exit()],
},
Exposure(),
EqualWeightSizer(target_leverage=1.0, max_weight=0.1),
], name="vwap")
Results on the top 10 coins, equal weight
The rule ran on all 10 coins at once, each with an equal share of the account, on the 4h and 1d charts, in both directions. A portfolio of 10 coins is a better test than one coin. It trades many more times, so one lucky or unlucky coin cannot decide the result, and its drawdowns are usually smaller because each coin's bad stretch hits only its share of the account. It lifts a result only when the rule works across coins; a rule that works on one or two coins looks no better here. Running one rule over a whole portfolio in a single backtest is what Keel is built for. The long and short rows set the grade; the other direction shows whether any edge came from one side only. A run clears our bar when its Sharpe is clearly positive and it made enough round trips to trust. Fading the distance from VWAP works when price oscillates around fair value. It fails when news or a trend pulls price away and keeps it there. Holding all 10 coins in equal weight is the bar to beat: over the same window it returned -7.7%. The textbook run made -55.9%, less than holding. Round trips count whole trades from entry to exit across every coin, fills count every order, and fees and funding are shown as a share of starting capital. Funding is what the positions paid: a positive figure is a cost, like fees, and a negative one means they received more funding than they paid.
| Timeframe, side | Sharpe | Total return | Yearly return | Worst drawdown | Win rate | Round trips | Fills | Time in market | Fees | Funding paid |
|---|---|---|---|---|---|---|---|---|---|---|
| 4h, long only | 0.19 | +3.8% | +1.8% | -26.0% | 57.0% | 418 | 2,955 | 56.1% | 3.3% | +2.2% |
| 4h, long and shorttextbook | -0.94 | -55.9% | -32.0% | -58.8% | 57.2% | 937 | 5,583 | 93.7% | 4.9% | -3.3% |
| 1d, long only | 0.26 | +6.7% | +3.1% | -18.3% | 58.2% | 55 | 420 | 52.5% | 0.5% | +1.5% |
| 1d, long and short | -0.61 | -43.5% | -23.6% | -48.5% | 56.5% | 151 | 1,046 | 93.8% | 0.9% | -5.4% |
Holding all 10 coins instead
| Portfolio | Sharpe | Total return | Yearly return | Worst drawdown |
|---|---|---|---|---|
| Hold all 10, equal weight | 0.42 | -7.7% | -3.6% | -85.7% |
Holding means a long perpetual position on each coin for the whole window, not spot. Like any perp long it pays funding out of the account while it is open, and these hold figures include that cost, so a hold can end near flat after a deep drawdown.
Coin by coin
The same rule on each coin alone, with the whole account on that one coin, at 4h and 1d, long and short. Read this if you trade one coin. Expect more spread here than in the portfolio: fewer trades per coin means more room for luck either way. The best single coin was UNI 1d, long and short, with a Sharpe of 0.23. On its own, the rule beat holding the coin on none of them at 4h.
| Coin | 4h Sharpe | 4h return | 4h round trips | 1d Sharpe | 1d return | 1d round trips | Hold the coin |
|---|---|---|---|---|---|---|---|
| BTC | -0.58 | -31.0% | 93 | -0.73 | -40.5% | 16 | +6.6% |
| ETH | -0.69 | -51.6% | 93 | -0.46 | -44.3% | 17 | -22.7% |
| SOL | -0.65 | -53.4% | 90 | 0.08 | -14.7% | 18 | -36.7% |
| XRP | -0.96 | -76.5% | 94 | lost more than 80% | -82.1% | 14 | +98.3% |
| NEAR | -0.47 | -64.2% | 94 | 0.15 | -23.6% | 14 | +0.9% |
| ENA | lost more than 80% | -91.0% | 91 | lost more than 80% | -90.5% | 13 | -5.1% |
| UNI | -0.17 | -51.8% | 99 | 0.23 | -16.1% | 17 | +3.8% |
| DOGE | -0.92 | -76.1% | 93 | lost more than 80% | -83.7% | 12 | -65.5% |
| SUI | 0.06 | -28.2% | 101 | -0.28 | -52.1% | 17 | -22.1% |
| TAO | lost more than 80% | -80.5% | 89 | -0.11 | -39.3% | 13 | -34.0% |
Holding means a long perpetual position on each coin for the whole window, not spot. Like any perp long it pays funding out of the account while it is open, and these hold figures include that cost, so a hold can end near flat after a deep drawdown.
Equity curve
The first chart is the textbook run, the portfolio at 4h, long and short; the second is the best portfolio run, the portfolio at 1d, long only. Each line starts from the same balance as holding all 10 coins in equal weight, and the drawdown underneath shows how far the rule fell from its last high. A rule can end ahead and still be hard to hold through its worst stretch.
The textbook rule: the portfolio at 4h, long and short
The best run: the portfolio at 1d, long only
Does a simple fix help?
Two of the most common changes traders make to a rule like this, each run on the same portfolio at 4h and 1d, long and short. Each fix gets its own grade by the same rules as the page grade. Neither fix lifts the grade above Weak. A fix that helps on one window is a lead to test further, not a finding.
Vol-targeted sizing
WeakVol-targeted sizing keeps the rule's entries and exits and changes only the size. Each trade is sized from the coin's average true range, so that a move of one average true range costs the same small share of the account on every coin. A calm coin gets a bigger position and a wild one a smaller one, with a cap on any one coin. It did not raise the Sharpe on either timeframe. With it, the rule grades Weak.
| Run | Sharpe | As written | Total return | Worst drawdown | Round trips |
|---|---|---|---|---|---|
| 4h, long and short | -1.48 | -0.94 | -56.9% | -59.2% | 937 |
| 1d, long and short | -0.75 | -0.61 | -41.8% | -45.9% | 151 |
200-day trend filter
WeakThe 200-day trend filter keeps the rule's entries but lets a long through only while the coin closes above its 200-day simple moving average, and a short only while it closes below. Sizing stays the same. It follows the old rule of not trading against the big trend. The average needs that much price history before its first reading, so the filter sits out the start of the window and its runs trade over a shorter period than the rule as written. Keep that in mind when you compare the two. It raised the Sharpe on both timeframes. With it, the rule grades Weak.
| Run | Sharpe | As written | Total return | Worst drawdown | Round trips |
|---|---|---|---|---|---|
| 4h, long and short | -0.86 | -0.94 | -33.6% | -41.6% | 361 |
| 1d, long and short | -0.01 | -0.61 | -6.2% | -27.9% | 62 |
Best VWAP settings for crypto
We ran every combination of VWAP window in bars (20, 50, 100, 200) and entry z-score (1.5, 2, 2.5, 3) on the portfolio, on the 4h chart, long and short, and kept everything else the same. Each square is one full backtest of all 10 coins, coloured by Sharpe, and the outlined square is the textbook setting. The setting to trust is one whose neighbours also did well. A lone bright square in a dark grid is usually luck, and a grid run on a whole portfolio is harder to fool than one run on a single coin.
Top 10 coins, 4h, long and short
On the portfolio, no setting we tried had a positive Sharpe, so changing the settings does not rescue the rule here. The textbook setting ranks 10th of 16 by Sharpe. The best square was VWAP window 100 bars and entry z-score 3, with a Sharpe of -0.71, and the worst was VWAP window 20 bars and entry z-score 2.5, at -1.45.
| VWAP window (bars)across: Entry z-score | 1.5 | 2 | 2.5 | 3 |
|---|---|---|---|---|
| 20 | -1.32 | -1.29 | -1.45 | -0.97 |
| 50 | -1.03 | -0.94 | -0.90 | -0.90 |
| 100 | -0.88 | -0.88 | -0.79 | -0.71best |
| 200 | -0.83 | -0.83 | -0.79 | -0.98 |
What this test does not tell you
A backtest answers a narrow question: what this exact rule did on these coins over this window. Read these before you trust any number on this page.
- The test covers 2024-08-15 to 2026-09-29, one stretch of the crypto market. A rule that worked here can fail in the next stretch, so every result on this page is "in this test", not a forecast.
- These are Hyperliquid perpetual futures, not spot coins. Every open position paid or earned funding, and the results include it, which most published backtests leave out.
- Costs: every fill pays a 4.5 bp fee and 4.5 bp of slippage, so a round trip costs 18 bp, and every open position pays or earns funding each hour. A rule that trades often pays these many times over, which is why the fee column matters as much as the Sharpe.
- Orders fill at the close of the bar that gives the signal. Intrabar stops, limit orders and wicks that touch a level and come back are not modelled.
- The textbook portfolio run made 937 round trips across its coins: enough trades for the result to mean something, though one window is still one window. A single coin makes far fewer, so read the coin-by-coin table with more caution.
- The coin list is fixed for the whole window. Coins that were large at the end of the window may have been smaller at the start, so a pinned list leans a little toward coins that did well.
- How this test defines the VWAP: crypto never closes, so there is no session open to anchor VWAP to. This test uses a rolling VWAP over a fixed number of bars, takes the gap between the close and VWAP, and scores that gap against its own recent average and spread. A gap far below its usual level is a buy, far above is a short. The trade closes when the gap returns to its own recent average, which is not always the same as price touching VWAP. Traders draw this differently, so this is a test of one exact definition. The settings grid varies VWAP window in bars (20, 50, 100, 200) and entry z-score (1.5, 2, 2.5, 3) to show how much the choice matters.
- Sizing: Each of the ten coins trades its own signal and opens each trade at 1/10 of the account. While a trade is open, if its share of the account drifts more than 25% from that tenth, it is trimmed or topped up back to the edge of that range. No stop. This tests the rule on its own. A trader who adds judgment, other filters or a different position size is running a different strategy.
How Sharpe and drawdown are measured: the Sharpe calculator and the drawdown calculator. Why the best square in a grid flatters itself: overfitting in crypto backtests.
Test it yourself
Take the rule into Keel, or hand it to your AI assistant, and change the coins, the timeframe or the settings. A result you reproduce and then break on purpose is worth more than any single table.
Fork this strategy in Keel
Opens the textbook rule on all 10 coins, 4h, long and short, as your own draft, ready to change and backtest.
Fork this strategy in KeelAsk your agent
With Keel connected to Claude, ChatGPT or another assistant, paste:
Backtest the VWAP strategy from usekeel.io/strategies/backtested/vwap on an equal-weight basket of BTC, ETH, SOL, XRP, NEAR, ENA, UNI, DOGE, SUI and TAO at 4h with Keel
VWAP strategy questions
Does the VWAP strategy work in crypto?
Weak, in this test. Run on the top 10 coins in equal weight, after fees, slippage and funding, it made money on the portfolio in at least one run, but no run cleared our bar. The textbook version, 4h, long and short, returned -55.9% with a Sharpe of -0.94, against -7.7% for holding all 10 coins. The best portfolio run was 1d, long only, with a Sharpe of 0.26 and a total return of +6.7%. Whether that is worth trading depends on the timeframe and the coin: the results show every run, and the settings grid shows whether the good runs depend on one exact setting.
What are the best VWAP settings for crypto?
On the portfolio, the textbook setting ranked 10th of 16 on the 4h chart, and the best square was VWAP window 100 bars and entry z-score 3, with a Sharpe of -0.71. There, no setting we tried had a positive Sharpe, so changing the settings does not rescue the rule here. Prefer a setting whose neighbours also did well over the single best square.
Does the VWAP strategy work on Bitcoin?
On BTC 4h, long and short, with the whole account on Bitcoin, the rule had a Sharpe of -0.58 and returned -31.0%, against +6.6% for holding BTC over the same window, net of fees, slippage and funding. One coin is a small sample, so the portfolio result above is the better guide; the coin-by-coin table shows BTC next to the other coins.
Why use a rolling VWAP for crypto?
Stock traders reset VWAP at each day's open. Crypto trades around the clock, so any reset time is a choice someone made, and the result can depend on that choice. A rolling VWAP over a fixed number of bars treats every hour the same way, which makes the rule exact and repeatable. The settings grid on this page changes the VWAP length.
How realistic is this backtest?
Closer than most published backtests. Every fill pays fees and slippage, and every open position pays or earns funding, as a real perpetual futures position does. Orders fill at the close of the signal bar, so the test never buys at a price the chart only touched. It covers one window, so treat the result as evidence, not a promise. How it works explains the engine in depth.