GannSwingsXV_v1
Download scriptThis script is designed to analyze price movements on a trading chart by identifying specific "swings"—the significant highs and lows that define the market's structure. Instead of just showing every small fluctuation, it filters the data to highlight primary trends and structural shifts.
Here is a breakdown of how the logic functions:
Core Mechanics
The script works by constantly monitoring the price action (Highs and Lows) as new bars form. It categorizes these movements into two main types of behavior:
1. Trend Continuation The tool tracks whether the market is currently in an uptrend or a downtrend.
- In an uptrend, it looks for new highs. If the price moves higher while maintaining the trend's momentum, it identifies these as continuing points.
- In a downtrend, it tracks new lows, marking them as structural points of the current move.
2. Trend Breakouts and Reversals The script is programmed to detect when the price "breaks out" of its previous behavior. It monitors how many consecutive bars are moving in a certain direction (based on a user-defined "kind" setting). When the price reverses or breaches a specific count of these movements, the logic triggers a shift:
- It identifies the point where a downtrend has ended and an uptrend begins (or vice versa).
- When this shift happens, it marks the new high or low and updates the "Trend Buffer," effectively flipping the internal logic to start tracking the new direction.
Special Feature: Outside Bars
A unique part of this logic is how it handles "Outside Bars"—bars where the price range (the distance between the High and Low) completely encompasses the previous swing's range.
- The script can detect these specific high-volatility moments.
- Depending on your settings, it can visually flag these bars to show where the market expanded significantly beyond the established boundaries.
Dynamic Updating
The script includes a "Move Last Swing" feature. This allows the logic to be more reactive: if a new bar reaches the exact same high or low as the previous swing, the script can shift its focus to the most recent bar. This ensures that the most current price data is prioritized in the visual output.
Summary for the User
Essentially, this tool cleans up the "noise" of a chart. It looks at the price history, determines if it is moving up or down based on specific structural rules, and draws a path connecting the important peaks and valleys. It helps you see the "skeleton" of the market trend rather than just the daily vibrations.
//+------------------------------------------------------------------+
//| GannSwings.mq4 |
//| Copyright © 2005, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net"
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_color1 Yellow
#property indicator_color2 Yellow
#property indicator_color3 Blue
#property indicator_color4 Red
#property indicator_color5 Aqua
#property indicator_color6 HotPink
#define version "XV"
extern int kind=1;// òèï òåíäåíöèè, 1- ìàëàÿ, 2 - ïðîìåæóòî÷íàÿ, 3 - îñíîâíàÿ
extern bool ShowHiLo=false;
extern bool ShowOutSideBars=false;
extern bool MoveLastSwing=false; // åñëè ðàâíî true, òî êîí÷èê õâîñòà áóäåò ñäâèãàòüñÿ áëèæå ê íóëåâîìó áàðó äëÿ äâóõ îäèíàêîâûõ áàðîâ ïî High èëè Low
//---- buffers
double HighSwings[];
double LowSwings[];
double HighsBuffer[];
double LowsBuffer[];
double TrendBuffer[];
double UpCloseOutSideBuffers[];
double DownCloseOutSideBuffers[];
double SwingHigh,SwingLow;
int prevSwing,LastSwing,myBars,lowCounter,highCounter , cnt;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
IndicatorBuffers(7);
SetIndexStyle(0,DRAW_ZIGZAG);
SetIndexBuffer(0,HighSwings);
SetIndexEmptyValue(0,0.0);
SetIndexLabel(0,"HighSwing");
SetIndexStyle(1,DRAW_ZIGZAG);
SetIndexBuffer(1,LowSwings);
SetIndexEmptyValue(1,0.0);
SetIndexLabel(1,"LowSwing");
SetIndexBuffer(2,HighsBuffer);
SetIndexLabel(2,"HighActive");
SetIndexEmptyValue(2,0.0);
SetIndexBuffer(3,LowsBuffer);
SetIndexLabel(3,"LowActive");
SetIndexEmptyValue(3,0.0);
if (ShowHiLo)
{
SetIndexStyle(2,DRAW_ARROW);
SetIndexArrow(2,159);
SetIndexStyle(3,DRAW_ARROW);
SetIndexArrow(3,159);
}
else
{
SetIndexStyle(2,DRAW_NONE);
SetIndexStyle(3,DRAW_NONE);
}
SetIndexBuffer(4,UpCloseOutSideBuffers);
SetIndexStyle(4,DRAW_ARROW);
SetIndexArrow(4,108);
SetIndexLabel(4,"UpClose");
SetIndexEmptyValue(4,0.0);
SetIndexBuffer(5,DownCloseOutSideBuffers);
SetIndexStyle(5,DRAW_ARROW);
SetIndexArrow(5,108);
SetIndexLabel(5,"DownClose");
SetIndexEmptyValue(5,0.0);
SetIndexBuffer(6,TrendBuffer);
for (int i=Bars-1; i>=0; i--)
{
HighSwings[i]=0.0;
LowSwings[i]=0.0;
HighsBuffer[i]=0.0;
LowsBuffer[i]=0.0;
TrendBuffer[i]=0.0;
UpCloseOutSideBuffers[i]=0.0;
DownCloseOutSideBuffers[i]=0.0;
}
SwingHigh=0.0;
SwingLow=0.0;
prevSwing=0;
LastSwing=0.0;
myBars=0;
lowCounter=0;
highCounter=0;
Comment("\n","GannSwings ",version," kind=",kind);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
Comment("\n","\n"," ");
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
void DownTrendOutSide()
{
//----
//1
if (Close[cnt]<=Open[cnt] && lowCounter==1)
{
SwingHigh=High[cnt];
SwingLow=Low[cnt];
HighSwings[cnt]=High[cnt];
LowSwings[cnt]=Low[cnt];
highCounter=0;
lowCounter=0;
LastSwing=cnt;
}
//2
if ( Close[cnt]>Open[cnt] && lowCounter==1)
{
LowSwings[LastSwing]=0.0;
SwingLow=Low[cnt];
SwingHigh=High[cnt];
HighSwings[cnt]=High[cnt];
LowSwings[cnt]=Low[cnt];
highCounter=0;
lowCounter=0;
LastSwing=cnt;
TrendBuffer[cnt]=1.0;
//Print("breakout àïòðåíä ÷åðåç âíåøíèé áàð");
}
//3
if (Close[cnt]>Open[cnt] && highCounter==kind)
{
SwingLow=Low[cnt];
SwingHigh=High[cnt];
LowSwings[cnt]=Low[cnt];
HighSwings[cnt]=High[cnt];
highCounter=0;
lowCounter=0;
LastSwing=cnt;
TrendBuffer[cnt]=1.0;
//Print("breakout äàóíòðåíä ÷åðåç âíåøíèé áàð");
}
//4
if (Close[cnt]<=Open[cnt] && highCounter==kind)
{
SwingLow=Low[cnt];
SwingHigh=High[cnt];
if (Low[cnt]<LowSwings[LastSwing])
{
LowSwings[LastSwing]=0.0;
LowSwings[cnt]=Low[cnt];
}
HighSwings[cnt]=High[cnt];
highCounter=0;
lowCounter=0;
LastSwing=cnt;
//Print("Ðàçâîðîò äàóíòðåíäà ÷åðåç âíåøíèé áàð");
TrendBuffer[cnt]=1.0;
}
//----
return;
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
void UpTrendOutSide()
{
//----
if ( Close[cnt]>=Open[cnt] && highCounter==1)
{
SwingLow=Low[cnt];
SwingHigh=High[cnt];
LowSwings[cnt]=Low[cnt];
HighSwings[cnt]=High[cnt];
highCounter=0;
lowCounter=0;
LastSwing=cnt;
//Print("Ïðîäîëæåíèå àïòðåíä ÷åðåç âíåøíèé áàð");
}
if (Close[cnt]< Open[cnt] && highCounter==1)
{
HighSwings[LastSwing]=0.0;
SwingLow=Low[cnt];
SwingHigh=High[cnt];
LowSwings[cnt]=Low[cnt];
HighSwings[cnt]=High[cnt];
highCounter=0;
lowCounter=0;
LastSwing=cnt;
TrendBuffer[cnt]=-1.0;
//Print("breakout àïòðåíä ÷åðåç âíåøíèé áàð");
}
if (Close[cnt]>= Open[cnt] && lowCounter==kind)
{
SwingLow=Low[cnt];
SwingHigh=High[cnt];
LowSwings[cnt]=Low[cnt];
HighSwings[cnt]=High[cnt];
highCounter=0;
lowCounter=0;
LastSwing=cnt;
TrendBuffer[cnt]=-1.0;
//Print("breakout àïòðåíä ÷åðåç âíåøíèé áàð");
}
// TrendBuffer[cnt+1]==1.0 &&
if (Close[cnt]<Open[cnt] && lowCounter==kind)
{
SwingLow=Low[cnt];
SwingHigh=High[cnt];
if (High[cnt]>HighSwings[LastSwing])
{
HighSwings[LastSwing]=0.0;
HighSwings[cnt]=High[cnt];
}
LowSwings[cnt]=Low[cnt];
highCounter=0;
lowCounter=0;
LastSwing=cnt;
//Print("Ðàçâîðîò àïòðåíäà ÷åðåç âíåøíèé áàð");
TrendBuffer[cnt]=-1.0;
}
//----
return;
}
//+------------------------------------------------------------------+
//| OutSidePart function |
//+------------------------------------------------------------------+
void OutSidePart()
{
//----
if (TrendBuffer[cnt+1]==1.0)
{
UpTrendOutSide();
}//TrendBuffer[cnt+1]==1.0;
else
{// TrendBuffer[cnt+1]==-1.0
DownTrendOutSide();
}//TrendBuffer[cnt+1]==-1.0
//----
return;
}
//+------------------------------------------------------------------+
//| nonOutSidePart() function |
//+------------------------------------------------------------------+
void nonOutSidePart()
{
//----
if (TrendBuffer[cnt+1]==-1.0)
{
if (lowCounter==1)
{
if (LastSwing!=Bars-1) LowSwings[LastSwing]=0.0; // çàòðåì ïðåäûäóùèé ñâèíã
//Print("çàòðåì ïðåäûäóùèé Down ñâèíã");
LastSwing=cnt;
SwingHigh=High[cnt];
SwingLow=Low[cnt];
//TrendBuffer[cnt]=-1.0;
highCounter=0;
lowCounter=0;
LowSwings[cnt]=Low[cnt];
HighsBuffer[cnt]=SwingHigh;
//Print("ïðîäîëæåíèå äàóíòðåíäà");
}
else
{
if (highCounter==kind)
{
//if (LastSwing=!cnt)
LastSwing=cnt;
SwingHigh=High[cnt];
SwingLow=Low[cnt];
TrendBuffer[cnt]=1.0;
highCounter=0;
lowCounter=0;
HighSwings[cnt]=High[cnt];
LowsBuffer[cnt]=SwingLow;
//Print("ðàçâîðîò äàóíòðåíäà");
}
else
{
if (Low[cnt]==SwingLow && MoveLastSwing)
{
LowSwings[LastSwing]=0.0;
LastSwing=cnt;
LowSwings[cnt]=Low[cnt];
// continue;
}
}
}
}// TrendBuffer[cnt+1]==-1.0
else // TrendBuffer[cnt+1]==1.0
{
if (highCounter==1)
{
if (LastSwing!=Bars-1) HighSwings[LastSwing]=0.0; // çàòðåì ïðåäûäóùèé ñâèíã
LastSwing=cnt;
SwingHigh=High[cnt];
SwingLow=Low[cnt];
highCounter=0;
lowCounter=0;
HighSwings[cnt]=High[cnt];
HighsBuffer[cnt]=SwingHigh;
LowsBuffer[cnt]=SwingLow;
//Print("ïðîäîëæåíèå àïòðåíäà");
}
else
{
if (lowCounter==kind)
{
LastSwing=cnt;
SwingHigh=High[cnt];
SwingLow=Low[cnt];
TrendBuffer[cnt]=-1.0;
highCounter=0;
lowCounter=0;
LowSwings[cnt]=Low[cnt];
HighsBuffer[cnt]=SwingHigh;
LowsBuffer[cnt]=SwingLow;
//Print("ðàçâîðîò àïòðåíäà");
}
else
{
if (High[cnt]==SwingHigh && MoveLastSwing)
{
HighSwings[LastSwing]=0.0;
LastSwing=cnt;
HighSwings[cnt]=High[cnt];
}
}
}
} //TrendBuffer[cnt+1]==1.0
//----
return;
}
//+------------------------------------------------------------------+
//| return shift of last swing |
//+------------------------------------------------------------------+
int GetLastSwing()
{
//----
int point=1;
while (HighSwings[point]==0.0 && LowSwings[point]==0.0 && point<Bars) point++;
//----
return(point);
}
//+------------------------------------------------------------------+
//| Check prev swing |
//+------------------------------------------------------------------+
void SetPrevSwing()
{
//----
int LastPoint;
LastPoint=GetLastSwing();
HighSwings[0]=0.0;
SwingHigh=High[LastPoint];
SwingLow=Low[LastPoint];
LastSwing=LastPoint;
//----
return;
}
//+------------------------------------------------------------------+
//| check Out side bar |
//+------------------------------------------------------------------+
bool isOutSideSwingBar(int shift)
{
bool res=false;
//----
res=((High[shift]>SwingHigh)&&(Low[shift]<SwingLow));
if (res && ShowOutSideBars)
{
if (Close[shift]>Open[shift]) UpCloseOutSideBuffers[shift]=(High[shift]+Low[shift])/2.0;
else DownCloseOutSideBuffers[shift]=(High[shift]+Low[shift])/2.0;
}
//----
return(res);
}
//+------------------------------------------------------------------+
//| Check new low |
//+------------------------------------------------------------------+
void SetSwings(int shift)
{
//----
//----
return;
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars=IndicatorCounted();
int limit;
bool nonOutSide;
if (counted_bars==0)
{
limit=Bars-1;
LowsBuffer[limit]=Low[limit];
LowSwings[limit]=Low[limit];
SwingHigh=High[limit];
SwingLow=Low[limit];
LastSwing=limit;
TrendBuffer[limit]=-1.0;
}
if (counted_bars>0) limit=Bars-counted_bars;
if ( (counted_bars<0)|| ((counted_bars>0)&&(Bars-myBars>1)) ) init();
limit--;
//----
for ( cnt=limit;cnt>0;cnt--)
{
//if (cnt==0) SetPrevSwing();
nonOutSide=!isOutSideSwingBar(cnt);
if (High[cnt]>SwingHigh) {highCounter++;SwingHigh=High[cnt];HighsBuffer[cnt]=SwingHigh;}
if (Low[cnt]<SwingLow) {lowCounter++;SwingLow=Low[cnt];LowsBuffer[cnt]=SwingLow;}
TrendBuffer[cnt]=TrendBuffer[cnt+1];// åñëè íå áóäóò èçìåíåíèé - òðåíä ñîõðàíèòñÿ
if (nonOutSide)
{
nonOutSidePart(); // òóò ìû ðàáîòàåì ñ îáû÷íûìè áàðàìè
}// if (nonOutSide)
else // outSideBars
{
OutSidePart();
}// isOutSideSwingBar(cnt)
} // ÊÎÍÅÖ ÖÈÊËÀ
myBars=Bars;
//----
return(0);
}
//+------------------------------------------------------------------+
Comments