476 lines
11 KiB
Plaintext
476 lines
11 KiB
Plaintext
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center ZigZag Indicator
|
|
// -------------------------------------------------------------
|
|
// this indicator provides signals for Main strategy ...
|
|
//
|
|
// Maintainer:
|
|
// ------------
|
|
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
|
|
//
|
|
////////////////////////////////////////////////////////////////
|
|
//
|
|
// Global Properties ...
|
|
#property copyright "Copyright 2023, SaherElm IT Center"
|
|
#property link "https://saherelm.ir"
|
|
#property version "1.00"
|
|
#property description "SaherElm ZigZag Indicator"
|
|
#property strict
|
|
|
|
//
|
|
// START Inputs ...
|
|
//
|
|
input int depth = 12; // Depth
|
|
input int deviation = 5; // Deviation
|
|
input int backStep = 3; // BackStep
|
|
//
|
|
// END Inputs ...
|
|
//
|
|
|
|
//
|
|
// START Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
//
|
|
// Includes our shared library ...
|
|
#include "../Libraries/x-saherelm.lib.mq4"
|
|
|
|
//
|
|
// here we specify logging enabled or not ...
|
|
bool enableLogging = true;
|
|
|
|
//
|
|
// this is a Tag which attached to our Logger ...
|
|
string logTag = "XS_ZG";
|
|
|
|
//
|
|
#property indicator_chart_window
|
|
|
|
//
|
|
#property indicator_buffers 1
|
|
|
|
//
|
|
#property indicator_width1 1
|
|
#property indicator_color1 clrAqua
|
|
// #property indicator_type1 DRAW_SECTION
|
|
// #property indicator_style1 STYLE_SOLID
|
|
|
|
// //
|
|
// #property indicator_width2 1
|
|
// #property indicator_color2 clrNONE
|
|
// #property indicator_type2 DRAW_NONE
|
|
// #property indicator_style2 STYLE_SOLID
|
|
|
|
// //
|
|
// #property indicator_width3 1
|
|
// #property indicator_color3 clrNONE
|
|
// #property indicator_type3 DRAW_NONE
|
|
// #property indicator_style3 STYLE_SOLID
|
|
|
|
//
|
|
// Buffers ...
|
|
//
|
|
#define zigzagBufferIndex 0
|
|
#define highBufferIndex 1
|
|
#define lowBufferIndex 2
|
|
// #define ziggyBufferIndex 3
|
|
|
|
//
|
|
double zigzagBuffer[];
|
|
double highBuffer[];
|
|
double lowBuffer[];
|
|
// double ziggyBuffer[];
|
|
|
|
//
|
|
// recounting's depth of extremums ...
|
|
int level=3;
|
|
//
|
|
// END Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
|
|
//
|
|
// Start Event Handlers ...
|
|
//
|
|
//
|
|
// Initialization ...
|
|
int OnInit() {
|
|
//
|
|
// Initialize what we want ...
|
|
|
|
//
|
|
// Validating Input Parameters ...
|
|
if (
|
|
depth <= 0 ||
|
|
backStep < 0 ||
|
|
deviation < 0 ||
|
|
backStep >= depth
|
|
) {
|
|
return INIT_PARAMETERS_INCORRECT;
|
|
}
|
|
|
|
//
|
|
// Set Index Buffers of ZigZag ...
|
|
IndicatorBuffers(3);
|
|
|
|
//
|
|
// ZigZag Buffer ...
|
|
SetIndexBuffer(zigzagBufferIndex, zigzagBuffer);
|
|
SetIndexStyle(zigzagBufferIndex, DRAW_SECTION);
|
|
SetIndexLabel(zigzagBufferIndex, "ZigZag");
|
|
|
|
//
|
|
// High Buffer ...
|
|
SetIndexBuffer(highBufferIndex, highBuffer);
|
|
SetIndexLabel(highBufferIndex, "");
|
|
|
|
//
|
|
// Low Buffer ...
|
|
SetIndexBuffer(lowBufferIndex, lowBuffer);
|
|
SetIndexLabel(lowBufferIndex, "");
|
|
|
|
//
|
|
// Ziggy Buffer ...
|
|
// SetIndexBuffer(ziggyBufferIndex, ziggyBuffer);
|
|
// SetIndexLabel(ziggyBufferIndex, "");
|
|
|
|
//
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
|
|
//
|
|
// Do 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[]
|
|
) {
|
|
//
|
|
// this counts Available Bars ...
|
|
int limit;
|
|
|
|
//
|
|
int maxLength = MathMax(depth, backStep);
|
|
|
|
int i;
|
|
int counterZ;
|
|
int back;
|
|
int pos;
|
|
|
|
//
|
|
int lastlowpos = 0;
|
|
int lasthighpos = 0;
|
|
int whatlookfor = 0;
|
|
|
|
//
|
|
double extremum;
|
|
|
|
//
|
|
double curlow = 0.0;
|
|
double curhigh = 0.0;
|
|
double lasthigh = 0.0;
|
|
double lastlow = 0.0;
|
|
|
|
//
|
|
// input variable, we return 0 means nothing passed ...
|
|
if (rates_total < maxLength) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// first calculations ...
|
|
if (prev_calculated == 0) {
|
|
limit = InitializeBuffers();
|
|
} else {
|
|
//
|
|
// find first extremum in the depth ExtLevel or 100 last bars ...
|
|
i = counterZ = 0;
|
|
while(counterZ < level && i < 100) {
|
|
//
|
|
if(zigzagBuffer[i] != 0.0) {
|
|
counterZ++;
|
|
}
|
|
|
|
//
|
|
i++;
|
|
}
|
|
|
|
//
|
|
// no extremum found - recounting all from begin ...
|
|
if(counterZ == 0) {
|
|
limit = InitializeBuffers();
|
|
} else {
|
|
//
|
|
// set start position to found extremum position ...
|
|
limit = i-1;
|
|
|
|
//
|
|
//--- what kind of extremum?
|
|
if(lowBuffer[i] != 0.0) {
|
|
//
|
|
// low extremum ...
|
|
curlow = lowBuffer[i];
|
|
|
|
//
|
|
// will look for the next high extremum ...
|
|
whatlookfor=1;
|
|
} else {
|
|
//
|
|
// high extremum ...
|
|
curhigh = highBuffer[i];
|
|
|
|
//
|
|
// will look for the next low extremum ...
|
|
whatlookfor=-1;
|
|
}
|
|
|
|
//
|
|
// clear the rest data ...
|
|
for(i = limit - 1; i >= 0; i--) {
|
|
//
|
|
lowBuffer[i]=0.0;
|
|
highBuffer[i]=0.0;
|
|
zigzagBuffer[i]=0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Main Calculation Loop ...
|
|
for (i = limit; i >= 0; i--) {
|
|
//
|
|
// find lowest low in depth of bars ...
|
|
extremum = low[
|
|
iLowest(
|
|
_Symbol,
|
|
_Period,
|
|
MODE_LOW,
|
|
depth,
|
|
i
|
|
)
|
|
];
|
|
|
|
//
|
|
// this lowest has been found previously ...
|
|
if (extremum == lastlow) {
|
|
extremum = 0.0;
|
|
} else {
|
|
//
|
|
// new last low ...
|
|
lastlow=extremum;
|
|
|
|
//
|
|
// discard extremum if current low is too high ...
|
|
if(low[i] - extremum > deviation * _Point) {
|
|
extremum=0.0;
|
|
} else {
|
|
//
|
|
// clear previous extremums in backstep bars ...
|
|
for(back = 1; back <= backStep; back++) {
|
|
//
|
|
pos = i + back;
|
|
|
|
//
|
|
if(lowBuffer[pos] != 0 && lowBuffer[pos] > extremum) {
|
|
lowBuffer[pos] = 0.0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// found extremum is current low ...
|
|
if (low[i] == extremum) {
|
|
lowBuffer[i] = extremum;
|
|
} else {
|
|
lowBuffer[i] = 0.0;
|
|
}
|
|
|
|
//
|
|
// find highest high in depth of bars ...
|
|
extremum = high[
|
|
iHighest(
|
|
_Symbol,
|
|
_Period,
|
|
MODE_HIGH,
|
|
depth,
|
|
i
|
|
)
|
|
];
|
|
|
|
//
|
|
// this highest has been found previously ...
|
|
if (extremum == lasthigh) {
|
|
extremum = 0.0;
|
|
} else {
|
|
//
|
|
// new last high ...
|
|
lasthigh=extremum;
|
|
|
|
//
|
|
// discard extremum if current high is too low ...
|
|
if (extremum - high[i] > deviation * Point) {
|
|
extremum = 0.0;
|
|
} else {
|
|
//
|
|
// clear previous extremums in backstep bars ...
|
|
for(back = 1; back <= backStep; back++) {
|
|
//
|
|
pos = i + back;
|
|
|
|
//
|
|
if (highBuffer[pos] != 0 && highBuffer[pos] < extremum) {
|
|
highBuffer[pos] = 0.0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// found extremum is current high ...
|
|
if (high[i] == extremum) {
|
|
highBuffer[i] = extremum;
|
|
} else {
|
|
highBuffer[i] = 0.0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// final cutting ...
|
|
if( whatlookfor == 0) {
|
|
//
|
|
lastlow = 0.0;
|
|
lasthigh = 0.0;
|
|
} else {
|
|
//
|
|
lastlow = curlow;
|
|
lasthigh = curhigh;
|
|
}
|
|
|
|
//
|
|
for(i = limit; i >= 0; i--) {
|
|
switch(whatlookfor) {
|
|
//
|
|
// look for peak or lawn ...
|
|
case 0:
|
|
//
|
|
if (lastlow == 0.0 && lasthigh == 0.0) {
|
|
if(highBuffer[i]!=0.0) {
|
|
//
|
|
lasthigh = High[i];
|
|
lasthighpos = i;
|
|
whatlookfor = -1;
|
|
|
|
//
|
|
zigzagBuffer[i] = lasthigh;
|
|
}
|
|
|
|
//
|
|
if(lowBuffer[i] != 0.0) {
|
|
//
|
|
lastlow = Low[i];
|
|
lastlowpos = i;
|
|
whatlookfor = 1;
|
|
|
|
//
|
|
zigzagBuffer[i] = lastlow;
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
// look for peak ...
|
|
case 1:
|
|
//
|
|
if (
|
|
lowBuffer[i] != 0.0 &&
|
|
lowBuffer[i] < lastlow &&
|
|
highBuffer[i] == 0.0
|
|
) {
|
|
//
|
|
zigzagBuffer[lastlowpos] = 0.0;
|
|
lastlowpos = i;
|
|
lastlow = lowBuffer[i];
|
|
zigzagBuffer[i] = lastlow;
|
|
}
|
|
|
|
//
|
|
if(highBuffer[i] != 0.0 && lowBuffer[i] == 0.0) {
|
|
//
|
|
lasthigh = highBuffer[i];
|
|
lasthighpos = i;
|
|
zigzagBuffer[i] = lasthigh;
|
|
|
|
//
|
|
whatlookfor=-1;
|
|
}
|
|
break;
|
|
|
|
//
|
|
// look for lawn ...
|
|
case -1:
|
|
//
|
|
if(
|
|
highBuffer[i] != 0.0 &&
|
|
highBuffer[i] > lasthigh &&
|
|
lowBuffer[i] == 0.0
|
|
) {
|
|
//
|
|
zigzagBuffer[lasthighpos] = 0.0;
|
|
lasthighpos = i;
|
|
lasthigh = highBuffer[i];
|
|
zigzagBuffer[i] = lasthigh;
|
|
}
|
|
|
|
//
|
|
if(
|
|
lowBuffer[i] !=0.0 &&
|
|
highBuffer[i] == 0.0
|
|
) {
|
|
//
|
|
lastlow = lowBuffer[i];
|
|
lastlowpos = i;
|
|
zigzagBuffer[i] = lastlow;
|
|
whatlookfor=1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Done ...
|
|
return rates_total;
|
|
}
|
|
|
|
//
|
|
// De Initialization ...
|
|
void OnDeinit(const int reason) {
|
|
//
|
|
// RemoveDraws(signalPrefix);
|
|
ChartRedraw(0);
|
|
}
|
|
//
|
|
// END Event Handlers ...
|
|
//
|
|
|
|
//
|
|
// START Functions ...
|
|
//
|
|
int InitializeBuffers() {
|
|
//
|
|
ArrayInitialize(lowBuffer,0.0);
|
|
ArrayInitialize(highBuffer, 0.0);
|
|
ArrayInitialize(zigzagBuffer, 0.0);
|
|
|
|
//
|
|
//--- first counting position
|
|
return(Bars - depth);
|
|
}
|
|
//
|
|
// END Functions ...
|
|
// |