MobinMQL/Indicators/Examples/ZigzagColor.mq5
2025-07-22 14:48:34 +03:00

287 lines
9.1 KiB
MQL5

//+------------------------------------------------------------------+
//| ZigzagColor.mq5 |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots 1
#property indicator_type1 DRAW_COLOR_ZIGZAG
#property indicator_color1 clrDodgerBlue,clrRed
//--- input parameters
input int InpDepth =12; // Depth
input int InpDeviation=5; // Deviation
input int InpBackstep =3; // Back Step
//--- indicator buffers
double ZigzagPeakBuffer[];
double ZigzagBottomBuffer[];
double HighMapBuffer[];
double LowMapBuffer[];
double ColorBuffer[];
int ExtRecalc=3; // recounting's depth
enum EnSearchMode
{
Extremum=0, // searching for the first extremum
Peak=1, // searching for the next ZigZag peak
Bottom=-1 // searching for the next ZigZag bottom
};
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,ZigzagPeakBuffer,INDICATOR_DATA);
SetIndexBuffer(1,ZigzagBottomBuffer,INDICATOR_DATA);
SetIndexBuffer(2,ColorBuffer,INDICATOR_COLOR_INDEX);
SetIndexBuffer(3,HighMapBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(4,LowMapBuffer,INDICATOR_CALCULATIONS);
//--- set accuracy
IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- name for DataWindow and indicator subwindow label
string short_name=StringFormat("ZigZagColor(%d,%d,%d)",InpDepth,InpDeviation,InpBackstep);
IndicatorSetString(INDICATOR_SHORTNAME,short_name);
PlotIndexSetString(0,PLOT_LABEL,short_name);
//--- set an empty value
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
}
//+------------------------------------------------------------------+
//| ZigZag calculation |
//+------------------------------------------------------------------+
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<100)
return(0);
//---
int i,start=0;
int extreme_counter=0,extreme_search=Extremum;
int shift,back=0,last_high_pos=0,last_low_pos=0;
double val=0,res=0;
double cur_low=0,cur_high=0,last_high=0,last_low=0;
//--- initializing
if(prev_calculated==0)
{
ArrayInitialize(ZigzagPeakBuffer,0.0);
ArrayInitialize(ZigzagBottomBuffer,0.0);
ArrayInitialize(HighMapBuffer,0.0);
ArrayInitialize(LowMapBuffer,0.0);
//--- start calculation from bar number InpDepth
start=InpDepth-1;
}
//--- ZigZag was already calculated before
if(prev_calculated>0)
{
i=rates_total-1;
//--- searching for the third extremum from the last uncompleted bar
while(extreme_counter<ExtRecalc && i>rates_total -100)
{
res=(ZigzagPeakBuffer[i]+ZigzagBottomBuffer[i]);
//---
if(res!=0)
extreme_counter++;
i--;
}
i++;
start=i;
//--- what type of exremum we search for
if(LowMapBuffer[i]!=0)
{
cur_low=LowMapBuffer[i];
extreme_search=Peak;
}
else
{
cur_high=HighMapBuffer[i];
extreme_search=Bottom;
}
//--- clear indicator values
for(i=start+1; i<rates_total && !IsStopped(); i++)
{
ZigzagPeakBuffer[i] =0.0;
ZigzagBottomBuffer[i]=0.0;
LowMapBuffer[i] =0.0;
HighMapBuffer[i] =0.0;
}
}
//--- searching for high and low extremes
for(shift=start; shift<rates_total && !IsStopped(); shift++)
{
//--- low
val=Lowest(low,InpDepth,shift);
if(val==last_low)
val=0.0;
else
{
last_low=val;
if((low[shift]-val)>(InpDeviation*_Point))
val=0.0;
else
{
for(back=InpBackstep; back>=1; back--)
{
res=LowMapBuffer[shift-back];
//---
if((res!=0) && (res>val))
LowMapBuffer[shift-back]=0.0;
}
}
}
if(low[shift]==val)
LowMapBuffer[shift]=val;
else
LowMapBuffer[shift]=0.0;
//--- high
val=Highest(high,InpDepth,shift);
if(val==last_high)
val=0.0;
else
{
last_high=val;
if((val-high[shift])>(InpDeviation*_Point))
val=0.0;
else
{
for(back=InpBackstep; back>=1; back--)
{
res=HighMapBuffer[shift-back];
//---
if((res!=0) && (res<val))
HighMapBuffer[shift-back]=0.0;
}
}
}
if(high[shift]==val)
HighMapBuffer[shift]=val;
else
HighMapBuffer[shift]=0.0;
}
//--- set last values
if(extreme_search==0) // undefined values
{
last_low=0;
last_high=0;
}
else
{
last_low=cur_low;
last_high=cur_high;
}
//--- final selection of extreme points for ZigZag
for(shift=start; shift<rates_total && !IsStopped(); shift++)
{
res=0.0;
switch(extreme_search)
{
case Extremum:
if(last_low==0 && last_high==0)
{
if(HighMapBuffer[shift]!=0)
{
last_high=high[shift];
last_high_pos=shift;
extreme_search=-1;
ZigzagPeakBuffer[shift]=last_high;
ColorBuffer[shift]=0;
res=1;
}
if(LowMapBuffer[shift]!=0)
{
last_low=low[shift];
last_low_pos=shift;
extreme_search=1;
ZigzagBottomBuffer[shift]=last_low;
ColorBuffer[shift]=1;
res=1;
}
}
break;
case Peak:
if(LowMapBuffer[shift]!=0.0 && LowMapBuffer[shift]<last_low &&
HighMapBuffer[shift]==0.0)
{
ZigzagBottomBuffer[last_low_pos]=0.0;
last_low_pos=shift;
last_low=LowMapBuffer[shift];
ZigzagBottomBuffer[shift]=last_low;
ColorBuffer[shift]=1;
res=1;
}
if(HighMapBuffer[shift]!=0.0 && LowMapBuffer[shift]==0.0)
{
last_high=HighMapBuffer[shift];
last_high_pos=shift;
ZigzagPeakBuffer[shift]=last_high;
ColorBuffer[shift]=0;
extreme_search=Bottom;
res=1;
}
break;
case Bottom:
if(HighMapBuffer[shift]!=0.0 &&
HighMapBuffer[shift]>last_high &&
LowMapBuffer[shift]==0.0)
{
ZigzagPeakBuffer[last_high_pos]=0.0;
last_high_pos=shift;
last_high=HighMapBuffer[shift];
ZigzagPeakBuffer[shift]=last_high;
ColorBuffer[shift]=0;
}
if(LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]==0.0)
{
last_low=LowMapBuffer[shift];
last_low_pos=shift;
ZigzagBottomBuffer[shift]=last_low;
ColorBuffer[shift]=1;
extreme_search=Peak;
}
break;
default:
return(rates_total);
}
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//| Get highest value for range |
//+------------------------------------------------------------------+
double Highest(const double&array[],int count,int start)
{
double res=array[start];
//---
for(int i=start-1; i>start-count && i>=0; i--)
if(res<array[i])
res=array[i];
//---
return(res);
}
//+------------------------------------------------------------------+
//| Get lowest value for range |
//+------------------------------------------------------------------+
double Lowest(const double&array[],int count,int start)
{
double res=array[start];
//---
for(int i=start-1; i>start-count && i>=0; i--)
if(res>array[i])
res=array[i];
//---
return(res);
}
//+------------------------------------------------------------------+