//+------------------------------------------------------------------+
//|                                                RN_Trace_v1_0.mq4 |
//+------------------------------------------------------------------+
#property copyright "tradelover"
#property link      "forum.vamist.ro"
#property indicator_chart_window

extern int PipRange           = 3000;  //cit de departe de pretul curent se duce,
                                       //in pipsi INTREGI, deci daca ai cont cu 
                                       //pipeti nu trebuie sa adaugi zero, dar va
                                       //trebui setat parametrul de mai jos la "true"!!
                                       
                                       //###ENGLISH: how far the current price goes, the whole pips, so if you use the pipette should not add zero, but will be set following parameter to "true" !!
                                       
                                       
extern bool EnablePrimarySplit_1000 = true;
extern bool EnableSecondarySplit_100  = true; //Second split group, will split a second level of 100

                                       
extern bool PipettesPair      = true; //se pune true la perechile cu 5 (jpy=3) zecimale
                                       //am ales solutia asta pt ca la unii brokeri
                                       //doar unele perechi mai tranzactionate (EURUSD)
                                       //vor avea 5 zecimale, iar altele vor avea 4, 
                                       //ori unii brokeri ofera gold cu o zecimala, 
                                       //(silver cu doua) altii ofera gold cu doua 
                                       //zecimale (silver cu 3), dar pipsi intregi pe
                                       //perechile valutare, etc. Deci daca il pui pe o
                                       //pereche sau actiune cotata in pipeti, sau pe 
                                       //gold cu doua zecimale (ori silver cu 3), atunci
                                       //acest parametru va trebui setat la true.
                                       
                                       //###ENGLISH: put true in pairs 5 (JPY = 3) decimal places that I chose this solution for some brokers only some most traded pairs (EURUSD) will have five decimal places and others will have 4 or some brokers offer gold with a decimal, (silver two) others provide gold with two decimal places (silver 3), but the whole pips currency pairs, etc. So if you put on a pair or action listed in the pipette, or two decimal gold (or silver 3), then this parameter will be set to true.
                                       
extern int BinaryDecimalSplit = 0;     //split mode: 0=binary split, 1=decimal split
extern int LevelsOfSplit_Primary   = 3;     //intre 1 si 3-6 nivele, depinde de tipul
                                       //contului (pipsi/pipeti) si de split mode
                                       //###ENGLISH: between 1 and 3.6 levels, depending on the account type (pips / pipette) and split mode
extern int LevelsOfSplit_Secondary  = 3;     //intre 1 si 3-6 nivele, depinde de tipul

extern string Legend = "Parametrii liniilor, maxim 6 nivele.";//###ENGLISH Parameters lines, maximum of 6 levels.

extern int Width_1   = 3;    //grosimea liniei pe nivelul 1 (superior), intre 1 si 5  ###ENGLISH. line width on level 1 (top), between 1 and 5
extern int Style_1   = 0;    //stilul liniei, de la 0 la 4, valid doar daca width=1
                             //(vezi help, drawing styles)
extern color Color_1 = Red;  //culoarea liniei, set it as you wish

extern int Width_2   = 2;    //liniile de pe nivelul 2, idem
extern int Style_2   = 0; 
extern color Color_2 = OrangeRed;

extern int Width_3   = 1;    //liniile de pe nivelul 3, idem
extern int Style_3   = 0; 
extern color Color_3 = Orange;

extern int Width_4   = 1;    //liniile de pe nivelul 4, idem
extern int Style_4   = 1; 
extern color Color_4 = Gold;

extern int Width_5   = 1;    //liniile de pe nivelul 5, idem
extern int Style_5   = 3; 
extern color Color_5 = Yellow;
 
extern int Width_6   = 1;    //liniile de pe nivelul 6, idem
extern int Style_6   = 2; 
extern color Color_6 = Snow;

extern int Width_7   = 1;    //liniile de pe nivelul 6, idem
extern int Style_7   = 2; 
extern color Color_7 = Snow;

extern int Width_8   = 1;    //liniile de pe nivelul 6, idem
extern int Style_8   = 2; 
extern color Color_8 = Snow;

extern int Width_9   = 1;    //liniile de pe nivelul 6, idem
extern int Style_9   = 2; 
extern color Color_9 = Snow;

extern int Secondary_Width   = 1;    //liniile de pe nivelul 6, idem
extern int Secondary_Style   = 2; 
extern color Secondary_Color = clrLightSlateGray;

double pipettes, level1_Step, level2_Step;
//int nivele, 
int split;
bool IsDone;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   IsDone = false;

   //calculeaza pretul "cel mai rotund" posibil in functie de cotatia
   //instrumentului (pereche valutara, actiuni, etc) pe care e pus
   //chartul; Asta nu e chiar "imediat", prin rotunjire, deoarece spre
   //exemplu la euro pretul "rotund" este 1.3000, 1.4000, etc, pe cand 
   //la G/J spre exemplu este 130.00, 140.00, etc, iar la o cotatie 
   //intre 50 si 100 este diferit; de exemplu daca Bid-ul unui instrument 
   //oarecare este ceva de genul 7.154, vom avea "RN-urile" cele mai 
   //mari (de pe nivelul cel mai superior) de tipul 7.000, 8.000, etc,
   //deci nu intotdeauna se poate calcula doar prin simpla "rotunjire".
   
  //***ENGLISH: calculate price "the round" as possible depending on Quote of the instrument (currency pair, stock, etc) that is put charters; That's not "immediately" by rounding, as for example the euro price "round" is 1.3000, 1.4000, etc, the G / J for example is 130.00, 140.00, etc., and to quote while between 50 and 100 is different; for example, if the Bid of any instrument is something like 7154, we have "RN's" biggest (on the upper level) type 7000, 8000, etc., so not always can be calculated by simply "rounding".   
   if (PipettesPair) pipettes=10;
   else pipettes=1;
   
   level1_Step=1000*Point*pipettes;
   //daca splitul este zecimal (adica 1000 de pipsi pe nivelul 1, 100 pe al
   //doilea, 10 pe al treilea) atunci nu este util sa fie mai mult de trei
   //nivele de linii, celelalte se ignora. Daca splitul este binar (adica
   //1000 pe primul, 500 pe al doilea, 250 pe al treilea, etc) atunci pot
   //fi cel mult 6 nivele, ultimele avand 62.5 si respectiv 31.25 pipsi.

   //***ENGLISH: If Split is decimal (ie 1000 pips on level 1, 100 on the second, 10 the third) then it is useful to be more than three levels of lines, ignoring the others. If the split is binary (ie in 1000 the first, 500 the second, 250 the third, etc) then it could be more than 6 levels, the last with 62.5 and 31.25 respectively pips.

   level2_Step=100*Point*pipettes;  
   //***ENGLISH: Added a secondary split level for 100 on level 2
   
   return(0);
}

//+------------------------------------------------------------------+
//| Draw horiztonal lines                                            |
//+------------------------------------------------------------------+
void DrawLines(double levelStep, int nivele, bool isSecondary)
{
   if (BinaryDecimalSplit<=0) split=2;
   else split=10;

//   nivele=SplitLV;
   if (nivele<1) nivele=1;
   else if (split==10 && nivele>3) nivele=3;
   else if (split==2 && nivele>9) nivele=9;

   double pretIntreg, nouPretIntreg;
   //pretul "rotund" cel mai apropiat de pretul pietei (Bid)
   //###ENGLISH: price "round" the nearest market price (Bid)
   pretIntreg=NormalizeDouble(Bid/levelStep,0)*levelStep;
   
   //creez linia orizontala respectiva, daca nu exista deja
   CreateHLine("_RN_"+DoubleToStr(pretIntreg,Digits),pretIntreg,1, isSecondary);

   //creez toate liniile in sus, pe primul nivel, cat cuprinde range-ul de 
   //pipsi intregi specificat (atentie! nu pipeti!)
   for (nouPretIntreg=pretIntreg+levelStep; 
        nouPretIntreg<=Bid+PipRange*Point*pipettes; 
        nouPretIntreg+=levelStep)
        
      CreateHLine("_RN_"+DoubleToStr(nouPretIntreg,Digits),nouPretIntreg,1,isSecondary);
        
   //creez toate liniile in jos, pe primul nivel, cat cuprinde range-ul de 
   //pipsi intregi specificat (atentie! nu pipeti!)
   for (nouPretIntreg=pretIntreg-levelStep;
        nouPretIntreg>=Bid-PipRange*Point*pipettes;
        nouPretIntreg-=levelStep)
      CreateHLine("_RN_"+DoubleToStr(nouPretIntreg,Digits),nouPretIntreg,1,isSecondary);

   //traseaza toate nivelele intermediare in sus si in jos
   for (int i=2; i<=nivele; i++)
   {
      levelStep/=split;  //trec pe nivelul urmator de linii
      
      //creez toate liniile in sus, pe fiecare nivel, cat cuprinde range-ul de 
      //pipsi intregi specificat (atentie! nu pipeti!)
      for (nouPretIntreg=pretIntreg+levelStep; 
           nouPretIntreg<=Bid+PipRange*Point*pipettes; 
           nouPretIntreg+=levelStep)
         CreateHLine("_RN_"+DoubleToStr(nouPretIntreg,Digits),nouPretIntreg,i,isSecondary);
        
      //creez toate liniile in jos, pe fiecare nivel, cat cuprinde range-ul de 
      //pipsi intregi specificat (atentie! nu pipeti!)
      for (nouPretIntreg=pretIntreg-levelStep;
           nouPretIntreg>=Bid-PipRange*Point*pipettes;
           nouPretIntreg-=levelStep)
         CreateHLine("_RN_"+DoubleToStr(nouPretIntreg,Digits),nouPretIntreg,i,isSecondary);
   }      
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   //sterge toate liniile orizontale din fereastra principala, cand se
   //schimba chartul, ori TF-ul, ori cand se ia indicatorul de pe chart
   //
   //   ObjectsDeleteAll(0, OBJ_HLINE); 

   //**+* MODIFIED 2014-09-30 (FINANCIALCRIS) ****
   // Indicator was deleting ALL horizontal lines.
   // Changed to delete only lines created by itself "_RN_"
   
   int obj_total= ObjectsTotal();
   
   for (int i= obj_total; i>=0; i--) {
      string name= ObjectName(i);
    
      if (StringSubstr(name,0,4)=="_RN_") 
         ObjectDelete(name);
   }

   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   if (!IsDone)   
      { 
         if (EnablePrimarySplit_1000==true)
         DrawLines(level1_Step,LevelsOfSplit_Primary, false);
          
         if (EnableSecondarySplit_100==true)
            DrawLines(level2_Step, LevelsOfSplit_Secondary, true);          
            
         IsDone=true; 
      }

   //nu este nevoie de functie start, daca pretul o ia aiurea in balarii
   //prea sus sau prea jos relativ la liniile trase anterior, un simplu 
   //refresh de chart este destul sa recreeze toate liniile corect
   //(de exemplu se trece pe alt TF si apoi se trece inapoi, doar doua
   //clickuri de mouse). In acest fel se economisesc resurse procesor,
   //deoarece indicatorul nu se va recalcula la fiecare tick.
   
   //**+* MODIFIED 2014-09-30 (FINANCIALCRIS) ****
   // Indicator wasn't refreshing when placed on the chart.
   // Added a boolean flag that's negated on the first call of Start().

   return(0);
}
//+------------------------------------------------------------------+

void CreateHLine(string nume, double pret, int nivel, bool isSec)
{
   int grosime,stil;
   color culoare;
   
   switch (nivel)
   { 
      case 9:
         grosime=Width_9;
         stil=Style_9;
         culoare=Color_9;
         break;
      
      case 8:
         grosime=Width_8;
         stil=Style_8;
         culoare=Color_8;
         break;
      
      case 7:
         grosime=Width_7;
         stil=Style_7;
         culoare=Color_7;
         break;
      
      case 6:
         grosime=Width_6;
         stil=Style_6;
         culoare=Color_6;
         break;
         
      case 5:
         grosime=Width_5;
         stil=Style_5;
         culoare=Color_5;
         break;
         
      case 4:
         grosime=Width_4;
         stil=Style_4;
         culoare=Color_4;
         break;
         
      case 3:
         grosime=Width_3;
         stil=Style_3;
         culoare=Color_3;
         break;
         
      case 2:
         grosime=Width_2;
         stil=Style_2;
         culoare=Color_2;
         break;
         
      case 1:
         grosime=Width_1;
         stil=Style_1;
         culoare=Color_1;
         break;
   }         
   
   if (isSec)
      {
         grosime=Secondary_Width;
         stil=Secondary_Style;
         culoare=Secondary_Color;
      }
   
   if (grosime!=1) stil=0; //in MT4 doar liniile subtiri pot avea "style"
   
   //verific daca exista deja linia respectiva, atunci nu o mai trag
   //deoarece probabil a fost trasa pe un nivel superior, anterior
   if (ObjectFind(nume)==-1)
   {
      ObjectCreate(nume,OBJ_HLINE,0,TimeCurrent(),pret);
      ObjectSet(nume,OBJPROP_WIDTH,grosime);
      ObjectSet(nume,OBJPROP_STYLE,stil);
      ObjectSet(nume,OBJPROP_COLOR,culoare);
      ObjectSet(nume,OBJPROP_BACK,true);
      ChartRedraw(0);
   }
}


