//+------------------------------------------------------------------+
//|                                                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"!!
extern bool PipettesPair      = false; //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.
extern int BinaryDecimalSplit = 0;     //split mode: 0=binary split, 1=decimal split
extern int LevelsOfSplit      = 6;     //intre 1 si 3-6 nivele, depinde de tipul
                                       //contului (pipsi/pipeti) si de split mode
extern string Legend = "Parametrii liniilor, maxim 6 nivele.";

extern int Width_1   = 3;    //grosimea liniei pe nivelul 1 (superior), intre 1 si 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;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   double pretIntreg, nouPretIntreg, pipettes, level1Step;
   int nivele, split;

   //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".
   if (PipettesPair) pipettes=10;
   else pipettes=1;
   level1Step=1000*Point*pipettes;
   
   //pretul "rotund" cel mai apropiat de pretul pietei (Bid)
   pretIntreg=NormalizeDouble(Bid/level1Step,0)*level1Step;
   
   //creez linia orizontala respectiva, daca nu exista deja
   CreateHLine("_RN_"+DoubleToStr(pretIntreg,Digits),pretIntreg,1);

   //creez toate liniile in sus, pe primul nivel, cat cuprinde range-ul de 
   //pipsi intregi specificat (atentie! nu pipeti!)
   for (nouPretIntreg=pretIntreg+level1Step; 
        nouPretIntreg<=Bid+PipRange*Point*pipettes; 
        nouPretIntreg+=level1Step)
      CreateHLine("_RN_"+DoubleToStr(nouPretIntreg,Digits),nouPretIntreg,1);
        
   //creez toate liniile in jos, pe primul nivel, cat cuprinde range-ul de 
   //pipsi intregi specificat (atentie! nu pipeti!)
   for (nouPretIntreg=pretIntreg-level1Step;
        nouPretIntreg>=Bid-PipRange*Point*pipettes;
        nouPretIntreg-=level1Step)
      CreateHLine("_RN_"+DoubleToStr(nouPretIntreg,Digits),nouPretIntreg,1);
   
   //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.
   if (BinaryDecimalSplit<=0) split=2;
   else split=10;

   nivele=LevelsOfSplit;
   if (nivele<1) nivele=1;
   else if (split==10 && nivele>3) nivele=3;
   else if (split==2 && nivele>6) nivele=6;

   //traseaza toate nivelele intermediare in sus si in jos
   for (int i=2; i<=nivele; i++)
   {
      level1Step/=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+level1Step; 
           nouPretIntreg<=Bid+PipRange*Point*pipettes; 
           nouPretIntreg+=level1Step)
         CreateHLine("_RN_"+DoubleToStr(nouPretIntreg,Digits),nouPretIntreg,i);
        
      //creez toate liniile in jos, pe fiecare nivel, cat cuprinde range-ul de 
      //pipsi intregi specificat (atentie! nu pipeti!)
      for (nouPretIntreg=pretIntreg-level1Step;
           nouPretIntreg>=Bid-PipRange*Point*pipettes;
           nouPretIntreg-=level1Step)
         CreateHLine("_RN_"+DoubleToStr(nouPretIntreg,Digits),nouPretIntreg,i);
   }
   
   return(0);
}

//+------------------------------------------------------------------+
//| 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); 
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   //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.
   return(0);
}
//+------------------------------------------------------------------+

void CreateHLine(string nume, double pret, int nivel)
{
   int grosime,stil;
   color culoare;
   
   switch (nivel)
   { 
      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 (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);
   }
}


