ZigAndZag[alert]
Download scriptThis script is a sophisticated technical analysis tool designed for the MetaTrader 4 platform. It functions by analyzing price movements to identify significant structural trends and specific entry/exit points, effectively acting as a "scalpel" to separate high-probability signals from market noise.
The logic operates through three distinct analytical phases:
1. Structural Foundation (Identification of Extremes)
The script begins by scanning historical price data to identify two types of movements:
- Slalom Points: These are short-term price fluctuations. The tool identifies local highs and lows within a small window to map out the immediate "zigzag" of the market.
- Keel Over Points: These represent much larger, broader structural turns in the market. By looking at a wider timeframe, the script identifies major shifts in direction (the "Keel Over") that define the overarching trend.
2. Data Refining and Cleaning
Once the raw highs and lows are identified, the script performs a secondary refinement process. It cleans the data by ensuring that multiple signals don't overlap or contradict one another. For example, if two opposing signals appear too close together, it filters them to ensure only the most significant and relevant price pivots remain. This prevents "false positives" where the market might appear to be reversing when it is actually just consolidating.
3. Trend Synthesis and Signal Generation
In the final phase, the script merges these two different perspectives—the short-term "Slalom" and the long-term "Keel Over"—into a unified trend line.
- Trend Detection: It uses the major structural points to determine if the current market environment is in an "Up Trend" or a "Down Trend."
- Precision Execution: By combining the broader trend with the smaller "Slalom" fluctuations, the tool generates specific trading signals:
- Buy/Sell Signals: Triggered when a short-term price move aligns with the dominant long-term trend.
- Limit Orders: The script can identify potential "reversal zones" where a trade might be pending if the price hits a specific calculated value (the "Navel") that suggests a high probability of a turnaround.
Summary of Operation
In simple terms, the script looks at the "big picture" to see which way the ocean current is moving, while simultaneously watching the "small waves" to find the best moment to jump in. It highlights these opportunities on your chart using visual markers (arrows and lines), distinguishing between immediate aggressive entries and strategic limit orders based on the interplay between short-term volatility and long-term structure.
//+------------------------------------------------------------------+
//| ZigAndZagScalpel.mq4 |
//| Bookkeeper, 2006, yuzefovich@gmail.com |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 7 // Èëè 8 - äëÿ testBuffer
#property indicator_color1 Aqua
#property indicator_color2 Black
#property indicator_color3 Black
#property indicator_color4 Black
#property indicator_color5 Yellow
#property indicator_color6 Lime
#property indicator_color7 OrangeRed
//#property indicator_color8 Yellow // Äëÿ ïîäáîðà ÷åãî-íèáóäü
extern int KeelOver=55; // Äëÿ M15
extern int Slalom=17; // Äëÿ M15
double KeelOverZigAndZagSECTION[];
double KeelOverZagBuffer[];
double SlalomZigBuffer[];
double SlalomZagBuffer[];
double LimitOrdersBuffer[];
double BuyOrdersBuffer[];
double SellOrdersBuffer[];
//double testBuffer[];
//+------------------------------------------------------------------+
int shift,back,CountBar,Backstep=3;
int LastSlalomZagPos,LastSlalomZigPos,LastKeelOverZagPos,LastKeelOverZigPos;
double Something,LimitPoints,Navel;
double CurKeelOverZig,CurKeelOverZag,CurSlalomZig,CurSlalomZag;
double LastSlalomZag,LastSlalomZig,LastKeelOverZag,LastKeelOverZig;
bool TrendUp,SetBuyOrder,SetLimitOrder,SetSellOrder,Second=false;
string LastZigOrZag="None";
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
int init()
{
SetIndexBuffer(0,KeelOverZigAndZagSECTION);
SetIndexStyle(0,DRAW_SECTION,STYLE_DOT);//DRAW_SECTION èëè DRAW_NONE
SetIndexEmptyValue(0,0.0);
SetIndexBuffer(1,KeelOverZagBuffer);
SetIndexStyle(1,DRAW_NONE);
SetIndexEmptyValue(1,0.0);
SetIndexBuffer(2,SlalomZigBuffer);
SetIndexStyle(2,DRAW_NONE);
SetIndexEmptyValue(2,0.0);
SetIndexBuffer(3,SlalomZagBuffer);
SetIndexStyle(3,DRAW_NONE);
SetIndexEmptyValue(3,0.0);
SetIndexBuffer(4,LimitOrdersBuffer);
SetIndexStyle(4,DRAW_ARROW);
SetIndexArrow(4,108);
SetIndexEmptyValue(4,0.0);
SetIndexBuffer(5,BuyOrdersBuffer);
SetIndexStyle(5,DRAW_ARROW);
SetIndexArrow(5,233);
SetIndexEmptyValue(5,0.0);
SetIndexBuffer(6,SellOrdersBuffer);
SetIndexStyle(6,DRAW_ARROW);
SetIndexArrow(6,234);
SetIndexEmptyValue(6,0.0);
// SetIndexStyle(7,DRAW_SECTION);
// SetIndexBuffer(7,testBuffer);
// SetIndexEmptyValue(7,0.0);
return(0);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
int start()
{
CountBar=Bars-KeelOver;
LimitPoints=Ask-Bid;
if(CountBar<=3*KeelOver) return(-1); // Ìàëîâàòî áóäåò
if(KeelOver<=2*Slalom) return(-1); // Òùàòåëüíåå íàäî
// Çà÷èñòêà íåïðàâèëüíîé èñòîðèè
for(shift=Bars-1; shift>Bars-KeelOver; shift--)
{
SlalomZagBuffer[shift]=0.0;
SlalomZigBuffer[shift]=0.0;
KeelOverZagBuffer[shift]=0.0;
KeelOverZigAndZagSECTION[shift]=0.0;
LimitOrdersBuffer[shift]=0.0;
BuyOrdersBuffer[shift]=0.0;
SellOrdersBuffer[shift]=0.0;
// testBuffer[shift]=0.0;
}
//+---Ïåðâûé ïîõîä ïî èñòîðèè----------------------------------------+
The_First_Crusade();
//+---Âòîðîé ïðîõîä ïî èñòîðè÷åñêèì ìåñòàì---------------------------+
//+---ñ öåëüþ ïîä÷èñòêè íåâåðíî ïîíÿòûõ ñîáûòèé----------------------+
LastSlalomZag=-1; LastSlalomZagPos=-1;
LastSlalomZig=-1; LastSlalomZigPos=-1;
LastKeelOverZag=-1; LastKeelOverZagPos=-1;
LastKeelOverZig=-1; LastKeelOverZigPos=-1;
The_Second_Crusade();
//+---Òðåòèé èñòîðè÷åñêèé ýêñêóðñ - ïîñòðîåíèå "òðåíäà"--------------+
//+---è ðàññòàíîâêà "òîðãîâûõ ñèãíàëîâ"------------------------------+
LastSlalomZag=-1; LastSlalomZagPos=-1;
LastSlalomZig=-1; LastSlalomZigPos=-1;
LastZigOrZag="None";
The_Third_Crusade();
//+---À ÷åãî ìû òåïåðü áóäåì èìåòü çäåñü è ñåé÷àñ?-------------------+
Shift_Zerro();
return(0);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
void The_First_Crusade()
{
for(shift=CountBar; shift>0; shift--)
{
// Ïîèñê òî÷åê "âñòàë â ïîçó" - "óøåë ñ ðûíêà"
CurSlalomZig=Low[Lowest(NULL,0,MODE_LOW,Slalom,shift)];
CurSlalomZag=High[Highest(NULL,0,MODE_HIGH,Slalom,shift)];
// Ïðîâåðÿåì shift íà íàëè÷èå î÷åðåäíîãî ÑëàëîìÇèãà äëÿ âõîäà
// â ïîêóïêó èëè äëÿ âûõîäà èç ïðîäàæè
if(CurSlalomZig==LastSlalomZig) CurSlalomZig=0.0;
else
{
LastSlalomZig=CurSlalomZig;
if((Low[shift]-CurSlalomZig)>LimitPoints) CurSlalomZig=0.0;
else
{
// Íà èíòåðâàëå Backstep ìîæåò áûòü òîëüêî îäèí Çèã,
// îñòàâëÿåì òîëüêî ïîñëåäíèé, áîëåå ðàííèå óáèðàåì
for(back=1; back<=Backstep; back++)
{
Something=SlalomZigBuffer[shift+back];
if((Something!=0)&&(Something>CurSlalomZig))
SlalomZigBuffer[shift+back]=0.0;
}
}
}
// Ïðîâåðÿåì shift íà íàëè÷èå î÷åðåäíîãî ÑëàëîìÇàãà äëÿ âõîäà âíèç
// èëè äëÿ âûõîäà èç ïîêóïêè
if(CurSlalomZag==LastSlalomZag) CurSlalomZag=0.0;
else
{
LastSlalomZag=CurSlalomZag;
if((CurSlalomZag-High[shift])>LimitPoints) CurSlalomZag=0.0;
else
{
// Íà èíòåðâàëå Backstep ìîæåò áûòü òîëüêî îäèí Çàã,
// îñòàâëÿåì òîëüêî ïîñëåäíèé, áîëåå ðàííèå óáèðàåì
for(back=1; back<=Backstep; back++)
{
Something=SlalomZagBuffer[shift+back];
if((Something!=0)&&(Something<CurSlalomZag))
SlalomZagBuffer[shift+back]=0.0;
}
}
}
// Âñå, ÷òî íàøëè íîâåíüêîãî è ïóñòûøêè - êëàäåì â áóôåðà ñëàëîìà
SlalomZigBuffer[shift]=CurSlalomZig;
SlalomZagBuffer[shift]=CurSlalomZag;
// Èùåì òî÷êè ðàçâîðîòà äëÿ ïîñòðîåíèÿ "ëèíåéíîãî òðåíäà", ïðè ýòîì
// â áóôåð ðàçâîðîòîâ ZigAndZag ïîêà ÷òî áóäåì êëàñòü òîëüêî ÎâåðêèëüÇèãè
CurKeelOverZig=Low[Lowest(NULL,0,MODE_LOW,KeelOver,shift)];
CurKeelOverZag=High[Highest(NULL,0,MODE_HIGH,KeelOver,shift)];
// Ïðîâåðÿåì shift íà íàëè÷èå î÷åðåäíîãî ÎâåðêèëüÇèãà
if(CurKeelOverZig==LastKeelOverZig) CurKeelOverZig=0.0;
else
{
LastKeelOverZig=CurKeelOverZig;
if((Low[shift]-CurKeelOverZig)>LimitPoints) CurKeelOverZig=0.0;
else
{
// Íà èíòåðâàëå Backstep ìîæåò áûòü òîëüêî îäèí Çèã,
// îñòàâëÿåì òîëüêî ïîñëåäíèé, áîëåå ðàííèå óáèðàåì
for(back=1; back<=Backstep; back++)
{
Something=KeelOverZigAndZagSECTION[shift+back];
if((Something!=0)&&(Something>CurKeelOverZig))
KeelOverZigAndZagSECTION[shift+back]=0.0;
}
}
}
// Ïðîâåðÿåì shift íà íàëè÷èå î÷åðåäíîãî ÎâåðêèëüÇàãà
if(CurKeelOverZag==LastKeelOverZag) CurKeelOverZag=0.0;
else
{
LastKeelOverZag=CurKeelOverZag;
if((CurKeelOverZag-High[shift])>LimitPoints) CurKeelOverZag=0.0;
else
{
// Íà èíòåðâàëå Backstep ìîæåò áûòü òîëüêî îäèí Çàã,
// áîëåå ðàííèå óáèðàåì
for(back=1; back<=Backstep; back++)
{
Something=KeelOverZagBuffer[shift+back];
if((Something!=0)&&(Something<CurKeelOverZag))
KeelOverZagBuffer[shift+back]=0.0;
}
}
}
// Âñå, ÷òî íàøëè èëè íå íàøëè - êëàäåì â áóôåðà ðàçâîðîòîâ
KeelOverZigAndZagSECTION[shift]=CurKeelOverZig;
KeelOverZagBuffer[shift]=CurKeelOverZag;
}
return;
}
//+------------------------------------------------------------------+
void The_Second_Crusade()
{
// Ïðîñòî ïîä÷èñòêà ëèøíåãî
for(shift=CountBar; shift>0; shift--)
{
CurSlalomZig=SlalomZigBuffer[shift];
CurSlalomZag=SlalomZagBuffer[shift];
if((CurSlalomZig==0)&&(CurSlalomZag==0)) continue;
if(CurSlalomZag!=0)
{
if(LastSlalomZag>0)
{
if(LastSlalomZag<CurSlalomZag) SlalomZagBuffer[LastSlalomZagPos]=0;
else SlalomZagBuffer[shift]=0;
}
if(LastSlalomZag<CurSlalomZag || LastSlalomZag<0)
{
LastSlalomZag=CurSlalomZag;
LastSlalomZagPos=shift;
}
LastSlalomZig=-1;
}
if(CurSlalomZig!=0)
{
if(LastSlalomZig>0)
{
if(LastSlalomZig>CurSlalomZig) SlalomZigBuffer[LastSlalomZigPos]=0;
else SlalomZigBuffer[shift]=0;
}
if((CurSlalomZig<LastSlalomZig)||(LastSlalomZig<0))
{
LastSlalomZig=CurSlalomZig;
LastSlalomZigPos=shift;
}
LastSlalomZag=-1;
}
CurKeelOverZig=KeelOverZigAndZagSECTION[shift];
CurKeelOverZag=KeelOverZagBuffer[shift];
if((CurKeelOverZig==0)&&(CurKeelOverZag==0)) continue;
if(CurKeelOverZag !=0)
{
if(LastKeelOverZag>0)
{
if(LastKeelOverZag<CurKeelOverZag)
KeelOverZagBuffer[LastKeelOverZagPos]=0;
else KeelOverZagBuffer[shift]=0.0;
}
if(LastKeelOverZag<CurKeelOverZag || LastKeelOverZag<0)
{
LastKeelOverZag=CurKeelOverZag;
LastKeelOverZagPos=shift;
}
LastKeelOverZig=-1;
}
if(CurKeelOverZig!=0)
{
if(LastKeelOverZig>0)
{
if(LastKeelOverZig>CurSlalomZig)
KeelOverZigAndZagSECTION[LastKeelOverZigPos]=0;
else KeelOverZigAndZagSECTION[shift]=0;
}
if((CurKeelOverZig<LastKeelOverZig)||(LastKeelOverZig<0))
{
LastKeelOverZig=CurKeelOverZig;
LastKeelOverZigPos=shift;
}
LastKeelOverZag=-1;
}
}
return;
}
//+------------------------------------------------------------------+
void The_Third_Crusade()
{
bool first=true;
for(shift=CountBar; shift>0; shift--)
{
// Íèçâåãàåì ïðåæíèõ ïðîðîêîâ
LimitOrdersBuffer[shift]=0.0;
BuyOrdersBuffer[shift]=0.0;
SellOrdersBuffer[shift]=0.0;
// Çàäàåì öåíòð ìèðîçäàíüÿ èíòåðâàëà shift (ïî ëþáîìó -
// ñïîñîá áîëüøîãî ïîëèòè÷åñêîãî âåñà íå èìååò)
Navel=(5*Close[shift]+2*Open[shift]+High[shift]+Low[shift])/9;
// Åñëè îâåðêèëü - ñìîòðèì,
// êóäà (ìîæåò áûòü) äàëüøå ñåéìîìåíòíî ïîéäåì: ââåðõ èëè âíèç
if(KeelOverZigAndZagSECTION[shift]!=0.0)
{
TrendUp=true;
first=false;
Alert("Trend UP Signal");
}
if(KeelOverZagBuffer[shift]!=0.0)
{
TrendUp=false;
first=false;
Alert("Trend Down Signal");
}
// Ñîáèðàåì â KeelOverZigAndZagSECTION è ÎâåðêèëüÇèãè, è ÎâåðêèëüÇàãè,
// è ïóñòûøêè - âñå â îäíó êó÷êó, òàêèì îáðàçîì ïîëó÷àåì äîëãîèãðàþùèé
// ZigAndZag, íàòÿãèâàÿ íèòü "òðåíäà" íà ïóïêè ðàçâîðîòíûõ ñâå÷åê
if(KeelOverZagBuffer[shift]!=0.0 || KeelOverZigAndZagSECTION[shift]!=0.0)
{
KeelOverZigAndZagSECTION[shift]=Navel;
}
else KeelOverZigAndZagSECTION[shift]=0.0;
// Ïðîâåðÿåì shift íà íàëè÷èå ÑëàëîìÇèãà èëè ÑëàëîìÇàãà
if(SlalomZigBuffer[shift]!=0.0)
{
LastZigOrZag="Zig";
LastSlalomZig=Navel;
SetBuyOrder=false;
SetLimitOrder=false;
SetSellOrder=false;
}
if(SlalomZagBuffer[shift]!=0.0)
{
LastZigOrZag="Zag";
LastSlalomZag=Navel;
SetBuyOrder=false;
SetLimitOrder=false;
SetSellOrder=false;
}
// è, åñëè íè ÑëàëîìÇèãà, íè ÑëàëîìÇàãà óæå íåò,
// à îâåðêèëü óæå áûë - ñìîòðèì, à ÷òî åñòü ïî âõîäó-âûõîäó
if(SlalomZigBuffer[shift]==0.0 &&
SlalomZagBuffer[shift]==0.0 &&
first==false) Slalom_With_A_Scalpel();
}
return;
}
//+------------------------------------------------------------------+
void Shift_Zerro()
{
shift=0;
Navel=(5*Close[0]+2*Open[0]+High[0]+Low[0])/9;
Slalom_With_A_Scalpel();
KeelOverZigAndZagSECTION[0]=Navel;
return;
}
//+------------------------------------------------------------------+
void Slalom_With_A_Scalpel()
{
// Ïðîâåðÿåì ñóùåñòâóþùèé ñèãíàë íà èìååò ïðàâî áûòü
// èëè íà åñëè íå ñòîèò, à õîòåëîñü áû:
// åñëè õîä ÷èñòî êîíêðåòíî ïî æèçíè - çàáèâàåì Ñòðåëêó íà äåíüãè,
// åñëè ïðîòèâ - ñòàâèì íà øóõåð Øàðèêà Äåëàé-Íîãè
if(LastZigOrZag=="Zig")
{
if(TrendUp==true)
{
if((Navel-LastSlalomZig)>=LimitPoints && SetBuyOrder==false)
{
SetBuyOrder=true;
BuyOrdersBuffer[shift]=Low[shift+1];
LastSlalomZigPos=shift;
}
if(Navel<=LastSlalomZig && SetBuyOrder==true)
{
SetBuyOrder=false;
BuyOrdersBuffer[LastSlalomZigPos]=0.0;
LastSlalomZigPos=-1;
}
}
if(TrendUp==false)
{
if(Navel>LastSlalomZig && SetLimitOrder==false)
{
SetLimitOrder=true;
LimitOrdersBuffer[shift]=Navel;
// LimitOrdersBuffer[shift]=Close[shift];
LastSlalomZigPos=shift;
}
if(Navel<=LastSlalomZig && SetLimitOrder==true)
{
SetLimitOrder=false;
LimitOrdersBuffer[LastSlalomZigPos]=0.0;
LastSlalomZigPos=-1;
}
}
}
if(LastZigOrZag=="Zag")
{
if(TrendUp==false)
{
if((LastSlalomZag-Navel)>=LimitPoints && SetSellOrder==false)
{
SetSellOrder=true;
SellOrdersBuffer[shift]=High[shift+1];
LastSlalomZagPos=shift;
}
if(Navel>=LastSlalomZag && SetSellOrder==true)
{
SetSellOrder=false;
SellOrdersBuffer[LastSlalomZagPos]=0.0;
LastSlalomZagPos=-1;
}
}
if(TrendUp==true)
{
if(LastSlalomZag>Navel && SetLimitOrder==false)
{
SetLimitOrder=true;
LimitOrdersBuffer[shift]=Navel;
// LimitOrdersBuffer[shift]=Close[shift];
LastSlalomZagPos=shift;
}
if(Navel>=LastSlalomZag && SetLimitOrder==true)
{
SetLimitOrder=false;
LimitOrdersBuffer[LastSlalomZagPos]=0.0;
LastSlalomZagPos=-1;
}
}
}
return;
}
//+--Ñîáñòâåííî, ÿ âñå ñêàçàë. Çàáàâíî, åñëè âñå ýòî ðàáîòàòü áóäåò--+
//+------------------------------------------------------------------+
Comments