forked from animatedread/Warrior_EA
301 lines
10 KiB
MQL5
301 lines
10 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| ADZigZag.mq5 |
|
||
|
|
//| AD Institutional Indicators |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
// Renamed/rebranded copy of MetaQuotes' stock ZigZag.mq5 (Copyright 2000-2026, MetaQuotes Ltd.,
|
||
|
|
// https://www.mql5.com) - file, property, and identifier names only; the pivot-detection algorithm
|
||
|
|
// itself (Depth/Deviation/Backstep scan, extreme tracking, final-selection state machine) is
|
||
|
|
// untouched. Used by CExpertSignalAIBase as the ground-truth source for "is this bar a confirmed
|
||
|
|
// ZigZag reversal" training labels (see AdvanceZigZagLabelState() in ExpertSignalAIBase.mqh) -
|
||
|
|
// replacing the old hand-rolled fractal/deviation-%/ATR-trend-context approximation of a ZigZag
|
||
|
|
// with the real, well-known indicator, at its own stock default settings (Depth=12, Deviation=5,
|
||
|
|
// Backstep=3).
|
||
|
|
#property copyright "AD Institutional Indicators"
|
||
|
|
#property link ""
|
||
|
|
#property version "1.00"
|
||
|
|
#property indicator_chart_window
|
||
|
|
#property indicator_buffers 3
|
||
|
|
#property indicator_plots 1
|
||
|
|
//--- plot ADZigZag
|
||
|
|
#property indicator_label1 "ADZigZag"
|
||
|
|
#property indicator_type1 DRAW_SECTION
|
||
|
|
#property indicator_color1 clrRed
|
||
|
|
#property indicator_style1 STYLE_SOLID
|
||
|
|
#property indicator_width1 1
|
||
|
|
//--- input parameters
|
||
|
|
input int InpDepth = 12; // Depth
|
||
|
|
input int InpDeviation = 5; // Deviation
|
||
|
|
input int InpBackstep = 3; // Back Step
|
||
|
|
//--- indicator buffers
|
||
|
|
double ADZZBuffer[]; // main buffer
|
||
|
|
double ADZZHighMapBuffer[]; // ZigZag high extremes (peaks)
|
||
|
|
double ADZZLowMapBuffer[]; // ZigZag low extremes (bottoms)
|
||
|
|
|
||
|
|
int ADZZExtRecalc = 3; // number of last extremes for recalculation
|
||
|
|
|
||
|
|
enum EnADZZSearchMode
|
||
|
|
{
|
||
|
|
ADZZ_Extremum = 0, // searching for the first extremum
|
||
|
|
ADZZ_Peak = 1, // searching for the next ZigZag peak
|
||
|
|
ADZZ_Bottom = -1 // searching for the next ZigZag bottom
|
||
|
|
};
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Custom indicator initialization function |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OnInit()
|
||
|
|
{
|
||
|
|
//--- indicator buffers mapping
|
||
|
|
SetIndexBuffer(0, ADZZBuffer, INDICATOR_DATA);
|
||
|
|
SetIndexBuffer(1, ADZZHighMapBuffer, INDICATOR_CALCULATIONS);
|
||
|
|
SetIndexBuffer(2, ADZZLowMapBuffer, INDICATOR_CALCULATIONS);
|
||
|
|
//--- set short name and digits
|
||
|
|
string short_name = StringFormat("ADZigZag(%d,%d,%d)", InpDepth, InpDeviation, InpBackstep);
|
||
|
|
IndicatorSetString(INDICATOR_SHORTNAME, short_name);
|
||
|
|
PlotIndexSetString(0, PLOT_LABEL, short_name);
|
||
|
|
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
|
||
|
|
//--- set an empty value
|
||
|
|
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| ADZigZag 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 = 0;
|
||
|
|
int start = 0, extreme_counter = 0, extreme_search = ADZZ_Extremum;
|
||
|
|
int shift = 0, back = 0, last_high_pos = 0, last_low_pos = 0;
|
||
|
|
double val = 0, res = 0;
|
||
|
|
double curlow = 0, curhigh = 0, last_high = 0, last_low = 0;
|
||
|
|
//--- initializing
|
||
|
|
if(prev_calculated == 0)
|
||
|
|
{
|
||
|
|
ArrayInitialize(ADZZBuffer, 0.0);
|
||
|
|
ArrayInitialize(ADZZHighMapBuffer, 0.0);
|
||
|
|
ArrayInitialize(ADZZLowMapBuffer, 0.0);
|
||
|
|
start = InpDepth;
|
||
|
|
}
|
||
|
|
|
||
|
|
//--- ADZigZag 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 < ADZZExtRecalc && i > rates_total - 100)
|
||
|
|
{
|
||
|
|
res = ADZZBuffer[i];
|
||
|
|
if(res != 0.0)
|
||
|
|
extreme_counter++;
|
||
|
|
i--;
|
||
|
|
}
|
||
|
|
i++;
|
||
|
|
start = i;
|
||
|
|
|
||
|
|
//--- what type of extremum we search for
|
||
|
|
if(ADZZLowMapBuffer[i] != 0.0)
|
||
|
|
{
|
||
|
|
curlow = ADZZLowMapBuffer[i];
|
||
|
|
extreme_search = ADZZ_Peak;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
curhigh = ADZZHighMapBuffer[i];
|
||
|
|
extreme_search = ADZZ_Bottom;
|
||
|
|
}
|
||
|
|
//--- clear indicator values
|
||
|
|
for(i = start + 1; i < rates_total && !IsStopped(); i++)
|
||
|
|
{
|
||
|
|
ADZZBuffer[i] = 0.0;
|
||
|
|
ADZZLowMapBuffer[i] = 0.0;
|
||
|
|
ADZZHighMapBuffer[i] = 0.0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//--- searching for high and low extremes
|
||
|
|
for(shift = start; shift < rates_total && !IsStopped(); shift++)
|
||
|
|
{
|
||
|
|
//--- low
|
||
|
|
val = low[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 = 1; back <= InpBackstep; back++)
|
||
|
|
{
|
||
|
|
res = ADZZLowMapBuffer[shift - back];
|
||
|
|
if((res != 0) && (res > val))
|
||
|
|
ADZZLowMapBuffer[shift - back] = 0.0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(low[shift] == val)
|
||
|
|
ADZZLowMapBuffer[shift] = val;
|
||
|
|
else
|
||
|
|
ADZZLowMapBuffer[shift] = 0.0;
|
||
|
|
//--- high
|
||
|
|
val = high[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 = 1; back <= InpBackstep; back++)
|
||
|
|
{
|
||
|
|
res = ADZZHighMapBuffer[shift - back];
|
||
|
|
if((res != 0) && (res < val))
|
||
|
|
ADZZHighMapBuffer[shift - back] = 0.0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if(high[shift] == val)
|
||
|
|
ADZZHighMapBuffer[shift] = val;
|
||
|
|
else
|
||
|
|
ADZZHighMapBuffer[shift] = 0.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//--- set last values
|
||
|
|
if(extreme_search == 0) // undefined values
|
||
|
|
{
|
||
|
|
last_low = 0.0;
|
||
|
|
last_high = 0.0;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
last_low = curlow;
|
||
|
|
last_high = curhigh;
|
||
|
|
}
|
||
|
|
|
||
|
|
//--- final selection of extreme points for ADZigZag
|
||
|
|
for(shift = start; shift < rates_total && !IsStopped(); shift++)
|
||
|
|
{
|
||
|
|
res = 0.0;
|
||
|
|
switch(extreme_search)
|
||
|
|
{
|
||
|
|
case ADZZ_Extremum:
|
||
|
|
if(last_low == 0.0 && last_high == 0.0)
|
||
|
|
{
|
||
|
|
if(ADZZHighMapBuffer[shift] != 0)
|
||
|
|
{
|
||
|
|
last_high = high[shift];
|
||
|
|
last_high_pos = shift;
|
||
|
|
extreme_search = ADZZ_Bottom;
|
||
|
|
ADZZBuffer[shift] = last_high;
|
||
|
|
res = 1;
|
||
|
|
}
|
||
|
|
if(ADZZLowMapBuffer[shift] != 0.0)
|
||
|
|
{
|
||
|
|
last_low = low[shift];
|
||
|
|
last_low_pos = shift;
|
||
|
|
extreme_search = ADZZ_Peak;
|
||
|
|
ADZZBuffer[shift] = last_low;
|
||
|
|
res = 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case ADZZ_Peak:
|
||
|
|
if(ADZZLowMapBuffer[shift] != 0.0 && ADZZLowMapBuffer[shift] < last_low && ADZZHighMapBuffer[shift] == 0.0)
|
||
|
|
{
|
||
|
|
ADZZBuffer[last_low_pos] = 0.0;
|
||
|
|
last_low_pos = shift;
|
||
|
|
last_low = ADZZLowMapBuffer[shift];
|
||
|
|
ADZZBuffer[shift] = last_low;
|
||
|
|
res = 1;
|
||
|
|
}
|
||
|
|
if(ADZZHighMapBuffer[shift] != 0.0 && ADZZLowMapBuffer[shift] == 0.0)
|
||
|
|
{
|
||
|
|
last_high = ADZZHighMapBuffer[shift];
|
||
|
|
last_high_pos = shift;
|
||
|
|
ADZZBuffer[shift] = last_high;
|
||
|
|
extreme_search = ADZZ_Bottom;
|
||
|
|
res = 1;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case ADZZ_Bottom:
|
||
|
|
if(ADZZHighMapBuffer[shift] != 0.0 && ADZZHighMapBuffer[shift] > last_high && ADZZLowMapBuffer[shift] == 0.0)
|
||
|
|
{
|
||
|
|
ADZZBuffer[last_high_pos] = 0.0;
|
||
|
|
last_high_pos = shift;
|
||
|
|
last_high = ADZZHighMapBuffer[shift];
|
||
|
|
ADZZBuffer[shift] = last_high;
|
||
|
|
}
|
||
|
|
if(ADZZLowMapBuffer[shift] != 0.0 && ADZZHighMapBuffer[shift] == 0.0)
|
||
|
|
{
|
||
|
|
last_low = ADZZLowMapBuffer[shift];
|
||
|
|
last_low_pos = shift;
|
||
|
|
ADZZBuffer[shift] = last_low;
|
||
|
|
extreme_search = ADZZ_Peak;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
return(rates_total);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//--- return value of prev_calculated for next call
|
||
|
|
return(rates_total);
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Search for the index of the highest bar |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
int Highest(const double &array[], const int depth, const int start)
|
||
|
|
{
|
||
|
|
if(start < 0)
|
||
|
|
return(0);
|
||
|
|
|
||
|
|
double max = array[start];
|
||
|
|
int index = start;
|
||
|
|
//--- start searching
|
||
|
|
for(int i = start - 1; i > start - depth && i >= 0; i--)
|
||
|
|
{
|
||
|
|
if(array[i] > max)
|
||
|
|
{
|
||
|
|
index = i;
|
||
|
|
max = array[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//--- return index of the highest bar
|
||
|
|
return(index);
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Search for the index of the lowest bar |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
int Lowest(const double &array[], const int depth, const int start)
|
||
|
|
{
|
||
|
|
if(start < 0)
|
||
|
|
return(0);
|
||
|
|
|
||
|
|
double min = array[start];
|
||
|
|
int index = start;
|
||
|
|
//--- start searching
|
||
|
|
for(int i = start - 1; i > start - depth && i >= 0; i--)
|
||
|
|
{
|
||
|
|
if(array[i] < min)
|
||
|
|
{
|
||
|
|
index = i;
|
||
|
|
min = array[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//--- return index of the lowest bar
|
||
|
|
return(index);
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|