287 lines
9.1 KiB
MQL5
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);
| |||
}
| |||
//+------------------------------------------------------------------+
|