#property indicator_separate_window
#property indicator_buffers    3
#property indicator_color1     clrLimeGreen
#property indicator_color2     clrOrange
#property indicator_color3     clrGray
#property indicator_width1     2
#property indicator_width2     2
#property indicator_width3     2
#property indicator_levelcolor clrMediumOrchid
#property strict

//
//
//
//
//

extern ENUM_TIMEFRAMES     TimeFrame       = PERIOD_CURRENT;   // Time frame
extern int                 MaPeriod        = 14;               // Ma period
extern ENUM_MA_METHOD      MaMethod        = MODE_SMA;         // Ma method
extern ENUM_APPLIED_PRICE  MaPrice         = PRICE_CLOSE;      // Ma price to use
extern ENUM_APPLIED_PRICE  Price           = PRICE_CLOSE;      // Price to use
extern double              levelUp         = 5.00;             // Upper level
extern double              levelDn         = -5.00;            // Lower level
extern bool                alertsOn        = true;             // Turn alerts on?
extern bool                alertsOnCurrent = false;            // Alerts on current (still opened) bar?
extern bool                alertsMessage   = true;             // Alerts showing a pop-up message?
extern bool                alertsSound     = false;            // Alerts playing sound?
extern bool                alertsEmail     = false;            // Alerts sending email?
extern bool                alertsNotify    = false;            // Alerts send notification?
extern string              soundFile       = "alert2.wav";     // Alerts Sound File to use
input bool                 Interpolate     = true;             // Interpolate in mtf mode


double up[],dn[],diff[],trend[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,MaPeriod,MaMethod,MaPrice,Price,levelUp,levelDn,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,alertsNotify,soundFile,_buff,_ind)

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorBuffers(5);
   SetIndexBuffer(0,up); SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,dn); SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,diff);
   SetIndexBuffer(3,trend);
   SetIndexBuffer(4,count);
   SetLevelValue(0,levelUp);
   SetLevelValue(1,levelDn);
   
   indicatorFileName = WindowExpertName();
   TimeFrame         = fmax(TimeFrame,_Period);
   
   IndicatorSetString(INDICATOR_SHORTNAME,timeFrameToString(TimeFrame)+" Ma distance ("+(string)MaPeriod+")");
return(0);
}
int deinit() { return(0); }

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = MathMin(Bars-counted_bars,Bars-1); count[0] = limit;
         double pipMultiplier = MathPow(10,MathMod(Digits,2));
         
         //
         //
         //
         
         if (TimeFrame != Period())
         {
            limit = (int)MathMax(limit,MathMin(Bars-1,_mtfCall(9,0)*TimeFrame/_Period));
            for(int i=limit; i>=0 && !_StopFlag; i--)
            {
               int y = iBarShift(NULL,TimeFrame,Time[i]);
                  up[i]   = _mtfCall(0,y);
                  dn[i]   = _mtfCall(1,y);
                  diff[i] = _mtfCall(2,y);
              
                  //
                  //
                  //
                     
                  if (!Interpolate || (i>0 && y==iBarShift(NULL,TimeFrame,Time[i-1]))) continue;
                    #define _interpolate(buff) buff[i+k] = buff[i]+(buff[i+n]-buff[i])*k/n
                    int n,k; datetime btime = iTime(NULL,TimeFrame,y);
                       for(n = 1; (i+n)<Bars && Time[i+n] >= btime; n++) continue;	
                       for(k = 1; k<n && (i+n)<Bars && (i+k)<Bars; k++) 
                       {
                          _interpolate(diff); 
                          up[i+k] = (up[i]!= EMPTY_VALUE) ? diff[i+k] : EMPTY_VALUE;
                          dn[i+k] = (dn[i]!= EMPTY_VALUE) ? diff[i+k] : EMPTY_VALUE;
                       }                 
         }
   return(0);
   }  
   

   //
   //
   //
   //
   //
   //

   for(int i=limit; i >= 0; i--)
   {
      diff[i] = (iMA(NULL,0,1,0,MODE_SMA,Price,i)-iMA(NULL,0,MaPeriod,0,MaMethod,MaPrice,i))/(pipMultiplier*_Point);
      if (diff[i]>0) 
            { up[i] = diff[i]; dn[i] = EMPTY_VALUE; }
      else  { dn[i] = diff[i]; up[i] = EMPTY_VALUE; }
      trend[i] = (diff[i]>levelUp) ? 1 : (diff[i]<levelDn) ? -1 :  0;
   }
   
   //
   //
   //
   //
   //
   
   if (alertsOn)
   {
      int whichBar = 1; if (alertsOnCurrent) whichBar = 0; 
      if (trend[whichBar]!=trend[whichBar+1])
      {
         if (trend[whichBar] ==  1) doAlert(whichBar," crossing upper level");
         if (trend[whichBar] == -1) doAlert(whichBar," crossing lower level");  
      }
   }               
return(0);
}

//
//
//
//
//

void doAlert(int forBar, string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
      if (previousAlert != doWhat || previousTime != Time[forBar]) {
          previousAlert  = doWhat;
          previousTime   = Time[forBar];

          //
          //
          //
          //
          //

          message = timeFrameToString(_Period)+" "+_Symbol+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" Ma distance "+doWhat;
             if (alertsMessage) Alert(message);
             if (alertsNotify)  SendNotification(message);
             if (alertsEmail)   SendMail(_Symbol+" Ma distance ",message);
             if (alertsSound)   PlaySound(soundFile);
      }
}

//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}




