Final Draft ArrZZx2_alerts
Download scriptThis script is designed as a sophisticated technical analysis tool for trading platforms. Its primary purpose is to identify market trends, pinpoint specific price fluctuations, and provide visual signals (arrows) to help traders determine potential entry or exit points based on price momentum and structural shifts.
The logic functions through a multi-layered processing system that cleans the "noise" of the market before generating final signals:
1. Data Smoothing and Base Calculations
The script begins by analyzing raw price data (such as Open, Close, High, or Low prices). Instead of looking at every tiny fluctuation, it applies a weighted smoothing process. This creates a stable foundation that represents the general "flow" of the market. By using different weightings, the tool can prioritize certain types of price information to create a smoother, more reliable baseline for the subsequent steps.
2. Signal Filtering (The Moving Average Layer)
Once the base price is established, the script applies an additional layer of calculation to identify peaks and valleys. It looks for significant high and low points within specific windows of time. This step helps the tool distinguish between minor market "wiggles" and actual structural changes in direction. It essentially filters out the distractions of everyday volatility to find where the market is genuinely turning.
3. Structural Trend Identification
The script then performs a deeper analysis of these peaks and valleys to identify the overarching trend. It categorizes price action into structural movements:
- Long-term Trends: Identifying major shifts in market direction.
- Short-term Dynamics: Monitoring smaller fluctuations that occur within the larger trend.
By comparing current price points against previous historical peaks and troughs, the script determines if the market is currently in an uptrend, a downtrend, or a transitional phase.
4. Signal Generation and Alerting
The final logic layer translates all these calculations into actionable visual cues on the chart:
- Directional Arrows: When the script detects a confirmed structural shift, it places "Up" or "Down" arrows to notify the user of a trend change.
- Refined Markers: It creates specific markers to highlight potential price limits or areas where momentum is shifting significantly.
- Automated Notifications: The script includes an integrated alert system. When the logic confirms a trend change, it can trigger a visual pop-up on the screen, play an audio sound, or (optionally) send an email notification to ensure the trader sees the signal immediately.
Summary of User Experience
For the end user, this means you don't have to manually interpret dozens of different price movements. The script performs the heavy lifting by smoothing out the market noise, identifying the significant structural "turning points," and then placing clear arrows on your chart to tell you when the trend has officially shifted.
//+------------+-----------------------------------------------------+
//| 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 White
#property indicator_width1 1
#property indicator_color2 Lime
#property indicator_color3 Blue
#property indicator_color4 Blue
#property indicator_color5 Aqua
#property indicator_width5 1
#property indicator_color6 Violet
#property indicator_width6 1
#property indicator_color7 Aqua
#property indicator_width7 1
#property indicator_color8 Violet
#property indicator_width8 1
//--------------------------------------------------------------------
extern int SR = 3; // =3..4
extern int SRZZ = 5; // =4..12..20..12
extern int MainRZZ = 12;//20; // =12..20..54..20
extern int FP = 21;
extern int SMF = 3; // =1..5
extern bool DrawZZ = false;
extern string exaprice = "Price modes";
extern string exprice = "0=close,1=open,2=high,3=low";
extern string exprice2 = "4=(h+l)/2,5=(h+l+c)/3,6=(H+L+2*C)/4";
extern int PriceConst = 0;
extern bool alertsOn = true;
extern bool alertsOnCurrent = true;
extern bool alertsMessage = true;
extern bool alertsSound = true;
extern bool alertsEmail = false;
//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; }
int init()
{
IndicatorBuffers(8);
SetIndexBuffer(0,Lmt);
SetIndexStyle(0,DRAW_ARROW,EMPTY,2);
SetIndexArrow(0,110);
SetIndexEmptyValue(0,0.0);
SetIndexBuffer(1,LZZ);
if(DrawZZ)
{
SetIndexStyle(1,DRAW_SECTION,EMPTY,4);
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);//Green up arrow
SetIndexArrow(4,110);
SetIndexEmptyValue(4,0.0);
SetIndexLabel(4,"trend UP");
SetIndexBuffer(5,Dn);
SetIndexStyle(5,DRAW_ARROW,EMPTY,1);//Red down arrow
SetIndexArrow(5,110);
SetIndexEmptyValue(5,0.0);
SetIndexLabel(5,"trend DOWN");
SetIndexBuffer(6,pUp);
SetIndexStyle(6,DRAW_ARROW,EMPTY,1);//Green up markers
SetIndexArrow(6,110);
SetIndexEmptyValue(6,0.0);
SetIndexBuffer(7,pDn);
SetIndexStyle(7,DRAW_ARROW,EMPTY,1);//Red down markers
SetIndexArrow(7,110);
SetIndexEmptyValue(7,0.0);
return(0);
}
//---------------------------------------------------------------------
void deinit()
{
return;
}
//---------------------------------------------------------------------
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();
//---------------------------------------------------------------------
if (alertsOn)
{
if (alertsOnCurrent)
int whichBar = 0;
else whichBar = 1;
if (Up[whichBar] > 0) doAlert(" trend changeed to UP");
if (Dn[whichBar] > 0) doAlert(" trend changeed ro DOWN");
}
return(0);
}
//+------------------------------------------------------------------+
//
//
//
//
//
void doAlert(string doWhat)
{
static string previousAlert="nothing";
static datetime previousTime;
string message;
if (previousAlert != doWhat || previousTime != Time[0]) {
previousAlert = doWhat;
previousTime = Time[0];
//
//
//
//
//
message = StringConcatenate(Symbol()," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," ArrZZx2 ",doWhat);
if (alertsMessage) Alert(message);
if (alertsEmail) SendMail(StringConcatenate(Symbol()," ArrZZx2"),message);
if (alertsSound) PlaySound("alert2.wav");
}
}
Comments