// downloaded at http://www.forexfactory.com/showthread.php?p=7589261#post7589261
//////////////////////////////////////////////////////////////////////
// !!! YOU MUST COMPILE THIS EA WITH THE BUILD 509 COMPILER, download the metaeditor for build 509 at http://www.forexfactory.com/showthread.php?t=470340 !!!
//////////////////////////////////////////////////////////////////////
#property copyright "? // mod. Marc (fxdaytrader), http://ForexBaron.net"
#property link      "http://ForexBaron.net"
#define iNAME "ZZ_Semafor_Pips"

#property indicator_buffers 6
#property indicator_chart_window

#property indicator_color1 Red
#property indicator_color2 DarkViolet
#property indicator_color3 Green
#property indicator_color4 Red
#property indicator_color5 DarkViolet
#property indicator_color6 Green

#property indicator_width1 4
#property indicator_width2 3
#property indicator_width3 4
#property indicator_width4 1
#property indicator_width5 1
#property indicator_width6 1

//---- input parameters

extern double     Points1        = 3.0; 
extern double     Points2        = 9.0; 
extern double     Points3        = 15.0; 
extern bool       DrawSignals    = false; 
extern int        Code_Sml       = 158;
extern int        Code_Mid       = 159;
extern int        Code_Big       = 178;

//double UpLine[];
//double BotLine[];

double ZZ_Sml[]; 
double ZZ_Mid[];
double ZZ_Big[];
double Sig_Sml[]; 
double Sig_Mid[];
double Sig_Big[];

int SigCode = 171; //167
double point;
double pips2dbl;
//fxdaytrader:
extern string sep3="";
extern string ahi0=" ******* Alert settings:";
extern int  SignalCandle           = 1;
extern bool Sm1Alerts = FALSE;
extern bool MidAlerts = FALSE;
extern bool BigAlerts = TRUE;
extern bool PopupAlerts            = TRUE;
extern bool EmailAlerts            = FALSE;
extern bool PushNotificationAlerts = FALSE;
extern bool SoundAlerts            = FALSE;
extern string SoundFileLong        = "alert.wav";
extern string SoundFileShort       = "alert2.wav";
int lastAlert=3;
//

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init() {
   BrokerDigitAdjust(Symbol());//fxdaytrader
   
   /*
   if(Digits == 3 || Digits == 5)
   point = Point*10;
   else point = Point;
   */
   point=pips2dbl;
   
   SetIndexEmptyValue(0,0.0);
   SetIndexEmptyValue(1,0.0);
   SetIndexEmptyValue(2,0.0);
   SetIndexEmptyValue(3,0.0);
   SetIndexEmptyValue(4,0.0);
   SetIndexEmptyValue(5,0.0);
     
   
   SetIndexBuffer(0,ZZ_Sml);
   SetIndexBuffer(1,ZZ_Mid);//circle
   SetIndexBuffer(2,ZZ_Big);//star
   SetIndexBuffer(3,Sig_Sml);
   SetIndexBuffer(4,Sig_Mid);
   SetIndexBuffer(5,Sig_Big);
   
   SetIndexLabel(0,"ZZ Sm1");
   SetIndexLabel(1,"ZZ Mid");
   SetIndexLabel(2,"ZZ Big");
   SetIndexLabel(3,"Sig Sm1");
   SetIndexLabel(4,"Sig Mid");
   SetIndexLabel(5,"Sig Big");
   
   SetIndexStyle(0,DRAW_ARROW); 
   SetIndexStyle(1,DRAW_ARROW); 
   SetIndexStyle(2,DRAW_ARROW); 
   
   if(DrawSignals)
   {
      SetIndexStyle(3,DRAW_ARROW); 
      SetIndexStyle(4,DRAW_ARROW); 
      SetIndexStyle(5,DRAW_ARROW);
      SetIndexArrow(3, SigCode);
      SetIndexArrow(4, SigCode);
      SetIndexArrow(5, SigCode); 
   }
   else
   {
      SetIndexStyle(3,DRAW_NONE); 
      SetIndexStyle(4,DRAW_NONE); 
      SetIndexStyle(5,DRAW_NONE);
   
   }
   SetIndexArrow(0,Code_Sml);
   SetIndexArrow(1,Code_Mid);
   SetIndexArrow(2,Code_Big); 
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//---- TODO: add your code here
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
      ZZ_Calculate(ZZ_Sml,Sig_Sml,Points1,Sm1Alerts,"Sm1");
      ZZ_Calculate(ZZ_Mid,Sig_Mid,Points2,MidAlerts,"Mid");
      ZZ_Calculate(ZZ_Big,Sig_Big,Points3,BigAlerts,"Big");
   return(0);
}

//==============================================================================
//
//==============================================================================
void ZZ_Calculate(double& zz[], double& sig[], double deviat,bool givealerts,string type)
{

   int i; int LastBar;int nBars; 
   int LastHiBarNum=0;int LastLoBarNum;int initCount;
   double LastHi;double LastLo;
   bool findTrough; bool findPeak;// если findTrough=true, то находимся в состоянии поиска впадины
   
   
      int    counted_bars=IndicatorCounted();
             
         nBars=3000;
   
         if (nBars < Bars-1 )
         {
         LastHi=High[nBars-1];
         LastLo=Low[nBars-1];
         LastHiBarNum = nBars-1;
         LastLoBarNum = nBars-1;
         //UpLine[nBars-1]=LastHi; //Убираем. Искажает самый первый обнаруженный уровень
         //BotLine[nBars-1]=LastLo;
         findPeak=(true);
         initCount=nBars-2;
         }
         else
         {
         LastHi=High[Bars-1];
         LastLo=Low[Bars-1];
         LastHiBarNum = Bars-1;
         LastLoBarNum = Bars-1;
         //UpLine[Bars-1]=LastHi;
         //BotLine[Bars-1]=LastLo;
         findPeak=(true);
         initCount=Bars-2;
         }
   
         i = initCount;
         while(i >= LastBar)
         {
              zz[i]=0;  //Иначе ZZ искажается при переключении timeframe
         //------  Обрабатываем пики 	Ищем пик ---------------------------------------------------------
   
   	      if (High[i]>=LastHi )
   		      {
   		      LastHi=High[i];
   		      LastHiBarNum=i;
   		      }
   		      
   		      
   		      //sig[i]=sig[i+1];
   		
   	      if (High[i] < LastHi) 
   		      {
   		      //if ((Low[i] < LastHi*( (100-Percent)/100 ) ) && findPeak)	//поймали пик
   			   if ((Low[i] < LastHi - point*deviat) && findPeak)
   			      {
   			      LastLo=Low[i];
   			        
   			        //if (ShowZZ==true)
   			        zz[LastHiBarNum]=LastHi;
   			      
   			      LastLoBarNum=i;
   			      sig[i]=LastHi;
   			      findPeak=false;
   			      findTrough=true;
   			      }		
   		      /*
   		      else
   			      {
   			      sig[i]=sig[i+1];
   			      } */
   		      }
   	         
         //------ Обрабатываем впадины -------------------------------------------------------------------
   
   	      if (Low[i]<=LastLo )// 
   		      {
   		      LastLo=Low[i];
   		      LastLoBarNum=i;
   		      }
   		     // sig[i]=sig[i+1];
   		
   	
   	      //if (Low[i] > LastLo )
   		   if (Low[i] > LastLo )
   		      {
   		      //if ((High[i] > LastLo*( (100+Percent)/100) ) 	&& findTrough )//поймали дно
   			   if ((High[i] > LastLo + point*deviat ) 	&& findTrough )//поймали дно
   			   
   			      {
   			      LastHi=High[i];
   			      
   			     // if (ShowZZ==true)
   			      zz[LastLoBarNum] = LastLo;
   			      
   			      LastHiBarNum=i;
   			      sig[i]=LastLo;
   			      findPeak=true;
   			      findTrough=false;
   			      }		
   		        /*
   		        else
   			      {
   			      sig[i]=sig[i+1];
   			      }*/
               }
               
               /*
               if(findPeak == true)
               sig[i] = LastLo;
               else
               sig[i] = 0;
               
               if(findTrough == true)
               sig[i] = LastHi;
               else
               sig[i] = 0;
               */
 
         i--;
         }
///////////////////////
 if (givealerts) {
  if (zz[SignalCandle]==iLow(Symbol(),0,SignalCandle)) { doAlerts("BUY SIGNAL ("+type+")",SoundFileLong); }//long
  if (zz[SignalCandle]==iHigh(Symbol(),0,SignalCandle)) { doAlerts("SELL SIGNAL ("+type+")",SoundFileShort); }//short
 }//if (givealerts) {
///////////////////////
}

//fxdaytrader:
void BrokerDigitAdjust(string symbol) {
 int Multiplier = 1;
 int digits=MarketInfo(symbol,MODE_DIGITS);
 if (digits==3 || digits==5) Multiplier = 10;
 if (digits==6) Multiplier = 100;   
 if (digits==7) Multiplier = 1000;
 pips2dbl = Multiplier*MarketInfo(symbol,MODE_POINT);
}

void doAlerts(string msg,string SoundFile) {
 static int lasttime=0;
 if (iTime(Symbol(),0,0)!=lasttime) {
  lasttime=iTime(Symbol(),0,0);
        msg=iNAME+" Alert on "+Symbol()+", period "+TFtoStr(Period())+": "+msg;//+", bid = "+DoubleToStr(MarketInfo(Symbol(),MODE_BID),Digits)+", servertime: "+TimeToStr(TimeCurrent());
 string emailsubject="MT4 alert on acc. "+AccountNumber()+", "+WindowExpertName()+" - Alert on "+Symbol()+", period "+TFtoStr(Period());
  if (PopupAlerts) Alert(msg);
  if (EmailAlerts) SendMail(emailsubject,msg);
  if (PushNotificationAlerts) SendNotification(msg);
  if (SoundAlerts) PlaySound(SoundFile);
 }
}//void doAlerts(string msg,string SoundFile) {

string TFtoStr(int period) {
 if (period==0) period=Period();
 switch(period) {
  case 1     : return("M1");  break;
  case 5     : return("M5");  break;
  case 15    : return("M15"); break;
  case 30    : return("M30"); break;
  case 60    : return("H1");  break;
  case 240   : return("H4");  break;
  case 1440  : return("D1");  break;
  case 10080 : return("W1");  break;
  case 43200 : return("MN1"); break;
  default    : return(DoubleToStr(period,0));
 }
 return("UNKNOWN");
}//string TFtoStr(int period) {


