Quant BuffetRelax, Not Over Thinking

Volume Weighted Average Price (VWAP) as Precise Trend-Following Indicator for Day-Traders

Log in to collect

Academic paper

Volume Weighted Average Price (VWAP) The Holy Grail for Day Trading Systems

AuthorsCarlo Zarattini; Andrew Aziz

Institute
  • Pentum Group (United States)
  • ?Concretum Group
  • ?Concretum Research
  • ?Bear Bull Traders
  • ?Peak Capital Trading

Strategy in a nutshell

Trade QQQ (or TQQQ) intraday using a VWAP-based trend system. Enter long if the first 1-min candle closes above VWAP, short if below. Stop-loss triggered by candle crossing VWAP. Positions closed at day’s end.

Economic rationale

VWAP captures intraday market trends and liquidity. The strategy exploits statistically validated short-term price patterns, enhancing intraday execution, risk-adjusted returns, and algorithmic trading efficiency.

Backtest performance

Annualised return43%
Volatility18%
Beta-0.001
Sharpe ratio2.39
Sortino ratio0.511
Maximum drawdown-9.4%
Win rate17%

Full Python code

from AlgorithmImports import *
import numpy as np
# endregion
class VolumeWeightedAveragePriceVWAPAsPreciseTrendFollowingIndicatorForDayTraders(QCAlgorithm):
def Initialize(self) -> None:
self.SetStartDate(2018, 1, 1)
self.SetCash(100000)
self.symbol: Symbol = self.AddEquity("QQQ", Resolution.Minute).Symbol
self.Securities[self.symbol].SetFeeModel(ConstantFeeModel(0))
# self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
self.VWAP: IntradayVwap = IntradayVwap(self.symbol)
self.traded_weight: float = 1.
self.trade_flag: bool = False
self.Settings.MinimumOrderMarginPortfolioPercentage = 0.
self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.AfterMarketOpen(self.symbol), self.OnMarketOpen)
self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.BeforeMarketClose(self.symbol, 1), self.BeforeMarketClose)
def OnData(self, data: Slice) -> None:
# trading allowed only after open market
if not self.trade_flag:
    return
# update VWAP indicator
bar: TradeBar = data.Bars.get(self.symbol)
self.VWAP.Update(bar)
        
# trade execution
if self.VWAP.IsReady:
    if data[self.symbol].Close > self.VWAP.Current.Value:
        if not self.Portfolio[self.symbol].IsLong:
            self.SetHoldings(self.symbol, self.traded_weight)
    else:
        if not self.Portfolio[self.symbol].IsShort:
            self.SetHoldings(self.symbol, -self.traded_weight)
def OnMarketOpen(self) -> None:
self.trade_flag = True
def BeforeMarketClose(self) -> None:
self.Liquidate()
self.VWAP.Reset()
self.trade_flag = False