Free Tool: VWAP + MACD Momentum Scalping Strategy & Custom Indicators (MT4 / MT5 / cTrader)
Posted: Sun Jul 26, 2026 3:38 pm
Are you getting chopped up trying to scalp M1 and M5 charts during active London and New York sessions? Combining Volume Weighted Average Price (VWAP) with the MACD gives you a professional two-step filter: institutional trend direction plus momentum timing.
Most retail traders rely on exponential moving averages for trend bias, but MAs lag and ignore volume. VWAP acts as the true intraday value equilibrium. When price trades above daily VWAP, institutional buyers are in control; when below, sellers dominate. By forcing your scalp trades to align with this baseline, you immediately eliminate low-probability counter-trend setups.
The Scalping Strategy Rules:
Timeframes: M1 or M5 during high-liquidity windows (London/NY overlap).
Indicators: Daily Session VWAP + MACD (Fast: 6, Slow: 13, Signal: 5 for hyper-responsive execution, or standard 12, 26, 9).
Long Entry: Price must be above the Daily VWAP. Wait for the MACD line to cross above the Signal line (best when occurring below the zero level after a pullback).
Short Entry: Price must be below the Daily VWAP. Wait for the MACD line to cross below the Signal line.
Risk Management: Place protective stop losses 2 pips beyond the recent swing high/low or use a dynamic 1.5x ATR stop. Target a 1.5R to 2.0R risk-to-reward ratio.
To automate the chart reading, I coded custom overlay indicators for MT4, MT5, and IC Trader (cTrader) that print entry arrows when both conditions align. Grab the source code below!
MT4 (MQL4) Custom Indicator
This indicator calculates the daily session VWAP and monitors MACD crossovers, plotting Buy and Sell arrows directly on the main chart window.
Most retail traders rely on exponential moving averages for trend bias, but MAs lag and ignore volume. VWAP acts as the true intraday value equilibrium. When price trades above daily VWAP, institutional buyers are in control; when below, sellers dominate. By forcing your scalp trades to align with this baseline, you immediately eliminate low-probability counter-trend setups.
The Scalping Strategy Rules:
Timeframes: M1 or M5 during high-liquidity windows (London/NY overlap).
Indicators: Daily Session VWAP + MACD (Fast: 6, Slow: 13, Signal: 5 for hyper-responsive execution, or standard 12, 26, 9).
Long Entry: Price must be above the Daily VWAP. Wait for the MACD line to cross above the Signal line (best when occurring below the zero level after a pullback).
Short Entry: Price must be below the Daily VWAP. Wait for the MACD line to cross below the Signal line.
Risk Management: Place protective stop losses 2 pips beyond the recent swing high/low or use a dynamic 1.5x ATR stop. Target a 1.5R to 2.0R risk-to-reward ratio.
To automate the chart reading, I coded custom overlay indicators for MT4, MT5, and IC Trader (cTrader) that print entry arrows when both conditions align. Grab the source code below!
MT4 (MQL4) Custom Indicator
This indicator calculates the daily session VWAP and monitors MACD crossovers, plotting Buy and Sell arrows directly on the main chart window.
Code: Select all
//+------------------------------------------------------------------+
//| VWAP_MACD_Scalper.mq4|
//| VWAP + MACD On-Chart Arrow Scalping Tool|
//+------------------------------------------------------------------+
#property copyright "Free Open Source"
#property link ""
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 clrBlue
#property indicator_color2 clrLime
#property indicator_color3 clrRed
#property indicator_width1 1
#property indicator_width2 2
#property indicator_width3 2
//--- Input Parameters
input int InpFastEMA = 6; // MACD Fast EMA
input int InpSlowEMA = 13; // MACD Slow EMA
input int InpSignalSMA = 5; // MACD Signal SMA
input ENUM_APPLIED_PRICE InpPrice = PRICE_CLOSE; // MACD Applied Price
//--- Indicator Buffers
double VwapBuffer[];
double BuyArrowBuffer[];
double SellArrowBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
SetIndexBuffer(0, VwapBuffer);
SetIndexStyle(0, DRAW_LINE);
SetIndexLabel(0, "Daily VWAP");
SetIndexBuffer(1, BuyArrowBuffer);
SetIndexStyle(1, DRAW_ARROW);
SetIndexArrow(1, 233); // Up arrow
SetIndexLabel(1, "Buy Signal");
SetIndexEmptyValue(1, 0.0);
SetIndexBuffer(2, SellArrowBuffer);
SetIndexStyle(2, DRAW_ARROW);
SetIndexArrow(2, 234); // Down arrow
SetIndexLabel(2, "Sell Signal");
SetIndexEmptyValue(2, 0.0);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
if(rates_total < InpSlowEMA) return(0);
int limit = rates_total - prev_calculated;
if(prev_calculated > 0) limit++;
else limit = rates_total - 1;
double cumVolume = 0;
double cumTypPriceVol = 0;
int currentDay = -1;
// Calculate from oldest to newest
for(int i = limit; i >= 0; i--)
{
int barDay = TimeDay(time[i]);
// Reset VWAP at the start of a new daily session
if(barDay != currentDay)
{
cumVolume = 0;
cumTypPriceVol = 0;
currentDay = barDay;
}
double typPrice = (high[i] + low[i] + close[i]) / 3.0;
double vol = (double)tick_volume[i];
if(vol == 0) vol = 1; // Prevent division by zero
cumVolume += vol;
cumTypPriceVol += typPrice * vol;
VwapBuffer[i] = cumTypPriceVol / cumVolume;
// Clear previous signals
BuyArrowBuffer[i] = 0.0;
SellArrowBuffer[i] = 0.0;
// Evaluate MACD Crossover on completed bars (avoid intrabar repainting)
if(i < rates_total - 1)
{
double macdCurrent = iMACD(NULL, 0, InpFastEMA, InpSlowEMA, InpSignalSMA, InpPrice, MODE_MAIN, i);
double sigCurrent = iMACD(NULL, 0, InpFastEMA, InpSlowEMA, InpSignalSMA, InpPrice, MODE_SIGNAL, i);
double macdPrevious = iMACD(NULL, 0, InpFastEMA, InpSlowEMA, InpSignalSMA, InpPrice, MODE_MAIN, i+1);
double sigPrevious = iMACD(NULL, 0, InpFastEMA, InpSlowEMA, InpSignalSMA, InpPrice, MODE_SIGNAL, i+1);
// Long Condition: Price > VWAP and MACD crosses above Signal
if(close[i] > VwapBuffer[i] && macdPrevious <= sigPrevious && macdCurrent > sigCurrent)
{
BuyArrowBuffer[i] = low[i] - (10 * Point);
}
// Short Condition: Price < VWAP and MACD crosses below Signal
else if(close[i] < VwapBuffer[i] && macdPrevious >= sigPrevious && macdCurrent < sigCurrent)
{
SellArrowBuffer[i] = high[i] + (10 * Point);
}
}
}
return(rates_total);
}