//+----------------------------------------------------------------------------+
//|                                     СandlesDistributionStatistic 1.03.mq4  |
//|                                                                            |
//|  18.06.2018  Индикатор для расчёта :                                       |
//|              распределения групп счеч по длине                             |
//|              Open-Close и High-Low                                         |
//+----------------------------------------------------------------------------+
#property copyright "Usver73"
#property version   "1.03"
#property indicator_chart_window  //Индикатор
enum     _EventLogs
  {
   ALL  = 1, //On 
   NONE = 3  //Off
  };

#define ALL           0  //все свечи
#define BUY           1  //свечи БАЙ
#define SEL           2  //свечи СЕЛЛ

#define HILO          0  //High-Low свечи
#define BODY          1  //тело свечи весь 

#define AL_D          0  //Весь день
#define IN_D          1  //Указанный период интрадей

extern int      Group         = 1; // Количество свечей в группе
extern datetime BeginDateCalc = D'2018.06.18 00:00:00';
extern datetime EndDateCalc   = D'2018.06.18 23:59:59';
extern string   a1="ПАРАМЕТРЫ ШКАЛЫ";
extern int      step          =9; //Цена деления шкалы
extern int      count         =5; //Количество делений шкалы
extern string   aa1="ИНТРАДЕЙ ПЕРИОДЫ";
extern int      IDbegin       =0;//Интрадей начало  периода, час
extern int      IDlenth       =0;//Интрадей продолжительность периода, час
extern string aa3="-----------------------";
input color           BackColor     = clrWhiteSmoke;     //Цвет фона
input color           FontColor     = clrDarkBlue;       //Цвет шрифта 
input color           HeadColor     = clrBrown;          //Цвет заголовков
extern _EventLogs     LogMode       = 3;

//------------------------------------------------------------------+
//    входные параметры инфопанели
//------------------------------------------------------------------+
//input string          aa6="НАСТРОЙКИ ИНФОРМАЦИОННОЙ ПАНЕЛИ";//    
                
        int            ShiftCol      = 750;               //ширина между столбцами
        int            ShiftRow      = 160;               //высота между строк
        int            StartShiftX   = 20;               // смещение от левого края
        int            StartShiftY   = 20;               // смещение от верхнего края
        int            FontSize      = 9;                //Размер шрифта

int                   PanelCorn     = CORNER_LEFT_UPPER; // Угол расположения инфопанели на графике 
int                   CountBlock    =1; //кличество выводимых блоков     
int                   handle;    
bool                  Work          =true;    
string                s0,s1,s2;
double                maxPrice=0, minPrice=0; //максимальная / минимальная цена за период
double                maxBodyA=0, maxBodyB=0, maxBodyS; // max. тело свечи
double                maxSizeA=0, maxSizeB=0, maxSizeS; // max. свеча High-Low  
struct                Ginfo {                // набор характеристик группы свеч
double                open;
double                close;
double                high;
double                low;
int                   id;
datetime              time;
};
//+----------------------------------------------------------------------------+
//|  script program start function                                             |
//+----------------------------------------------------------------------------+
string NameGrCdl[3]; // DELETED
int    DataArr[][3][2][2];                         //Массив с данными
int    ScaleArr[];                                 //Массив с границами размеров 
string LvlArr[];                                   //Массив с именами строк
string ParamArr [3]  ={"ШТ","%","+%"};        //массив с наименованием параметров
string GroupArr [3]  ={"ALL", "BUY","SELL"};       //массив с названиями групп по типу свечей
string PeriodArr[2]  ={"Весь период","Внутри дня с "};//массив наименований периодов

string shortname;     
string LBLname="lbl";
int LvlSize;  // количество строк в табл.
//--------------------------------------------------------------------//
//
//--------------------------------------------------------------------//     
void OnDeinit(const int reason)
 {
   DeleteControl();     
 }          
//--------------------------------------------------------------------//
//
//--------------------------------------------------------------------//
void init() 
{
 Work=true;
 LvlSize = count+4;
 int i,firstLVL;
 
 ArrayResize(ScaleArr,count+1);
 ArrayResize(LvlArr, LvlSize);
 ArrayResize(DataArr,LvlSize);
 //Заполняем массив наименований строк
 for(i=1;i<LvlSize-2;i++)LvlArr[i]=i*step;

 LvlArr[0]        ="0";
 LvlArr[LvlSize-3]="> "+LvlArr[LvlSize-4];  
 LvlArr[LvlSize-2]="Max";
 LvlArr[LvlSize-1]="Итого"; 
 // заполняем массив- шкалу распределения свеч
 switch(step)
   {
    case  2:
      firstLVL=1;
      break;
    case  3:
      firstLVL=2;
      break;
    default:
      firstLVL = MathCeil(step/2.0);
      break;
   }
 ScaleArr[0] = firstLVL;
 
 for(i=1;i<=count;i++) ScaleArr[i]=ScaleArr[i-1]+step;

 if(LogMode<2) {
   Print(__FUNCTION__ ," : Шкала распределения");
   for(int ii=0;ii<LvlSize;ii++)Print(__FUNCTION__ , " : [id Строки]= ",ii,"  Группировка по значению: ",LvlArr[ii], " , Верхняя граница ",ScaleArr[ii]);
  }
 if (IDlenth !=0)
  {
   CountBlock=2;
   int EndHour     = IDbegin+IDlenth;
   if (EndHour >=24) {EndHour=24; IDlenth=24-IDbegin;}
   PeriodArr[1]=StringConcatenate(PeriodArr[1]," ", IDbegin, ":00 до ", EndHour-1, ":59. Длина ",IDlenth,"ч.");
  }
  PutRectangle("lbl_background", StartShiftX-10, StartShiftY-10, ShiftCol*CountBlock+77,180+20*LvlSize,CORNER_LEFT_UPPER, BackColor,BORDER_RAISED);
  PutButton("lblClose","X",ShiftCol*CountBlock+50);
  PutButton("lblRecalc","O",ShiftCol*CountBlock+30);
  
 PutRectangle(StringConcatenate(LBLname,"HeadNameBG"),StartShiftX-8,StartShiftY+90,73,(LvlSize+4)*20,CORNER_LEFT_UPPER,clrDarkBlue,BORDER_RAISED);
 PutLabel(StringConcatenate(LBLname,"HeadName"),   StartShiftX , StartShiftY+110, "Р-р",   PanelCorn,   FontSize+3, clrWhite);// SUB заголовок Size
 
 for(int r=0;r< ArraySize(LvlArr);r++) PutLabel(StringConcatenate(LBLname,"HeadRow"+r),   StartShiftX , StartShiftY+170+20*r, LvlArr[r], PanelCorn,  FontSize+1, clrWhite);//названия строк 

  shortname= "DistrSat_" + Symbol() + "_" + GetNameTF(Period());
  IndicatorSetString(INDICATOR_SHORTNAME,shortname);
}
//--------------------------------------------------------------------//
//
//--------------------------------------------------------------------//
void start() 
{
  int    i;
  if(!Work)return;// Если был проход, то выход
  Ginfo  GR; //свойства группы свеч
  ArrayInitialize (DataArr,0);
  
  for (i=Bars; i>0; i--) 
  {
    if ((Time[i]>=BeginDateCalc && Time[i]<=EndDateCalc )) 
    {
      GR.open=0; GR.close=0; GR.high=0; GR.low=0; GR.id=0; GR.time=0;
      bool   ser = Series(i, GR);
 
      if (!ser)continue;
      
      if (maxPrice < High[i])               maxPrice= High[i];     // поиск максимальной цены за период
      if (minPrice > Low[i] || minPrice==0) minPrice= Low[i];      // поиск минимальной цены за период
      GetStat(AL_D, GR);                                            // статистика за весь период
      int BarHour = TimeHour (GR.time);     // час бара
     // int DayW    = TimeDayOfWeek(GR.time); //день недели бара
      
      if (IDlenth!=0 && IDbegin <= BarHour && BarHour < (IDbegin+IDlenth))
       {
        if(LogMode<2)Print(__FUNCTION__ , " : Проверка диапазона интрадей. Начальный час ",IDbegin ,
                           " , Конечный час ",IDbegin+IDlenth, " , время(ч) свечи(группы) ", BarHour);
        GetStat(IN_D,GR);                                           //статистика за все дни в период IntraDay
       }
    }
  }
  
  string FirstTime= TimeToStr(BeginDateCalc,TIME_DATE | TIME_MINUTES);
  if (BeginDateCalc < iTime(NULL,0,Bars-1))
   {
    string TimeFirstBar= TimeToString(iTime(NULL,0,Bars-1));
    string str = "На графике "+IntegerToString(Bars-1)+" баров. Начальная дата "+ TimeToStr(BeginDateCalc)+ " меньше даты самого раннего бара "+ TimeFirstBar;
    Alert(str);
    FirstTime= TimeToStr(BeginDateCalc,TIME_DATE | TIME_MINUTES)+ "("+ TimeFirstBar  +")";
   } 
  
  //Рисуем заголовок по инструменту и фон
   string LastTime= TimeToStr(EndDateCalc,TIME_DATE | TIME_MINUTES);
    //меньшее время между текущим и заданным в настройках вр. окончания. Для заголовка
   if (TimeCurrent() < EndDateCalc) LastTime=TimeToStr(TimeCurrent(),TIME_DATE | TIME_MINUTES);// Print("TimeCurrent ", TimeCurrent());}

   string filename = "DistributionStat_" + Symbol() + "_" + GetNameTF(Period()) +".csv";
   handle=FileOpen(filename,FILE_CSV|FILE_READ|FILE_WRITE," ");
   if (handle < 0) Print("Error: file " + filename + " cannot be created");
   while (!FileIsEnding(handle)) string data = FileReadString(handle);  
   
   //пишем заголовок на экран 
   s0=StringConcatenate(Symbol(),", ",GetNameTF(Period()),", значность ", _Digits,", Группировка ",Group," свеч(и)");
   PutLabel("lbl_Head0", StartShiftX ,StartShiftY, s0,PanelCorn,FontSize+2, clrDarkBlue);// заголовок Группы периода
   
   s0=StringConcatenate("Период с ", FirstTime, " по ",LastTime);
   PutLabel("lbl_Head01", StartShiftX ,StartShiftY+20, s0,PanelCorn,FontSize+2, clrDarkBlue);
   
   s0= StringConcatenate("Макс. цена ", DoubleToStr(maxPrice,_Digits), " Мин.цена ", DoubleToStr(minPrice,_Digits),
                         " Размах ", (maxPrice-minPrice)/_Point , " пп");
   PutLabel("lbl_Head02", StartShiftX ,StartShiftY+40, s0,PanelCorn,FontSize+2, clrDarkBlue);// информация о макс. и мин. цене
   s0=StringConcatenate("Шаг ",step, "  Количество шагов ", count);
   PutLabel("lbl_Head03", StartShiftX ,StartShiftY+60, s0,PanelCorn,FontSize+2, clrDarkBlue);// информация о размере и количестве шагов
   // пишем заголовок в файл
   FileWrite(handle, StringConcatenate(Symbol(), ";TF= ",GetNameTF(Period()),";",TimeToStr(BeginDateCalc,TIME_DATE | TIME_MINUTES),";", LastTime,";Группа",";",Group));
   FileWrite(handle,"Максимальная цена;", DoubleToStr(maxPrice,_Digits), ";Минимальная цена;", DoubleToStr(minPrice,_Digits), ";Размах;",((maxPrice-minPrice)/_Point) );
   FileWrite(handle,"Шаг;",step, "  Количество шагов;", count);
   FileWrite(handle,"ПЕРИОД;ГРУППА;ДЛИНА СВЕЧИ пп;Кол-во;%;	% наростающим");
  //DrawBlock(0);// вывод на экран и в файл блоков по всему периоду
  
  for (int d=0; d<=CountBlock-1;d++)
   {
    DrawBlock(d);// вывод на экран и в файл блоков по всему периоду
   }
  Print("Конец работы индикатора");
  FileClose(handle);
  ChartSetInteger (0,CHART_FOREGROUND,false);
  ChartRedraw(0);
  Work=false;
}
//--------------------------------------------------------------------//
// Поиск серии однонаправленных свечей
//--------------------------------------------------------------------//
bool Series(int i, Ginfo & GR)
 {
  int    Direct=0;
  string strDir="";
  double Size = Close[i]-Open[i];
  //Print(__FUNCTION__ , " : Start bar ",i, " , end bar ", i+1-Group,". Break.");
  if(Size>0)          {Direct= 1; strDir="BUY";}
  else if (Size<0)    {Direct=-1; strDir="SELL";}
  else if (Size==0 && Group==1)    return (false);  // прерываем анализ если первая свеча в группе с 0-м телом и группа состоит из более , чем одной свечи
                                                    // т.к. невозможно определить направление серии по 0-му телу свечи
  
  // прерываем поиск если очередная свеча - нулевая (текущая)
  if (i+1-Group<1){if(LogMode<2)Print(__FUNCTION__ , " : Start bar ",i, " , end bar ", i+1-Group,". Break.");return (false);}
  
  GR.open = Open[i]; GR.close = Close[i+1-Group]; 
  GR.low  = Low[i];  GR.high = High[i];
  
  for (int a=i-1; a>i-Group;a--)
    {
      double dirA = Close[a]-Open[a];

      if( (Direct > 0 && dirA < 0) || (Direct < 0 && dirA > 0)) return (false); // если свеча имеет противоположное направление, значит группа не сформировалась
      if(Time[a] - Time[a+1]>_Period*60) {if(LogMode)Print(__FUNCTION__ , " : Большое время между свечами (ночь/выходной). Серия прервана.");return(false);} // если переход через начь/выходные- прерываем серию

      if(GR.low  > Low[a])  GR.low  = Low[a];  // находим ЛОУ группы
      if(GR.high < High[a]) GR.high = High[a]; // находим ХАЙ группы  
    }
  
  GR.id   = i;GR.time = Time[i];
  if (LogMode<2){
          Print(__FUNCTION__ , " : Найдена группа свечей ", strDir,". Первая свеча ",i,
                               " , время ", TimeToStr(GR.time,TIME_DATE)," ", TimeToStr(GR.time,TIME_MINUTES),
                               " , Open ",DoubleToStr(GR.open,_Digits)," , Close ", DoubleToStr(GR.close,_Digits), 
                               " , High ", DoubleToStr(GR.high,_Digits)," , Low ", DoubleToStr(GR.low,_Digits));
          Print(__FUNCTION__ ,  ": HIGH-LOW группы из ",Group," свеч(и): ", (GR.high-GR.low)/_Point ," , Тело группы: ", MathAbs( (GR.open-GR.close)/_Point ));                            
   }
  return (true);
 }
//+------------------------------------------------------------------+
//|  Создание ИНФО панели                                            |
//+------------------------------------------------------------------+
void DrawBlock(int g)//g- номер диапазона
 {
 string sgf,sg,sg0,sg1,sg2;
 int x, y;
 LBLname+=IntegerToString(g);
 
 int row=(int)MathFloor((g)/3);
 int col=g-row*3;
 
 x = StartShiftX+ShiftCol*col;
 y = StartShiftY+60+ShiftRow*row;
 
 y=y+30;
 PutRectangle(StringConcatenate(LBLname,"HeadGrBG"),x+65,y,ShiftCol,20,CORNER_LEFT_UPPER,clrDarkBlue,BORDER_RAISED);
 PutLabel(StringConcatenate(LBLname,"HeadGr"),   x +270, y, PeriodArr[g],   PanelCorn,   FontSize+4, clrWhite);// заголовок Группы периода
 
 y+=20; x+=20;
 PutRectangle(StringConcatenate(LBLname,"HeadGrHiLoBG"),x+45,y,ShiftCol/2,20,CORNER_LEFT_UPPER,clrRoyalBlue,BORDER_RAISED);
 PutLabel(StringConcatenate(LBLname,"HeadGrHiLo"),   x+180 , y, "HIGH - LOW",   PanelCorn,   FontSize+3,clrWhite);// SUB заголовок HiLo 
 
 PutRectangle(StringConcatenate(LBLname,"HeadGrOpClBG"),x+45+ShiftCol/2,y,ShiftCol/2,20,CORNER_LEFT_UPPER,clrRoyalBlue,BORDER_RAISED);
 PutLabel(StringConcatenate(LBLname,"HeadGrOpCl"),   x+560 , y, "OPEN - CLOSE",   PanelCorn,   FontSize+3, clrWhite);// SUB заголовок OpCl
 
 y+=20;

//=====================
 
 for(int l=0;l<6;l++) PutRectangle(StringConcatenate(LBLname,"HeadGrSubBG",l),x+45+125*l,y,125,20,CORNER_LEFT_UPPER,clrDodgerBlue,BORDER_RAISED);
 
 x=StartShiftX+ShiftCol*col+110;
 for(int a=0;a<2;a++) PutLabel(StringConcatenate(LBLname,"HeadGrSub",a),x+390*a, y, GroupArr[0]+"           "+GroupArr[1]+"          "+GroupArr[2],   PanelCorn,   FontSize+2, clrWhite);// SUB заголовок Group A/B/S 

 x=StartShiftX+ShiftCol*col+70;
 for(int b=0;b<6;b++) PutLabel(StringConcatenate(LBLname,"HeadGrSub2",b,g),   x+3+125*b , y+20, ParamArr[0]+"   "+ParamArr[1]+"   "+ParamArr[2],   PanelCorn,   FontSize+1, HeadColor);// SUB заголовок Group /шт/%/+%

 // рисуем заголовки строк
 y+=40;
 int k,n,r;
//============================================ 
// считаем строку ИТОГО
     for(k=0;k<2;k++){              // Body/Candle
        for(n=0;n<3;n++){           // All/Buy/Sell
           for(r=0;r<count+2;r++){  // Row
              DataArr[count+3][n][k][g] += DataArr[r][n][k][g];
             }
          }
       }
  // заполняем экранную таблицу значениями
x+=2;
     for(k=0;k<2;k++) {  
        for(n=0;n<3;n++) {
           double total    = DataArr[count+3][n][k][g]*1.0;
           double acc_perc = 0;
           int xx   = x+n*125+k*375;
           for(r=0;r<ArraySize(LvlArr);r++) {
              
              if(total==0)continue;
              
              int vol  = DataArr[r][n][k][g];
              double perc = vol/total*100;
              
              if(r<count+2)acc_perc+=perc;
              
              sg0= GetFixStr(IntegerToString(vol),5);
              sg1= GetFixStr(DoubleToStr(perc,1),6);
              sg2= GetFixStr(DoubleToStr(acc_perc,1),6); 
              sg = sg0;
              sgf= vol;
              if(r<count+2){sg=sg+sg1+sg2; sgf=StringConcatenate(sgf,";",DoubleToStr(perc,1),";",DoubleToStr(acc_perc,1));}
              
              PutLabel(StringConcatenate(LBLname,"Data",r,n,k),   xx , y+20*r, sg, PanelCorn,  FontSize, FontColor);
             
              FileWrite(handle,StringConcatenate(PeriodArr[g],";",GroupArr[n],";",LvlArr[r] ,";",sgf));
             }
           PutRectangle(StringConcatenate(LBLname,"Broder",n,k,g),xx-8,y-20,2,(count+5)*20,CORNER_LEFT_UPPER,clrDodgerBlue,BORDER_FLAT);// вертикальные линии
          }
       } 

 y+=40; 
 
 string sHeadGrC=StringConcatenate("Размер ",ParamArr[0],"     ",ParamArr[1],"     ",ParamArr[2]);
 s2=s2+sHeadGrC+GetFixStr(" ",4);
 y=y+15;
 //FileWrite(handle,"--------");
 }
//--------------------------------------------------------------------//
////-------------Возвращает строку определенной длины-------------
//--------------------------------------------------------------------// 
 
 string GetFixStr(string str,int len)//str- исходная строка, len- конечная длина
  {
    int     AddCountChr = len- StringLen (str);
    string  AddStr ="";
    StringInit (AddStr,AddCountChr,032);
    return(str+AddStr);
  }
//+------------------------------------------------------------------+
//|  Создание контрола "LABLE"                                       |
//+------------------------------------------------------------------+
void PutLabel(string name,int x,int y,string text,int coner, int w, color clr)
  {
   if (ObjectFind(name)<0)ObjectCreate(0,name,OBJ_LABEL,0,0,0);
   ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
   ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
   ObjectSetInteger(0,name,OBJPROP_CORNER,coner);
   ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
   ObjectSetInteger(0,name,OBJPROP_BACK,false);
   ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
   ObjectSetText(name,text,w,"Courier New",clr);
  } 
//+------------------------------------------------------------------+
//|  Создание контрола "BUTTON"                                      |
//+------------------------------------------------------------------+  
void PutButton(string name, string txt, int x)
  {
  ObjectCreate(0,name,OBJ_BUTTON,0,0,0);
  ObjectSetText(name,txt,10,"Arial");  
  ObjectSetInteger(0,name,OBJPROP_BGCOLOR,clrDodgerBlue);
  ObjectSetInteger(0,name,OBJPROP_COLOR,clrWhite);
  ObjectSetInteger(0,name,OBJPROP_CORNER,CORNER_LEFT_UPPER);
  ObjectSetInteger(0,name,OBJPROP_XDISTANCE,StartShiftX+x);
  ObjectSetInteger(0,name,OBJPROP_YDISTANCE,StartShiftY-7);
  ObjectSetInteger(0,name,OBJPROP_XSIZE ,15);
  }  
//--------------------------------------------------------------------//
//
//--------------------------------------------------------------------//
void GetStat(int p, Ginfo &G) //  p- период (весь/интрадей)G- структура с инфо по свече
{
/* 
#define ALL           0  //все свечи
#define BUY           1  //свечи БАЙ
#define SEL           2  //свечи СЕЛЛ

#define BODY          0  //тело свечи
#define HILO          1  //High-Low свечи

#define Al_D          0  //Весь день
#define IN_D          1  //Указанный период интрадей*/

  int    HiLoSize =(int) NormalizeDouble( (G.high-G.low)/_Point,0);
  int    BodySize   =(int) NormalizeDouble(  MathAbs(G.open-G.close)/_Point,0); 
  int    Dir        =0;                // направление свечи: 1- БАЙ, -1 - СЕЛЛ, 0= n/a
  int    ScaleSize  =ArraySize(ScaleArr);
  string Direct     ="";
  string stBar      =IntegerToString(G.id);
  string stDT       =TimeToStr(G.time,TIME_DATE)+" "+TimeToStr(G.time,TIME_MINUTES);
  
  
  if      (G.open-G.close < 0) {Dir= 1;Direct="BUY";}
  else if (G.open-G.close > 0) {Dir=-1;Direct="SELL";}
  if(LogMode==1)Print(__FUNCTION__ , " : Распределение свеч по группам:"); 
 // Записываем свечи с 0-м размером 
  if(BodySize < ScaleArr[0]) {
     if(LogMode==1)Print(__FUNCTION__ , " : тело ",Direct," свечи ",stBar," , time ",stDT,  " < ",ScaleArr[0]);           
                DataArr[0][ALL][BODY][p]++;
     if(Dir== 1)DataArr[0][BUY][BODY][p]++;
     if(Dir==-1)DataArr[0][SEL][BODY][p]++;
    }
  if(HiLoSize < ScaleArr[0])  {
     if(LogMode==1)Print(__FUNCTION__ , " : HILO ",Direct," свечи ",stBar," , time ",stDT,  " < ",ScaleArr[0]);           
                DataArr[0][ALL][HILO][p]++;
     if(Dir== 1)DataArr[0][BUY][HILO][p]++;
     if(Dir==-1)DataArr[0][SEL][HILO][p]++;
    } 
// Записываем основное "тело" таблицы  
  for(int i=1; i<=count; i++)
    {
     if(ScaleArr[i-1] <= BodySize && BodySize < ScaleArr[i]) {
        if(LogMode==1)Print(__FUNCTION__ , " : тело ",Direct," свечи ",stBar," , time ",stDT,  " в диапазоне ",ScaleArr[i-1] ," <= И < ",ScaleArr[i]);
                   DataArr[i][ALL][BODY][p]++;
        if(Dir== 1)DataArr[i][BUY][BODY][p]++;
        if(Dir==-1)DataArr[i][SEL][BODY][p]++;
      }
     if(ScaleArr[i-1] <= HiLoSize && HiLoSize < ScaleArr[i]) {
       if(LogMode==1)Print(__FUNCTION__ , " : HILO ",Direct," свечи ",stBar," , time ",stDT,  " в диапазоне ",ScaleArr[i-1] ," <= И < ",ScaleArr[i]);
                  DataArr[i][ALL][HILO][p]++;
       if(Dir== 1)DataArr[i][BUY][HILO][p]++;
       if(Dir==-1)DataArr[i][SEL][HILO][p]++;
      }
    }
 // Print(__FUNCTION__ , " : ScaleArr[count] ",ScaleArr[count]);
 // Считаем максимальные свечи - количество OpCl
  if(BodySize > ScaleArr[count]) {
    if(LogMode==1)Print(__FUNCTION__ , " : тело ",Direct," свечи ",stBar," , time ",stDT,  " > ",ScaleArr[0]);           
               DataArr[LvlSize-3][ALL][BODY][p]++;
    if(Dir== 1)DataArr[LvlSize-3][BUY][BODY][p]++;
    if(Dir==-1)DataArr[LvlSize-3][SEL][BODY][p]++;
// Ищем максимальную свечу  OpCl  
    if(DataArr[LvlSize-2][ALL][BODY][p] < BodySize)           DataArr[LvlSize-2][ALL][BODY][p] = BodySize;
    if(Dir== 1 && DataArr[LvlSize-2][BUY][BODY][p] < BodySize)DataArr[LvlSize-2][BUY][BODY][p] = BodySize;
    if(Dir==-1 && DataArr[LvlSize-2][SEL][BODY][p] < BodySize)DataArr[LvlSize-2][SEL][BODY][p] = BodySize;
    } 
 // Считаем максимальные свечи - количество HILO    
  if(HiLoSize > ScaleArr[count]) {
    if(LogMode==1)Print(__FUNCTION__ , " : HILO ",Direct," свечи ",stBar," , time ",stDT,  " > ",ScaleArr[0]);
               DataArr[LvlSize-3][ALL][HILO][p]++; 
    if(Dir== 1)DataArr[LvlSize-3][BUY][HILO][p]++; 
    if(Dir==-1)DataArr[LvlSize-3][SEL][HILO][p]++; 
// Ищем максимальную свечу  HILO      
    if(DataArr[LvlSize-2][ALL][HILO][p] < HiLoSize)           DataArr[LvlSize-2][ALL][HILO][p] = HiLoSize;
    if(Dir== 1 && DataArr[LvlSize-2][BUY][HILO][p] < HiLoSize)DataArr[LvlSize-2][BUY][HILO][p] = HiLoSize;
    if(Dir==-1 && DataArr[LvlSize-2][SEL][HILO][p] < HiLoSize)DataArr[LvlSize-2][SEL][HILO][p] = HiLoSize;
   } 
}
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 01.09.2005                                                     |
//|  Описание : Возвращает наименование таймфрейма                             |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    TimeFrame - таймфрейм (количество секунд)      (0 - текущий TFmain)     |
//+----------------------------------------------------------------------------+
string GetNameTF(int TimeFrame=0) {
  if (TimeFrame==0) TimeFrame=Period();
  switch (TimeFrame) {
    case PERIOD_M1:  return("M1");
    case PERIOD_M5:  return("M5");
    case PERIOD_M15: return("M15");
    case PERIOD_M30: return("M30");
    case PERIOD_H1:  return("H1");
    case PERIOD_H4:  return("H4");
    case PERIOD_D1:  return("Daily");
    case PERIOD_W1:  return("Weekly");
    case PERIOD_MN1: return("Monthly");
    default:         return("UnknownPeriod");
  }
}
//+------------------------------------------------------------------+
//|  bool to string                                 |
//+------------------------------------------------------------------+ 
string BoolToStr(bool b)
 {
  if(b) return("TRUE");
  return("FALSE");
 }
//+------------------------------------------------------------------+
//|  Создание контрола Прямоугольник                                 |
//+------------------------------------------------------------------+  
void PutRectangle(string Oname,long x,long y,long xSize, long ySize, int coner, color cl,int Border_type)
{
    if (ObjectFind(Oname)<0)
     { 
      if(!ObjectCreate(0,Oname,OBJ_RECTANGLE_LABEL,0,0,0)) 
       { 
        Print(__FUNCTION__,": не удалось создать прямоугольную метку! Код ошибки = ",GetLastError()); 
       }
     }   
      ObjectSetInteger (0,Oname,OBJPROP_XDISTANCE,x);
      ObjectSetInteger (0,Oname,OBJPROP_YDISTANCE,y);
      ObjectSetInteger (0,Oname,OBJPROP_XSIZE ,xSize);
      ObjectSetInteger (0,Oname,OBJPROP_YSIZE ,ySize);
      ObjectSetInteger (0,Oname,OBJPROP_CORNER,coner);
      ObjectSetInteger (0,Oname,OBJPROP_BGCOLOR,cl); 
      ObjectSetInteger (0,Oname,OBJPROP_BORDER_TYPE,Border_type); 
      ObjectSetInteger (0,Oname,OBJPROP_COLOR,cl); 
      ObjectSetInteger (0,Oname,OBJPROP_BACK,false);
} 
//--------------------------------------------------------------------//
////---------Реакция на события------------------------- 
//--------------------------------------------------------------------//
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
//--- проверим событие на нажатие кнопки мышки
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      string clickedChartObject=sparam;
      if(clickedChartObject=="lblClose")       Remove();
      if(clickedChartObject=="lblRecalc")      Work=true;
      if(ObjectGetInteger(0, clickedChartObject, OBJPROP_STATE)==true)
      {
        Sleep(100);
        ObjectSetInteger(0,clickedChartObject,OBJPROP_STATE,false);
      }
      ChartRedraw();// принудительно перерисуем все объекты на графике
     }
}
//--------------------------------------------------------------------//
//
//--------------------------------------------------------------------//
void Remove()
{
  DeleteControl();
  ChartRedraw();
  if (ChartIndicatorDelete(0,0,shortname)) Print("Удален индикатор ",shortname);
  else PrintFormat("Не удалось удалить индикатор %s с окна #%d. Код ошибки %d", 
                     shortname,0,GetLastError()); 
}
//--------------------------------------------------------------------//
//Удаляем "наши" контролы
//--------------------------------------------------------------------//
void DeleteControl()
 {
    for(int i=ObjectsTotal()-1;i>=0;i--) 
     { 
       string name=ObjectName(i); 
       if (StringFind (name,"lbl",0)>-1) ObjectDelete(name); 
     } 
 } 