//+------------------------------------------------------------------+
//| AlexSTAL_ZigZagProfExtra.mq4 |
//| AlexSTAL & PPC |
//| Professional Zig-Zag |
//+------------------------------------------------------------------+
#property copyright "Aleksandr Chugunov & George Tischenko"
#include <AlexSTAL_OutsideBar.mqh>
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Red
// Êîëè÷åñòâî áàðîâ äëÿ ðàñ÷åòà ýêñòðåìóìîâ
// íå ìîæåò áûòü ìåíüøå 2
extern int ExtPeriod = 12;
// Ìèíèìàëüíîå ðàññòîÿíèå öåíû ìåæäó ñîñåäíèìè ïèêîì è âïàäèíîé (èíà÷å íå ðåãèñòðèðóåòñÿ)
extern int MinAmplitude = 10;
// Ìèíèìàëüíîå äâèæåíèå öåíû â ïóíêòàõ íà íóëåâîì áàðå äëÿ ïåðåðàñ÷åòà èíäèêàòîðà
extern int MinMotion = 0;
// Èñïîëüçîâàòü áîëåå òî÷íûé àëãîðèòì âû÷èñëåíèÿ ïîðÿäêà ôîðìèðîâàíèÿ High/Low áàðà
extern bool UseSmallerTFforEB = true;
// Ñêîëüêî áàðîâ íåîáõîäèìî ïðîâåðÿòü íà êîððåêòíîñòü óæå ïðîñ÷èòàííîé èñòîðèè
// 0 - âñþ èñòîðèþ
extern int ExtraCheckedBarsCount = 0;
// Áóôåðû èíäèêàòîðà
double UP[], DN[];
// Áóôåð äëÿ êýøèðîâàíèÿ âíåøíåãî áàðà
double OB[];
// =Extra= Â äàííûõ áóôåðàõ áóäåì ñîõðàíÿòü High/Low äëÿ êàæäîãî áàðà
double barH[], barL[];
// Âðåìÿ îòêðûòèÿ ïîñëåäíåãî îáñ÷èòàííîãî áàðà
datetime LastBarTime;
// Çàùèòà îò äîêà÷êè èñòîðèè
int LastBarsCount, LastBarNum;
// Äëÿ îïòèìèçàöèè ðàñ÷åòîâ
double LastBarLastHigh, LastBarLastLow;
// Âðåìÿ ïåðâîãî ýêñòðåìóìà (íåîáõîäèìî äëÿ àëãîðèòìà âíåøíåãî áàðà)
datetime TimeFirstExtBar;
// Ñòàòè÷åñêèå ïåðåìåííûå äëÿ óñêîðåíèÿ ðàñ÷åòîâ
double MP, MM;
// Âñïîìîãàòåëüíàÿ ïåðåìåííàÿ
bool DownloadHistory;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
if (ExtPeriod < 2)
ExtPeriod = 2;
if (MinAmplitude < 0)
MinAmplitude = 0;
MP = NormalizeDouble(MinAmplitude * Point, Digits);
if (MinMotion < 1)
MinMotion = 1;
MM = NormalizeDouble(MinMotion * Point, Digits);
if (ExtraCheckedBarsCount < 0) // =Extra=
ExtraCheckedBarsCount = 0;
//---- indicators
IndicatorDigits(Digits);
IndicatorBuffers(5);
SetIndexBuffer(0, UP);
SetIndexStyle(0, DRAW_ZIGZAG);
SetIndexBuffer(1, DN);
SetIndexStyle(1, DRAW_ZIGZAG);
SetIndexBuffer(2, OB);
SetIndexBuffer(3, barH); // =Extra=
SetIndexBuffer(4, barL); // =Extra=
LastBarsCount = 0;
DownloadHistory = true;
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
// Áëîê ïîëíîé èíèöèàëèçàöèè ïðè ïîäêà÷êå èñòîðèè
// ----------------------------------------------
int counted_bars = IndicatorCounted(), i;
// Ïðîâåðèì è îáíóëèì ïðè íåîáõîäèìîñòè èíäèêàòîðíûå áóôåðû
if ( counted_bars != 0 )
for (i = (Bars-counted_bars-2); i >= 0; i--)
{
if (UP[i] != EMPTY_VALUE)
UP[i] = EMPTY_VALUE;
if (DN[i] != EMPTY_VALUE)
DN[i] = EMPTY_VALUE;
if (OB[i] != EMPTY_VALUE)
OB[i] = EMPTY_VALUE;
}
// Áåð忏íîãî... êàê ãîâîðèòñÿ ñàìè çíàåòå ÷òî
// Ïðè ïîèñêå áàãà MT4 äîáàâèë...
if (LastBarsCount == 0)
LastBarsCount = Bars;
if (Bars < LastBarsCount)
DownloadHistory = true;
LastBarsCount = Bars;
// IndicatorCounted() ìîæåò îáíóëèòñÿ ïðè âîññòàíîâëåíèè ñâÿçè
if ( counted_bars == 0 )
DownloadHistory = true;
// Çàùèòà îò äîêà÷êè ïðîïóùåííîé èñòîðèè âíóòðü ðàñ÷åòà
if ( (counted_bars != 0) && (LastBarNum != 0) )
if ( (Bars - iBarShift(NULL, 0, LastBarTime, true)) != LastBarNum )
DownloadHistory = true;
// Ïîëíàÿ èíèöèàëèçàöèÿ
if (DownloadHistory)
{
ArrayInitialize(UP, EMPTY_VALUE);
ArrayInitialize(DN, EMPTY_VALUE);
ArrayInitialize(OB, EMPTY_VALUE);
ArrayInitialize(barH, EMPTY_VALUE); // =Extra=
ArrayInitialize(barL, EMPTY_VALUE); // =Extra=
TimeFirstExtBar = 0;
counted_bars = 0;
LastBarTime = 0;
LastBarNum = 0;
DownloadHistory = false;
}
// Áëîê îïðåäåëåíèÿ ôîðìèðîâàíèÿ íîâîãî áàðà (ïåðâûé äîøåäøèé òèê)
bool NewBar = false;
if (LastBarTime != Time[0])
{
NewBar = true;
LastBarTime = Time[0];
LastBarNum = Bars;
// íîâûé áàð - îáíóëèì ïåðåìåííûå äëÿ îïòèìèçàöèè ðàñ÷åòîâ
LastBarLastHigh = High[0];
LastBarLastLow = Low[0];
}
// Âû÷èñëèì íåîáõîäèìîå êîëè÷åñòâî áàðîâ äëÿ ïåðåñ÷åòà
int BarsForRecalculation;
if ( counted_bars != 0 )
{
BarsForRecalculation = Bars - counted_bars - 1;
// Áëîê îïòèìèçàöèè ðàñ÷åòîâ
if (!NewBar)
{
if ( (NormalizeDouble(High[0]-LastBarLastHigh, Digits) >= MM) || (NormalizeDouble(LastBarLastLow-Low[0], Digits) >= MM) )
{
LastBarLastHigh = High[0];
LastBarLastLow = Low[0];
} else {
// Íà äàííîì òèêå ðàñ÷åò ïðîèçâîäèòü íå áóäåì, òàê êàê öåíà èçìåíÿëàñü âíóòðè
// íóëåâîãî áàðà èëè æå å¸ èçìåíåíèÿ íå áûëè áîëüøå ìèíèìàëüíîãî ïîðîãà,
// çàäàííîãî â ïåðåìåííîé MinMotion
return(0);
}
}
} else {
BarsForRecalculation = Bars - ExtPeriod;
}
// =Extra=
// Çàïîëíèì ìàññèâû íîâûìè çíà÷åíèÿìè ñ àíàëèçîì ñòàðûõ
int FoundDifference = -1;
int tmpCB = Bars - 1;
if ( ExtraCheckedBarsCount > 0)
tmpCB = MathMin(tmpCB, ExtraCheckedBarsCount);
for (i = tmpCB; i >= (Bars - counted_bars); i--)
{
if (barH[i] != High[i])
{
FoundDifference = MathMax(FoundDifference, i);
barH[i] = High[i];
}
if (barL[i] != Low[i])
{
FoundDifference = MathMax(FoundDifference, i);
barL[i] = Low[i];
}
}
// Äëÿ áàðîâ, ïîäñ÷èòàííûõ íà äàííîì òèêå ïðîñòî çàïîëíÿåì ìàññèâû
for (i = (Bars - counted_bars - 1); i >= 0; i--)
{
barH[i] = High[i];
barL[i] = Low[i];
}
// Áûëè íàéäåíû ïåðåðàñ÷åòû â ðàñ÷èòàííîì ïåðèîäå
if ( FoundDifference != -1 )
{
for (i = FoundDifference; i >= 0; i--)
{
UP[i] = EMPTY_VALUE;
DN[i] = EMPTY_VALUE;
OB[i] = EMPTY_VALUE;
}
BarsForRecalculation = FoundDifference;
}
// =Extra= end
//======================================================
//======== îñíîâíîé öèêë ===============================
//======================================================
int LET;
double H, L, Fup, Fdn;
int lastUPbar, lastDNbar;
double lastUP, lastDN;
int m, n; // Äëÿ ïîèñêà ïîñëåäíåãî ýêñòðåìóìà
for (i = BarsForRecalculation; i >= 0; i--)
{
// Ïîèñê ïîñëåäíåãî ýêñòðåìóìà
// ---------------------------
lastUP = 0;
lastDN = 0;
lastUPbar = i;
lastDNbar = i;
LET = 0;
m = 0; n = 0;
while ( UP[lastUPbar] == EMPTY_VALUE )
{
if ( lastUPbar > (Bars-ExtPeriod) )
break;
lastUPbar++;
}
lastUP = UP[lastUPbar]; //âîçìîæíî íàøëè ïîñëåäíèé ïèê
while ( DN[lastDNbar] == EMPTY_VALUE)
{
if ( lastDNbar > (Bars-ExtPeriod) )
break;
lastDNbar++;
}
lastDN = DN[lastDNbar]; //âîçìîæíî íàøëè ïîñëåäíþþ âïàäèíó
if ( lastUPbar < lastDNbar)
LET = 1;
if ( lastUPbar > lastDNbar)
LET = -1;
if ( lastUPbar == lastDNbar)
{
//lastUPbar==lastDNbar íàäî óçíàòü, êàêîé îäèíî÷íûé ýêñòðåìóì áûë ïîñëåäíèì:
m = lastUPbar;
n = m;
while ( m == n )
{
m++; n++;
while ( UP[m] == EMPTY_VALUE )
{
if ( m > (Bars-ExtPeriod) )
break;
m++;
} //âîçìîæíî íàøëè ïîñëåäíèé ïèê
while ( DN[n] == EMPTY_VALUE )
{
if ( n > (Bars-ExtPeriod) )
break;
n++;
} //âîçìîæíî íàøëè ïîñëåäíþþ âïàäèíó
if ( MathMax(m, n) > (Bars-ExtPeriod) )
break;
}
if (m < n)
LET = 1; //áàçîâûé îòñ÷åò - ïèê
else
if (m > n)
LET = -1; //áàçîâûé îòñ÷åò - âïàäèíà
}
// åñëè LET==0 - çíà÷èò ýòî íà÷àëî îòñ÷åòà èëè â ñàìîì íà÷àëå çàôèêñèðîâàí âíåøíèé áàð ñ 2 ýêñòðåìóìàìè
// Êîíåö ïîèñêà ïîñëåäíåãî ýêñòðåìóìà
// ----------------------------------
//---- ðàññìîòðèì öåíîâûå ýêñòðåìóìû çà ðàñ÷åòíûé ïåðèîä:
H = High[iHighest(NULL, 0, MODE_HIGH, ExtPeriod, i)];
L = Low[iLowest(NULL, 0, MODE_LOW, ExtPeriod, i)];
Fup = High[i];
Fdn = Low[i];
//---- ïðîàíàëèçèðóåì ñèòóàöèþ è ðàññìîòðèì âîçìîæíîñòü ðåãèñòðàöèè íîâûõ ýêñòðåìóìîâ:
switch(Comb(i,H,L,Fup,Fdn))
{
//---- íà ðàñ÷åòíîì áàðå ïîòåíöèàëüíûé ïèê (Comb)
case 1 :
switch(LET)
{
case 1 :
//ïðåäûäóùèé ýêñòðåìóì òîæå ïèê, âûáèðàåì áîëüøèé:
if ( lastUP < Fup )
{
UP[lastUPbar] = EMPTY_VALUE;
UP[i] = Fup;
}
break;
case -1 :
if ( (Fup-lastDN) > MP ) //ïðåäûäóùèé ýêñòðåìóì - âïàäèíà
UP[i] = Fup;
break;
default :
UP[i] = Fup;
TimeFirstExtBar = iTime(NULL, 0, i); //0 - çíà÷èò ýòî íà÷àëî ðàñ÷åòà
break;
}
break;
//---- íà ðàñ÷åòíîì áàðå ïîòåíöèàëüíàÿ âïàäèíà (Comb)
case -1 :
switch(LET)
{
case 1 :
if ( (lastUP-Fdn) > MP ) //ïðåäûäóùèé ýêñòðåìóì - ïèê
DN[i] = Fdn;
break;
case -1 :
//ïðåäûäóùèé ýêñòðåìóì òîæå âïàäèíà, âûáèðàåì ìåíüøóþ:
if ( lastDN > Fdn )
{
DN[lastDNbar] = EMPTY_VALUE;
DN[i] = Fdn;
}
break;
default :
DN[i] = Fdn;
TimeFirstExtBar = iTime(NULL, 0, i); //0 - çíà÷èò ýòî íà÷àëî ðàñ÷åòà
break;
}
break;
//---- íà ðàñ÷åòíîì áàðå ïîòåíöèàëüíûé ïèê è ïîòåíöèàëüíàÿ âïàäèíà (Comb)
case 2 : //ïðåäïîëîæèòåëüíî ñíà÷àëà ñôîðìèðîâàëñÿ LOW ïîòîì HIGH (áû÷èé áàð)
switch(LET)
{
case 1 : //ïðåäûäóùèé ýêñòðåìóì - ïèê
if ( (Fup-Fdn) > MP )
{
if ( (lastUP-Fdn) > MP )
{
UP[i] = Fup;
DN[i] = Fdn;
} else {
if ( lastUP < Fup )
{
UP[lastUPbar] = EMPTY_VALUE;
UP[i] = Fup;
}
}
} else {
if ( (lastUP-Fdn) > MP )
DN[i] = Fdn;
else {
if ( lastUP < Fup )
{
UP[lastUPbar] = EMPTY_VALUE;
UP[i] = Fup;
}
}
}
break;
case -1 : //ïðåäûäóùèé ýêñòðåìóì - âïàäèíà
if ( (Fup-Fdn) > MP )
{
UP[i] = Fup;
if ( (Fdn < lastDN) && (iTime(NULL, 0, lastDNbar) > TimeFirstExtBar) )
{
DN[lastDNbar] = EMPTY_VALUE;
DN[i] = Fdn;
}
} else {
if ( (Fup-lastDN) > MP )
UP[i] = Fup;
else {
if ( lastDN > Fdn )
{
DN[lastDNbar] = EMPTY_VALUE;
DN[i] = Fdn;
}
}
}
break;
default: break;
} //switch LET
break;
//---- íà ðàñ÷åòíîì áàðå ïîòåíöèàëüíûé ïèê è ïîòåíöèàëüíàÿ âïàäèíà (Comb)
case -2 : //ïðåäïîëîæèòåëüíî ñíà÷àëà ñôîðìèðîâàëñÿ HIGH ïîòîì LOW (ìåäâåæèé áàð)
switch(LET)
{
case 1 : //ïðåäûäóùèé ýêñòðåìóì - ïèê
if ( (Fup-Fdn) > MP )
{
DN[i] = Fdn;
if ( (lastUP < Fup) && (iTime(NULL, 0, lastUPbar) > TimeFirstExtBar) )
{
UP[lastUPbar] = EMPTY_VALUE;
UP[i] = Fup;
}
} else {
if ( (lastUP-Fdn) > MP)
DN[i] = Fdn;
else {
if ( lastUP < Fup )
{
UP[lastUPbar] = EMPTY_VALUE;
UP[i] = Fup;
}
}
}
break;
case -1 : //ïðåäûäóùèé ýêñòðåìóì - âïàäèíà
if ( (Fup-Fdn) > MP )
{
if ( (Fup-lastDN) > MP )
{
UP[i] = Fup;
DN[i] = Fdn;
} else {
if (lastDN > Fdn)
{
DN[lastDNbar] = EMPTY_VALUE;
DN[i] = Fdn;
}
}
} else {
if ( (Fup-lastDN) > MP )
UP[i] = Fup;
else {
if ( lastDN > Fdn)
{
DN[lastDNbar] = EMPTY_VALUE;
DN[i] = Fdn;
}
}
}
break;
default: break;
} //switch LET
break;
default: break;
} // switch (ãëàâíûé)
} // for (ãëàâíûé)
//----
return(0);
}
//+------------------------------------------------------------------+
//| ôóíêöèÿ àíàëèçà òåêóùåé ñèòóàöèè |
//+------------------------------------------------------------------+
int Comb(int i, double H, double L, double Fup, double Fdn)
{
//----
if (Fup==H && (Fdn==0 || (Fdn>0 && Fdn>L))) return(1); //íà ðàñ÷åòíîì áàðå ïîòåíöèàëüíûé ïèê
if (Fdn==L && (Fup==0 || (Fup>0 && Fup<H))) return(-1); //íà ðàñ÷åòíîì áàðå ïîòåíöèàëüíàÿ âïàäèíà
if (Fdn==L && Fup==H) //íà ðàñ÷åòíîì áàðå ïîòåíöèàëüíûé ïèê è ïîòåíöèàëüíàÿ âïàäèíà
{
// Ïîïûòêà íàéòè êåøèðîâàííûå äàííûå â áóôåðå OB[]
int OrderFormationHL = OB[i];
if (OrderFormationHL == EMPTY_VALUE)
{
OrderFormationHL = GetOrderFormationBarHighLow(Symbol(), Period(), i, UseSmallerTFforEB);
OB[i] = OrderFormationHL;
}
switch(OrderFormationHL)
{
case -1: //ïðåäïîëîæèòåëüíî ñíà÷àëà ñôîðìèðîâàëñÿ LOW ïîòîì HIGH (áû÷èé áàð)
return(2);
break;
case 1: //ïðåäïîëîæèòåëüíî ñíà÷àëà ñôîðìèðîâàëñÿ HIGH ïîòîì LOW (ìåäâåæèé áàð)
return(-2);
break;
}
}
//----
return(0); //íà ðàñ÷åòíîì áàðå ïóñòî...
}
Comments