//+------------------------------------------------------------------+
//|!      NIH98 !TMA Centered Multi Bands Indi.mq4
//+------------------------------------------------------------------+
#property copyright "NIH98"
#property link      ""

#property indicator_chart_window
#property indicator_buffers    3      //9
#property indicator_color1     clrYellow            // Main TMA Line
#property indicator_color2     clrYellow        // TMA Band 1 Upper Line
#property indicator_color3     clrYellow      // TMA Band 1 Lower Line
#property indicator_style1     STYLE_DOT
#property indicator_style2     STYLE_SOLID
#property indicator_style3     STYLE_SOLID

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
extern string                 TimeFrame            =  "W1";     // Time Frame
extern int                    HalfLength           =  1;            // Half Length
extern ENUM_MA_METHOD         MA_Method                 =  MODE_LWMA;     // MA Method
extern int                    MA_Period                =  1;             // MA Period
extern int                    ATRPeriod            =  140;           // ATR Period
extern ENUM_APPLIED_PRICE     Price                =  PRICE_MEDIAN; // Price Type
extern int                    LinesShift           =  0;             // Lines Shift

extern double                 ATRMultiplier       =  0.31;         // 1st Band

extern bool                   Interpolate          =  false;          // Interpolation

extern bool                   alertsOn             =  false;         // Alert On ?
extern bool                   alertsOnCurrent      =  false;         // Alert on current bar ?
extern bool                   alertsOnHighLow      =  false;         // Alert on High/Low ?
extern bool                   alertsMessage        =  false;         // Alert Send Message ?
extern bool                   alertsNotification   =  false;         // Alert Send Notification ?
extern bool                   alertsEmail          =  false;         // Alert Send E-Mail
extern bool                   alertsSound          =  false;         // ALert Sound ?
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double buffer1[]; // Centered TMA Line

double buffer2[]; // Band 1 upper
double buffer3[]; // Band 1 lower

double trend[];   // Calculation buffer for trend
double slope[];   // calculation buffer for slope

string indicatorFileName;
bool   calculateValue;
bool   returnBars;
int    timeFrame;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int   init()
      {
      IndicatorBuffers(5);
      HalfLength=MathMax(HalfLength,1);
      //Main TMA Line
      SetIndexBuffer       (0,buffer1);
      SetIndexShift        (0,LinesShift);
      SetIndexEmptyValue   (0,EMPTY_VALUE);
      SetIndexDrawBegin    (0,HalfLength);
      SetIndexLabel        (0,"TMA Center Line");
      
      //Bands
      SetIndexBuffer       (1,buffer2); 
      SetIndexStyle        (1,DRAW_LINE);
      SetIndexShift        (1,LinesShift); 
      SetIndexEmptyValue   (1,EMPTY_VALUE); 
      SetIndexDrawBegin    (1,HalfLength);
      SetIndexLabel        (1,"TMA UppBand");
      
      SetIndexBuffer       (2,buffer3);
      SetIndexStyle        (2,DRAW_LINE);
      SetIndexShift        (2,LinesShift);
      SetIndexEmptyValue   (2,EMPTY_VALUE);
      SetIndexDrawBegin    (2,HalfLength);
      SetIndexLabel        (2,"TMA LowBand");
      
      //calculation buffers
      SetIndexBuffer       (3,trend);
      SetIndexBuffer       (4,slope); 
      SetIndexEmptyValue(4,EMPTY_VALUE);
   
      
      
   
      indicatorFileName = WindowExpertName();
      returnBars        = TimeFrame=="returnBars";     if (returnBars)     return(0);
      calculateValue    = TimeFrame=="calculateValue"; if (calculateValue) return(0);
      timeFrame         = stringToTimeFrame(TimeFrame);
      
      
      IndicatorShortName("TMA Centered Bands  "+timeFrameToString(timeFrame)+"  ["+(int)HalfLength+"]");
      return(0);
      }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int   deinit() 
      { return(0); }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int   start()
      {
      int counted_bars=IndicatorCounted();
      int i,j,k,n,limit;
   
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
              limit=MathMin(Bars-1,Bars-counted_bars+HalfLength);
               if (returnBars)  { buffer1[0] = limit+1; return(0); }
   
      if (calculateValue || timeFrame==Period())
         {
         double range = 0.0;
      
         for   (i=limit; i>=0; i--)
               {
               double sum  = (HalfLength+1)*iMA(NULL,0,MA_Period,0,MA_Method,Price,i);
               double sumw = (HalfLength+1);
               
               for   (j=1, k=HalfLength; j<=HalfLength; j++, k--)
                     {
                        sum  += k*iMA(NULL,0,MA_Period,0,MA_Method,Price,i+j);
                        sumw += k;
            
                        if (j<=i)
                        {
                           sum  += k*iMA(NULL,0,MA_Period,0,MA_Method,Price,i-j);
                           sumw += k;
                        }
                     }
      
               range = iATR ( NULL, 0, ATRPeriod, i + 10 ) * ATRMultiplier;
               buffer1[i] = sum/sumw;
               buffer2[i] = buffer1[i]+range;
               buffer3[i] = buffer1[i]-range;
               
               slope  [i] = slope[i+1];
         
               if ( buffer1[i] != 0.0 )  
                  { 
                  slope[i] = ( ( buffer1[i] - buffer1[i+1] )  / buffer1[i] ) * 100000;
                  }
            
            
          
               trend[i] = 0;                     
               if    (alertsOnHighLow)       
                     {
                     if ( High[i] > buffer2[i] ) trend[i] =  1;
                     if ( Low [i] < buffer3[i] ) trend[i] = -1;
                     }
               else
                     {
                     if ( Close[i] > buffer2[i] ) trend[i] =  1;
                     if ( Close[i] < buffer3[i] ) trend[i] = -1;
                     }
               }
               if (!calculateValue) manageAlerts();
               return(0);            
         }

      limit = MathMax(limit,MathMin( Bars-1, iCustom ( NULL, timeFrame, indicatorFileName, "returnBars", HalfLength,MA_Method,MA_Period,ATRPeriod,Price,LinesShift,ATRMultiplier,Interpolate, alertsOn, alertsOnCurrent, alertsOnHighLow, alertsMessage, alertsNotification, alertsEmail, alertsSound, 0, 0 ) * timeFrame / Period() ) );
   
      for   (i=limit; i>=0; i--)
            {
            int y = iBarShift(NULL,timeFrame,Time[i]);
            //center line
            buffer1[i] = iCustom ( NULL, timeFrame, indicatorFileName, "calculateTma", HalfLength,MA_Method,MA_Period,ATRPeriod,Price, LinesShift,ATRMultiplier,Interpolate, alertsOn, alertsOnCurrent, alertsOnHighLow, alertsMessage, alertsNotification, alertsEmail, alertsSound, 0, y );
            //level 1 band
            buffer2[i] = iCustom ( NULL, timeFrame, indicatorFileName, "calculateTma", HalfLength,MA_Method,MA_Period,ATRPeriod,Price, LinesShift,ATRMultiplier,Interpolate, alertsOn, alertsOnCurrent, alertsOnHighLow, alertsMessage, alertsNotification, alertsEmail, alertsSound, 1, y );
            buffer3[i] = iCustom ( NULL, timeFrame, indicatorFileName, "calculateTma", HalfLength,MA_Method,MA_Period,ATRPeriod,Price, LinesShift,ATRMultiplier,Interpolate, alertsOn, alertsOnCurrent, alertsOnHighLow, alertsMessage, alertsNotification, alertsEmail, alertsSound, 2, y );
            
            trend[i]   = iCustom ( NULL, timeFrame, indicatorFileName, "calculateTma", HalfLength,MA_Method,MA_Period,ATRPeriod,Price, LinesShift,ATRMultiplier,Interpolate, alertsOn, alertsOnCurrent, alertsOnHighLow, alertsMessage, alertsNotification, alertsEmail, alertsSound, 3, y );
            //
       
            if (timeFrame <= Period() || y==iBarShift(NULL,timeFrame,Time[i-1])) continue;
            if (!Interpolate) continue;
            //

            datetime time = iTime(NULL,timeFrame,y);
         
            for   (n = 1; i+n < Bars && Time[i+n] >= time; n++) continue;	
         
            for   (k = 1; k < n; k++)
                  {
                  //center line
                  buffer1[i+k] = buffer1[i]  +(buffer1[i+n]-buffer1[i])*k/n;
                  
                  //level 1 band
                  buffer2[i+k] = buffer2[i]  +(buffer2[i+n]-buffer2[i])*k/n;
                  buffer3[i+k] = buffer3[i]  +(buffer3[i+n]-buffer3[i])*k/n;
                  
                  
                  }               
            }
      //
      
      manageAlerts();
      return(0);
      }
//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
void  manageAlerts()
      {
      int whichBar;
      if (alertsOn)
         {
         if (alertsOnCurrent)
                  whichBar = 0;
         else     whichBar = 1; whichBar = iBarShift(NULL,0,iTime(NULL,timeFrame,whichBar));
         if (trend[whichBar] != trend[whichBar+1])
            {
            if (trend[whichBar] == 1) doAlert(whichBar,"Above Upper");
            if (trend[whichBar] ==-1) doAlert(whichBar,"Below Lower");
            }         
         }
      }

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 =  StringConcatenate(Symbol(),"  TMA Centered Bands  "+timeFrameToString(timeFrame)+"  ",doWhat," Band   ",TimeToStr(TimeCurrent(),TIME_SECONDS));
         if (alertsMessage)      Alert(message);
         if (alertsNotification) SendNotification(message);
         if (alertsEmail)        SendMail(StringConcatenate(Symbol(),"TMA bands "),message);
         if (alertsSound)        PlaySound("alert2.wav");
         }
      }
//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
string   sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int      iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

int      stringToTimeFrame(string tfs)
         {
         tfs = StringUpperCase(tfs);
         for   (int i=ArraySize(iTfTable)-1; i>=0; i--)
               if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
               return(Period());
         }

string   timeFrameToString(int tf)
         {
         for   (int i=ArraySize(iTfTable)-1; i>=0; i--) 
               if (tf==iTfTable[i]) return(sTfTable[i]);
               return("");
         }

string   StringUpperCase(string str)
         {
         string   s = str;

         for   (int length=StringLen(str)-1; length>=0; length--)
               {
               int ichar = StringGetChar(s, length);
               if       ((ichar > 96 && ichar < 123) || (ichar > 223 && ichar < 256))
                        s = StringSetChar(s, length, ichar - 32);
               else if  (ichar > -33 && ichar < 0)
                        s = StringSetChar(s, length, ichar + 224);
               }
         return(s);
         }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
         