Author:
ArrZZx2

This script is designed as a sophisticated technical analysis tool for financial charts. Its primary objective is to filter out "market noise" and identify significant structural trends, price pivots, and potential reversal points by layering multiple layers of mathematical smoothing.

Here is a breakdown of the logic used by the script:

1. Data Smoothing and Foundation

The tool begins by establishing a baseline for price movement. Rather than looking at raw, erratic price changes, it applies a specialized moving average. It can be configured to look at different price types (such as Closing prices, Opening prices, or weighted averages of the High, Low, and Close).

Once this initial average is created, the script applies a secondary "Smoothing" layer. This process compares the recent highs and lows of the first average against its own moving values to create an even more stable line. This ensures that the subsequent signals are based on significant trends rather than temporary spikes.

2. Identification of Significant Peaks and Troughs (Z-Zones)

The core logic revolves around identifying "ZigZags"—these are the actual structural peaks and valleys of a market trend. The script scans the smoothed data to find:

  • Structural Highs: Points where the price significantly turns downward.
  • Structural Lows: Points where the price significantly turns upward.

It includes specific logic to ensure these points are "significant" enough to be counted, preventing the tool from reacting to minor fluctuations.

3. Signal Detection and Trend Analysis

Once the major structural peaks and valleys are mapped out, the script performs a deeper analysis to determine the current "state" of the trend:

  • Short-Term Dynamics: It identifies immediate price reactions relative to the established structural points.
  • Trend Confirmation: By comparing the current price position against previous major highs and lows, it determines if the market is currently in an uptrend or a downtrend.

4. Visual Output and Alerting

The final stage of the logic translates these complex calculations into visual cues on your chart:

  • Trend Arrows: The script places specific icons (arrows) on the chart to indicate potential entry points or trend shifts.
  • Projection Logic: It includes a "projection" feature where, if a certain price condition is met, it can "carry over" or project a signal forward, helping the user see the anticipated direction of the move.
  • Visual Cleanup: While it calculates many values in the background (like hidden averages and intermediate data), it is designed to keep the chart clean by only showing the most relevant trend signals and arrows to the user.

Summary for the User

In short, this tool acts as a trend-following filter. It ignores the small "wiggles" of the market to find the "skeleton" of the price movement. By identifying the major structural turns of the market, it provides visual cues (arrows) to help traders see where a trend might be forming, reversing, or losing momentum.

Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1
10 Views
4 Downloads
0 Favorites
ArrZZx2
//+------------+-----------------------------------------------------+
//| v.22.04.07 |                                         ArrZZx2.mq4 |
//+------------+                                                     |
//|------------|              Bookkeeper, 2007, yuzefovich@gmail.com |
//+------------+-----------------------------------------------------+
#property copyright ""
#property link      "http://www.forexter.land.ru/indicators.htm"
//----
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_color1  MediumBlue
#property indicator_color2  RoyalBlue
#property indicator_color3  Blue
#property indicator_color4  Blue
#property indicator_color5  DarkGreen
#property indicator_color6  Red
#property indicator_color7  DarkGreen
#property indicator_color8  Red
//--------------------------------------------------------------------
extern int    SR     =3;  // =3..4
extern int    SRZZ   =12; // =4..12..20
extern int    MainRZZ=20; // =12..20..54...
extern int    FP     =21;
extern int    SMF    =3;  // =1..5
extern bool   DrawZZ =false;
extern int    PriceConst=0; // 0 - Close
                            // 1 - Open
                            // 2 - High
                            // 3 - Low
                            // 4 - (H+L)/2
                            // 5 - (H+L+C)/3
                            // 6 - (H+L+2*C)/4
//extern string Prefix="ArrZZx2"; 
//--------------------------------------------------------------------
double        Lmt[];
double        LZZ[];
double        SA[];
double        SM[];
double        Up[];
double        Dn[];
double        pUp[];
double        pDn[];
//---------------------------------------------------------------------
int LTF[6]={0,0,0,0,0,0},STF[5]={0,0,0,0,0}; 
int MaxBar, nSBZZ, nLBZZ, SBZZ, LBZZ;
bool First=true;
int prevBars=0;
//---------------------------------------------------------------------
void MainCalculation(int Pos) {
if((Bars-Pos)>(SR+1)) SACalc(Pos); else SA[Pos]=0; 
if((Bars-Pos)>(FP+SR+2)) SMCalc(Pos); else SM[Pos]=0; return; }
//---------------------------------------------------------------------
void SACalc(int Pos) { int sw, i, w, ww, Shift; double sum; 
switch(PriceConst) {
case  0: 
  SA[Pos]=iMA(NULL,0,SR+1,0,MODE_LWMA,PRICE_CLOSE,Pos);
  break;
case  1: 
  SA[Pos]=iMA(NULL,0,SR+1,0,MODE_LWMA,PRICE_OPEN,Pos);
  break;
/*case  2: 
  SA[Pos]=iMA(NULL,0,SR+1,0,MODE_LWMA,PRICE_HIGH,Pos);
  break;
case  3: 
  SA[Pos]=iMA(NULL,0,SR+1,0,MODE_LWMA,PRICE_LOW,Pos);
  break;*/
case  4: 
  SA[Pos]=iMA(NULL,0,SR+1,0,MODE_LWMA,PRICE_MEDIAN,Pos);
  break;
case  5: 
  SA[Pos]=iMA(NULL,0,SR+1,0,MODE_LWMA,PRICE_TYPICAL,Pos);
  break;
case  6: 
  SA[Pos]=iMA(NULL,0,SR+1,0,MODE_LWMA,PRICE_WEIGHTED,Pos);
  break;
default: 
  SA[Pos]=iMA(NULL,0,SR+1,0,MODE_LWMA,PRICE_OPEN,Pos);
  break; }
for(Shift=Pos+SR+2;Shift>Pos;Shift--) { sum=0.0; sw=0; i=0; w=Shift+SR;
ww=Shift-SR; if(ww<Pos) ww=Pos;
while(w>=Shift) {i++; sum=sum+i*SnakePrice(w); sw=sw+i; w--; }
while(w>=ww) { i--; sum=sum+i*SnakePrice(w); sw=sw+i; w--; }
SA[Shift]=sum/sw; } return; }
//----
double SnakePrice(int Shift) {
switch(PriceConst) {
   case  0: return(Close[Shift]);
   case  1: return(Open[Shift]);
   /*case  2: return(High[Shift]);
   case  3: return(Low[Shift]);*/
   case  4: return((High[Shift]+Low[Shift])/2);
   case  5: return((Close[Shift]+High[Shift]+Low[Shift])/3);
   case  6: return((2*Close[Shift]+High[Shift]+Low[Shift])/4);
   default: return(Open[Shift]); } }
//---------------------------------------------------------------------
void SMCalc(int i) { double t, b;
for(int Shift=i+SR+2;Shift>=i;Shift--) {
t=SA[ArrayMaximum(SA,FP,Shift)]; b=SA[ArrayMinimum(SA,FP,Shift)];
SM[Shift]=(2*(2+SMF)*SA[Shift]-(t+b))/2/(1+SMF); } return; }
//---------------------------------------------------------------------
void LZZCalc(int Pos) { 
int i,RBar,LBar,ZZ,NZZ,NZig,NZag; 
i=Pos-1; NZig=0; NZag=0;
while(i<MaxBar && ZZ==0) { i++; LZZ[i]=0; RBar=i-MainRZZ; 
if(RBar<Pos) RBar=Pos; LBar=i+MainRZZ;
if(i==ArrayMinimum(SM,LBar-RBar+1,RBar)) { ZZ=-1; NZig=i; }
if(i==ArrayMaximum(SM,LBar-RBar+1,RBar)) { ZZ=1;NZag=i; } }
if(ZZ==0) return; NZZ=0;
if(i>Pos) { if(SM[i]>SM[Pos]) { if(ZZ==1) {
if(i>=Pos+MainRZZ && NZZ<5) { NZZ++; LTF[NZZ]=i; } NZag=i; 
LZZ[i]=SM[i]; } }
else { if(ZZ==-1) { if(i>=Pos+MainRZZ && NZZ<5) { NZZ++; LTF[NZZ]=i; }
NZig=i; LZZ[i]=SM[i]; } } }
while(i<LBZZ || NZZ<5) {  LZZ[i]=0; RBar=i-MainRZZ; 
if(RBar<Pos) RBar=Pos; LBar=i+MainRZZ;
if(i==ArrayMinimum(SM,LBar-RBar+1,RBar)) {
if(ZZ==-1 && SM[i]<SM[NZig]) { 
if(i>=Pos+MainRZZ && NZZ<5) LTF[NZZ]=i; LZZ[NZig]=0; LZZ[i]=SM[i]; 
NZig=i; }
if(ZZ==1) { if(i>=Pos+MainRZZ && NZZ<5) { NZZ++; LTF[NZZ]=i; } 
LZZ[i]=SM[i]; ZZ=-1; NZig=i; } }
if(i==ArrayMaximum(SM,LBar-RBar+1,RBar)) {
if(ZZ==1 && SM[i]>SM[NZag]) { 
if(i>=Pos+MainRZZ && NZZ<5) LTF[NZZ]=i; LZZ[NZag]=0; LZZ[i]=SM[i]; 
NZag=i; }
if(ZZ==-1) { if(i>=Pos+MainRZZ && NZZ<5) { NZZ++; LTF[NZZ]=i; } 
LZZ[i]=SM[i]; ZZ=1; NZag=i; } } i++; if(i>MaxBar) return; } 
nLBZZ=Bars-LTF[5]; LZZ[Pos]=SM[Pos]; return; }
//----
void SZZCalc(int Pos) { 
int i,RBar,LBar,ZZ,NZZ,NZig,NZag; 
i=Pos-1; NZig=0; NZag=0;
while(i<=LBZZ && ZZ==0) { i++; pDn[i]=0; pUp[i]=0; Dn[i]=0; Up[i]=0; 
Lmt[i]=0; RBar=i-SRZZ; if(RBar<Pos) RBar=Pos; LBar=i+SRZZ;
if(i==ArrayMinimum(SM,LBar-RBar+1,RBar)) { ZZ=-1; NZig=i; }
if(i==ArrayMaximum(SM,LBar-RBar+1,RBar)) { ZZ=1; NZag=i; } }
if(ZZ==0) return; NZZ=0;
if(i>Pos) { if(SM[i]>SM[Pos]) { if(ZZ==1) {
if(i>=Pos+SRZZ && NZZ<4) { NZZ++; STF[NZZ]=i; } NZag=i; 
Dn[i-1]=Open[i-1]; } }
else { if(ZZ==-1) { if(i>=Pos+SRZZ && NZZ<4) { NZZ++; STF[NZZ]=i; }
NZig=i; Up[i-1]=Open[i-1]; } } }
while(i<=LBZZ || NZZ<4) { pDn[i]=0; pUp[i]=0; Dn[i]=0; Up[i]=0; 
Lmt[i]=0; RBar=i-SRZZ; if(RBar<Pos) RBar=Pos; LBar=i+SRZZ;
if(i==ArrayMinimum(SM,LBar-RBar+1,RBar)) {
if(ZZ==-1 && SM[i]<SM[NZig]) { 
if(i>=Pos+SRZZ && NZZ<4) STF[NZZ]=i; Up[NZig-1]=0; Up[i-1]=Open[i-1]; 
NZig=i; } if(ZZ==1) { if(i>=Pos+SRZZ && NZZ<4) { NZZ++; STF[NZZ]=i; } 
Up[i-1]=Open[i-1]; ZZ=-1; NZig=i;  } }
if(i==ArrayMaximum(SM,LBar-RBar+1,RBar)) {
if(ZZ==1 && SM[i]>SM[NZag]) { 
if(i>=Pos+SRZZ && NZZ<4) STF[NZZ]=i; Dn[NZag-1]=0; Dn[i-1]=Open[i-1]; 
NZag=i; } if(ZZ==-1) { if(i>=Pos+SRZZ && NZZ<4) { NZZ++; STF[NZZ]=i; } 
Dn[i-1]=Open[i-1]; ZZ=1; NZag=i; } } i++; if(i>LBZZ) return; } 
nSBZZ=Bars-STF[4]; return; }
//---------------------------------------------------------------------
void ArrCalc() { int i,j,k,n,z=0; double p, b;
i=LBZZ; while(LZZ[i]==0) i--; j=i; p=LZZ[i]; i--; while(LZZ[i]==0) i--; 
if(LZZ[i]>p) z=1; if(LZZ[i]>0 && LZZ[i]<p) z=-1; p=LZZ[j]; i=j-1;  
while(i>0) { if(LZZ[i]>p) { z=-1; p=LZZ[i]; }
if(LZZ[i]>0 && LZZ[i]<p) { z=1;  p=LZZ[i]; }
if(z>0 && Dn[i]>0) { Lmt[i]=Open[i]; Dn[i]=0; }
if(z<0 && Up[i]>0) { Lmt[i]=Open[i]; Up[i]=0; }
if(z>0 && Up[i]>0) { if(i>1) { j=i-1; k=j-SRZZ+1; if(k<0) k=0; 
n=j; while(n>=k && Dn[n]==0) { pUp[n]=Up[i]; pDn[n]=0; n--; } } 
if(i==1) pUp[0]=Up[i]; } 
if(z<0 && Dn[i]>0) { if(i>1) { j=i-1; k=j-SRZZ+1; if(k<0) k=0; 
n=j; while(n>=k && Up[n]==0) { pDn[n]=Dn[i]; pUp[n]=0; n--; } } 
if(i==1) pDn[0]=Dn[i]; } 
i--; } return; }
//---------------------------------------------------------------------
void deinit() { 
return; }
//---------------------------------------------------------------------
int init() { IndicatorBuffers(8);
SetIndexBuffer(0,Lmt);
SetIndexStyle(0,DRAW_ARROW,EMPTY,2); SetIndexArrow(0,251);
SetIndexEmptyValue(0,0.0);
SetIndexBuffer(1,LZZ);
if(DrawZZ) {
SetIndexStyle(1,DRAW_SECTION,EMPTY,2);
SetIndexEmptyValue(1,0.0); }
else SetIndexStyle(1,DRAW_NONE);
SetIndexBuffer(2,SA); SetIndexStyle(2,DRAW_NONE);
SetIndexBuffer(3,SM); SetIndexStyle(3,DRAW_NONE);
SetIndexBuffer(4,Up); SetIndexStyle(4,DRAW_ARROW,EMPTY,1);
SetIndexArrow(4,233); SetIndexEmptyValue(4,0.0);
SetIndexBuffer(5,Dn); SetIndexStyle(5,DRAW_ARROW,EMPTY,1);
SetIndexArrow(5,234); SetIndexEmptyValue(5,0.0);
SetIndexBuffer(6,pUp); SetIndexStyle(6,DRAW_ARROW);
SetIndexArrow(6,217); SetIndexEmptyValue(6,0.0);
SetIndexBuffer(7,pDn); SetIndexStyle(7,DRAW_ARROW);
SetIndexArrow(7,218); SetIndexEmptyValue(7,0.0); return(0); }
//---------------------------------------------------------------------
int start() { int counted_bars=IndicatorCounted(); int limit,i,j,n;
if(counted_bars<0) return(-1); if(counted_bars>0) counted_bars--;
if(First==true) { 
if(SR<2) SR=2; if(Bars<=2*(MainRZZ+FP+SR+2)) return(-1); 
if(SRZZ<=SR) SRZZ=SR+1; MaxBar=Bars-(MainRZZ+FP+SR+2);
LBZZ=MaxBar; SBZZ=LBZZ; prevBars=Bars; First=false; }
limit=Bars-counted_bars; for(i=limit;i>=0;i--) { MainCalculation(i); }
if(prevBars!=Bars) { SBZZ=Bars-nSBZZ; LBZZ=Bars-nLBZZ; prevBars=Bars; } 
SZZCalc(0); LZZCalc(0); ArrCalc(); return(0); }
//---------------------------------------------------------------------

Comments