//+------------------------------------------------------------------+
//|                                                 Mano Rounder.mq4 |
//|                                                           mladen |
//+------------------------------------------------------------------+

#property copyright "mladen"
#property link      ""

#property indicator_chart_window

extern int   OnChartOrder             = 0;
extern int   StepPips                 = 100;
extern int   SubLevels                = 1;
extern bool  showZones                = true;
extern bool  showLines                = true;
extern bool  showPrices               = true;
extern int   pricesShift              = -40;
extern color zoneColor                = C'233,233,233';
extern color LevelColor               = clrDimGray;
extern int   LevelLineWidth           = 1;
extern ENUM_LINE_STYLE LevelLineStyle = STYLE_SOLID;
extern color SubLevelColor            = clrDimGray;
extern int   SubLevelLineWidth        = 1;
extern int   SubLevelLineStyle        = clrDimGray;
extern color pricesColor              = clrDimGray;
input int    textSize                 = 7; // regular text size
input int    rtextSize                = 7; // rounded text size

//
//
//
//
//

extern int  alertTolerance  = 0;
extern bool alertsOn        = true;
extern bool alertsOnCurrent = true;
extern bool alertsMessage   = true;
extern bool alertsSound     = false;
extern bool alertsEmail     = false;
extern bool alertsNotify    = true;
//
//
//
//
//

int Step;
int totalLevels = 0;
int totalPrices = 0;
double Prices[];
double SubLevelStep;
string ShortName;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   ShortName = "ManoRounder"+OnChartOrder+"lines";
   return(0);
}

int deinit()
{
   ObjectsDeleteAll(0,"ManoRounder"+OnChartOrder+"lines");
   return(0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int start()
{
   int      l,counted_bars=IndicatorCounted();
   datetime last;
   datetime first;
   double   price;
   
   
   if (totalLevels>0)
      {
         first = ObjectGet("ManoRounder1",OBJPROP_TIME1);
         last  = ObjectGet("ManoRounder1",OBJPROP_TIME2);
      }
      if (_Digits==3 || _Digits==5)
            Step = StepPips*10;
      else  Step = StepPips;
      if (SubLevels>0)  SubLevelStep = Step/(SubLevels+1);
      
   //
   //
   //
   //
   //
         
   if (first != Time[Bars] || last != Time[0])
      {
         double lowPrice  = Low[ iLowest (NULL,0,MODE_LOW ,0,0)];
         double highPrice = High[iHighest(NULL,0,MODE_HIGH,0,0)];
         double low;
         double high;
         double current;
         
         //
         //
         //
         //
         //
         
            low     = MathFloor(lowPrice/(Step*_Point))*Step*_Point;
            high    = MathCeil(highPrice/(Step*_Point))*Step*_Point;
            current = low;
            
         // 
         //       
         //
         //
         //
         
         string name;
         while (totalLevels>0)
         {
            ObjectDelete(StringConcatenate(ShortName,totalLevels)); totalLevels--;
         }

         //
         //
         //
         //
         //
         
         
         while(current<=high)
         {
            if (showZones)
            {
               totalLevels++;  name = StringConcatenate(ShortName,totalLevels);
                  ObjectCreate(name,OBJ_RECTANGLE,0,Time[Bars-1],current,Time[0],current+(Step*_Point));
                     ObjectSet(name,OBJPROP_COLOR,zoneColor);
                     ObjectSet(name,OBJPROP_BACK,true);
            }                     
                  
            //
            //
            //
            //
            //
                              
            if (showLines)
            {
               totalLevels++;  name = StringConcatenate(ShortName,totalLevels);
               price = setPrice(current);
                  ObjectCreate(name,OBJ_TREND,0,Time[Bars-1],price,Time[0],price);
                     ObjectSet(name,OBJPROP_COLOR,LevelColor);
                     ObjectSet(name,OBJPROP_RAY,false);
                     ObjectSet(name,OBJPROP_BACK,true);
                     ObjectSet(name,OBJPROP_WIDTH,LevelLineWidth);
                     ObjectSet(name,OBJPROP_STYLE,LevelLineStyle);
               totalLevels++;  name = StringConcatenate(ShortName,totalLevels);
               price = setPrice(current+(Step*Point));
                  ObjectCreate(name,OBJ_TREND,0,Time[Bars-1],price,Time[0],price);
                     ObjectSet(name,OBJPROP_COLOR,LevelColor);
                     ObjectSet(name,OBJPROP_RAY,false);
                     ObjectSet(name,OBJPROP_BACK,true);
                     ObjectSet(name,OBJPROP_WIDTH,LevelLineWidth);
                     ObjectSet(name,OBJPROP_STYLE,LevelLineStyle);

               //
               //
               //
               //
               //
               
               if (SubLevelStep != 0)                     
               {
                  for (l=1; l<=SubLevels; l++)
                  {
                     totalLevels++;  name = StringConcatenate(ShortName,totalLevels);
                     price = setPrice(current+(SubLevelStep*l*_Point));
                     ObjectCreate(name,OBJ_TREND,0,Time[Bars-1],price,Time[0],price);
                        ObjectSet(name,OBJPROP_COLOR,SubLevelColor);
                        ObjectSet(name,OBJPROP_RAY,false);
                        ObjectSet(name,OBJPROP_BACK,true);
                        ObjectSet(name,OBJPROP_WIDTH,SubLevelLineWidth);
                        ObjectSet(name,OBJPROP_STYLE,SubLevelLineStyle);
                  }
                  for (l=1; l<=SubLevels; l++)
                  {
                     totalLevels++;  name = StringConcatenate(ShortName,totalLevels);
                     price = setPrice(current+((SubLevelStep*l+Step)*_Point));
                     ObjectCreate(name,OBJ_TREND,0,Time[Bars-1],price,Time[0],price);
                        ObjectSet(name,OBJPROP_COLOR,SubLevelColor);
                        ObjectSet(name,OBJPROP_RAY,false);
                        ObjectSet(name,OBJPROP_BACK,true);
                        ObjectSet(name,OBJPROP_WIDTH,SubLevelLineWidth);
                        ObjectSet(name,OBJPROP_STYLE,SubLevelLineStyle);
                  }                        
               }
            }

            //
            //
            //
            //
            //
            
            if (showPrices && (showLines || showZones))
            {
               totalLevels++;  name = StringConcatenate(ShortName,totalLevels);
                  ObjectCreate(name,OBJ_TEXT,0,barTime(-pricesShift),current);
                     ObjectSet(name,OBJPROP_COLOR,pricesColor);
                     ObjectSet(name,OBJPROP_BACK,true);
                     ObjectSetText(name,DoubleToStr(current,_Digits),textSize,"Arial",pricesColor);
               totalLevels++;  name = StringConcatenate(ShortName,totalLevels);
                  ObjectCreate(name,OBJ_TEXT,0,barTime(-pricesShift),current+(Step*_Point));
                     ObjectSet(name,OBJPROP_COLOR,pricesColor);
                     ObjectSet(name,OBJPROP_BACK,true);
                     ObjectSetText(name,DoubleToStr(current+(Step*_Point),_Digits),rtextSize,"Arial",pricesColor);

               //
               //
               //
               //
               //
               
               if (SubLevelStep != 0)                     
               {
                  for (l=1; l<=SubLevels; l++)
                  {
                     totalLevels++;  name = StringConcatenate(ShortName,totalLevels);
                        ObjectCreate(name,OBJ_TEXT,0,barTime(-pricesShift),current+(SubLevelStep*l*_Point));
                           ObjectSet(name,OBJPROP_COLOR,pricesColor);
                           ObjectSet(name,OBJPROP_BACK,true);
                           ObjectSetText(name,DoubleToStr(current+(SubLevelStep*l*_Point),_Digits),7,"Arial",pricesColor);
                  }                           
                  for (l=1; l<=SubLevels; l++)
                  {
                     totalLevels++;  name = StringConcatenate(ShortName,totalLevels);
                        ObjectCreate(name,OBJ_TEXT,0,barTime(-pricesShift),current+((SubLevelStep*l+Step)*_Point));
                           ObjectSet(name,OBJPROP_COLOR,pricesColor);
                           ObjectSet(name,OBJPROP_BACK,true);
                           ObjectSetText(name,DoubleToStr(current+((SubLevelStep*l+Step)*_Point),_Digits),7,"Arial",pricesColor);
                  }                           
               }
            }
            current += (Step*2*Point);
         }
      }

   //
   //
   //
   //
   //

   if (alertsOn)
   {
      if (alertsOnCurrent)
            l = 0;
      else  l = 1;            
      low  = NormalizeDouble(Low[l] ,_Digits);
      high = NormalizeDouble(High[l],_Digits);
      
      //
      //
      //
      //
      //
      
      for (l=0; l<totalPrices; l++)
      {
         if (MathAbs(NormalizeDouble((Prices[l]-low)/_Point,0)) <= alertTolerance) { doAlert("Low touched "+DoubleToStr(Prices[l],_Digits)+" line"); break; }
         if (MathAbs(NormalizeDouble((Prices[l]-high)/_Point,0)) <= alertTolerance) { doAlert("High touched "+DoubleToStr(Prices[l],_Digits)+" line"); break; }
      }
   }
   return(0);
}

//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
//
//
//
//
//

int barTime(int a)
{
   if(a<0)
         return(Time[0]+Period()*60*MathAbs(a));
   else  return(Time[a]);   
}
double setPrice(double price)
{
   totalPrices++; if (ArraySize(Prices) < totalPrices) ArrayResize(Prices,totalPrices);
   
   //
   //
   //
   //
   //
   
   double normalizedPrice = NormalizeDouble(price,_Digits);
         Prices[totalPrices-1] = normalizedPrice;
   return(normalizedPrice);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

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 = timeFrameToString(_Period)+" "+_Symbol+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" Mano Rounder "+doWhat;
          if (alertsMessage) Alert(message);
          if (alertsNotify)  SendNotification(message);
          if (alertsEmail)   SendMail(_Symbol+" Mano Rounder  ",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};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}
