Follow the link zigzaz divergences of cumulative volume on a zigzag. There's code below. Could someone make such an indicator for MT4?
Code: Select all
//+------------------------------------------------------------------+
//| PRC_CumVol ZigZag Divergence v2.1 – FINAL & CLEAN |
//| @forex_station | Nov 11, 2025 |
//+------------------------------------------------------------------+
#property copyright "@forex_station"
#property link "https://x.com/forex_station"
#property version "2.10"
#property strict
#property indicator_separate_window
#property indicator_buffers 4
//--- Histogram
#property indicator_label1 "CumUp"; #property indicator_type1 DRAW_HISTOGRAM; #property indicator_color1 clrGreen;
#property indicator_label2 "CumDown"; #property indicator_type2 DRAW_HISTOGRAM; #property indicator_color2 clrRed;
#property indicator_label3 "DivBear"; #property indicator_type3 DRAW_HISTOGRAM; #property indicator_color3 clrOrange;
#property indicator_label4 "DivBull"; #property indicator_type4 DRAW_HISTOGRAM; #property indicator_color4 clrLime;
//--- INPUTS
input double percentVariation = 3.0; // Swing threshold (%)
input int ArrowSize = 3; // 1-5
input color BearArrowColor = clrRed; // Bearish arrow
input color BullArrowColor = clrLime; // Bullish arrow
input int LineWidth = 2; // 1-5
input color BearLineColor = clrRed; // Bearish line
input color BullLineColor = clrLime; // Bullish line
//--- Buffers
double CumUp[], CumDown[], DivBear[], DivBull[];
//--- State
int dir = 1;
double lastExt = 0.0;
int lastExtBar = 0;
double cumV = 0.0;
//--- Swing Points
double pHigh=0, lpHigh=0, pVol=0, lpVol=0; int pBar=0, lpBar=0;
double tLow=0, ltLow=0, tVol=0, ltVol=0; int tBar=0, ltBar=0;
//+------------------------------------------------------------------+
int OnInit()
{
SetIndexBuffer(0, CumUp); SetIndexStyle(0, DRAW_HISTOGRAM);
SetIndexBuffer(1, CumDown); SetIndexStyle(1, DRAW_HISTOGRAM);
SetIndexBuffer(2, DivBear); SetIndexStyle(2, DRAW_HISTOGRAM);
SetIndexBuffer(3, DivBull); SetIndexStyle(3, DRAW_HISTOGRAM);
IndicatorShortName("PRC CumVol Div v2.1");
Print("PRC CumVol Divergence v2.1 Loaded – @forex_station");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
for(int i = ObjectsTotal()-1; i >= 0; i--)
{
string name = ObjectName(i);
if(StringFind(name, "PRC_Div_") == 0)
ObjectDelete(name);
}
}
//+------------------------------------------------------------------+
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 < 50) return(0);
int start = (prev_calculated == 0) ? rates_total - 1 : prev_calculated - 1;
//--- First run: reset state only
if(prev_calculated == 0)
{
dir = 1;
lastExt = close[start];
lastExtBar = start;
cumV = 0.0;
// DO NOT use ArrayInitialize on buffers — it wipes MT4's buffer memory!
// Just clear the visible part
for(int i = 0; i < rates_total; i++)
{
CumUp[i] = 0; CumDown[i] = 0;
DivBear[i] = 0; DivBull[i] = 0;
}
}
for(int i = start; i >= 0; i--)
{
double price = close[i];
double vol = (double)((tick_volume[i] > 0) ? tick_volume[i] : volume[i]);
cumV = (dir == 1) ? cumV + vol : cumV - vol;
bool peak = false, trough = false;
if(dir == 1)
{
if(price > lastExt) { lastExt = price; lastExtBar = i; }
if(price < lastExt * (1.0 - percentVariation / 100.0)) { peak = true; dir = -1; }
}
else
{
if(price < lastExt) { lastExt = price; lastExtBar = i; }
if(price > lastExt * (1.0 + percentVariation / 100.0)) { trough = true; dir = 1; }
}
double bear = 0, bull = 0;
//--- Bearish Divergence
if(peak && i > 0)
{
lpHigh = pHigh; lpVol = pVol; lpBar = pBar;
pHigh = high[lastExtBar];
pVol = cumV - (dir == 1 ? vol : -vol);
pBar = lastExtBar;
cumV = -vol; lastExt = price; lastExtBar = i;
if(pHigh > lpHigh && pVol < lpVol && lpBar > 0)
{
bear = pVol;
string l = "PRC_Div_Bear_Line_" + IntegerToString(pBar);
string a = "PRC_Div_Bear_Arr_" + IntegerToString(pBar);
if(ObjectFind(0, l) < 0)
{
ObjectCreate(0, l, OBJ_TREND, 0, time[lpBar], lpHigh, time[pBar], pHigh);
ObjectSetInteger(0, l, OBJPROP_COLOR, BearLineColor);
ObjectSetInteger(0, l, OBJPROP_WIDTH, LineWidth);
ObjectSetInteger(0, l, OBJPROP_RAY, false);
}
if(ObjectFind(0, a) < 0)
{
ObjectCreate(0, a, OBJ_ARROW_DOWN, 0, time[pBar], pHigh + 20 * Point);
ObjectSetInteger(0, a, OBJPROP_COLOR, BearArrowColor);
ObjectSetInteger(0, a, OBJPROP_WIDTH, ArrowSize);
ObjectSetInteger(0, a, OBJPROP_ARROWCODE, 234);
}
}
}
//--- Bullish Divergence
if(trough && i > 0)
{
ltLow = tLow; ltVol = tVol; ltBar = tBar;
tLow = low[lastExtBar];
tVol = cumV - (dir == 1 ? vol : -vol);
tBar = lastExtBar;
cumV = vol; lastExt = price; lastExtBar = i;
if(tLow < ltLow && tVol > ltVol && ltBar > 0)
{
bull = tVol;
string l = "PRC_Div_Bull_Line_" + IntegerToString(tBar);
string a = "PRC_Div_Bull_Arr_" + IntegerToString(tBar);
if(ObjectFind(0, l) < 0)
{
ObjectCreate(0, l, OBJ_TREND, 0, time[ltBar], ltLow, time[tBar], tLow);
ObjectSetInteger(0, l, OBJPROP_COLOR, BullLineColor);
ObjectSetInteger(0, l, OBJPROP_WIDTH, LineWidth);
ObjectSetInteger(0, l, OBJPROP_RAY, false);
}
if(ObjectFind(0, a) < 0)
{
ObjectCreate(0, a, OBJ_ARROW_UP, 0, time[tBar], tLow - 20 * Point);
ObjectSetInteger(0, a, OBJPROP_COLOR, BullArrowColor);
ObjectSetInteger(0, a, OBJPROP_WIDTH, ArrowSize);
ObjectSetInteger(0, a, OBJPROP_ARROWCODE, 233);
}
}
}
DivBear[i] = bear;
DivBull[i] = bull;
CumUp[i] = (cumV >= 0) ? cumV : 0.0;
CumDown[i] = (cumV < 0) ? cumV : 0.0;
}
return(rates_total);
}
//+------------------------------------------------------------------+