/*
//----+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ 
//Version  July 1, 2006                                              |
Editing   Nikolay Kositsin  15.06.2006  farria@mail.redcom.ru        |
//----+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ 
HTF.mqh      -   Это файл,    созданный   для  максимального упрощения 
написания индикаторов, расчитывающих свои значения на основе данных  с 
графика другого,более крупного таймфрейма.    Пример   использования - 
файл J2JMA_htf.mq4
//+------------------------------------------------------------------+
//|                                                          HTF.mqh |
//|                            Copyright © 2006, GS  Conversion only |
//|                    http://www.gustis.narod.ru;     gsb51@mail.ru |
//+------------------------------------------------------------------+
#property copyright "  Copyright © 2006, GS  Conversion only"
#property link      " http://www.gustis.narod.ru;     gsb51@mail.ru"
//---- отрисовка индикатора в основном окне
#property indicator_chart_window
//---- количество индикаторных буферов
#property indicator_buffers  4
//---- цвета индикатора
#property indicator_color1 Red
#property indicator_color2 Lime
#property indicator_color3 Magenta
#property indicator_color4 Gray
*/
//---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА -------------------------------------------------------------------------+
extern int  TFrame_Period = 240; // Старший период в минутах
extern int         Smooth = 48;  // сглажиание полученного мувинга. Наиболее оптимальное значение равно отношению периодов старшего таймфрейма к периоду графика
extern bool Trend_Visible = true;// визуализация индикации тренда
extern int  Trend_Minimum = 5;   // минимальная скорость мувинга, принимаемая за тренд
extern int         Shift  = 0;   // cдвиг индикатора вдоль оси времени 
//---- ------------------------------------------------------------------------------------------------------+
datetime TFrame_Times[]; 
//---- индикаторные буферы
double Ind_Buffer0[];
double Ind_Buffer1[];
double Ind_Buffer2[];
double Ind_Buffer3[];
double Vel_Buffer [];
//----
double MINIMUM;
int NTF,time1,weight;
//+------------------------------------------------------------------+
//| HTF initialization function                                      | 
//+------------------------------------------------------------------+
int init() 
  { 
//--------- индикаторы ---------------------------------------------- 

   //---- Стиль исполнения графика в линии     
   SetIndexStyle(0,DRAW_LINE);
   //---- Стиль исполнения графика виде точечной линии
   SetIndexStyle(1,DRAW_ARROW);
   SetIndexStyle(2,DRAW_ARROW);
   SetIndexStyle(3,DRAW_ARROW);
   //---- Определение стиля точечных объектов
   SetIndexArrow(1,159);
   SetIndexArrow(2,159);
   SetIndexArrow(3,159);
   //---- горизонтальный сдвиг индикаторных линий
   SetIndexShift(0, Shift); 
   SetIndexShift(1, Shift);
   SetIndexShift(2, Shift);
   SetIndexShift(3, Shift);
   //---- имя для окон данных и лэйбы для субъокон 
   IndicatorShortName(""+Label+"");
   SetIndexLabel   (0,""+Label+""+"_HTF3");
   SetIndexLabel   (1,"Up_Trend");
   SetIndexLabel   (2,"Down_Trend");
   SetIndexLabel   (3,"Straight_Trend");
   //---- 5 индикаторных буферов использованы для счёта
   IndicatorBuffers(5);
   SetIndexBuffer(0,Ind_Buffer0);
   SetIndexBuffer(1,Ind_Buffer1); 
   SetIndexBuffer(2,Ind_Buffer2); 
   SetIndexBuffer(3,Ind_Buffer3); 
   SetIndexBuffer(4,Vel_Buffer); 
   //---- установка значений индикатора, которые не будут видимы на графике
   SetIndexEmptyValue(0,EmptyValue); 
   SetIndexEmptyValue(1,EmptyValue); 
   SetIndexEmptyValue(2,EmptyValue); 
   SetIndexEmptyValue(3,EmptyValue); 
   //---- инициализация констант
   MINIMUM=Trend_Minimum*Point;
   weight=0;
   if (Smooth>1)for(int fff=1; fff<=Smooth; fff++)weight+=fff;
   NTF=TFrame_Period/Period(); 
   //---- Установка формата точности (количество знаков после десятичной точки) для визуализации значений индикатора  
   IndicatorDigits(digits());
//----------- Алерты ------------------------------------------------   
   if (TFrame_Period !=1 && TFrame_Period !=5 && TFrame_Period !=15 && TFrame_Period !=30 && TFrame_Period !=60 && TFrame_Period !=240 && TFrame_Period !=1440 && TFrame_Period != 10080)
      { 
       Alert("Chart ", Symbol(), "Параметр TimeFrame_period может быть только следующим: 1, 5, 15, 30, 60, 240, 1440, 7200, 10080.\n" +
                                 "Индикатор будет использовать текущий период графика");
       TFrame_Period=Period();
      }
   if (Period()>= TFrame_Period) 
      {
       TFrame_Period = Period();
       Alert("Параметр TimeFrame_period должен быть больше периода графика! Индикатор будет использовать текущий период графика");
      }
//-------------------------------------------------------------------- 
   // Все Time[] серии времени отсортированы в направлении убывания 
   ArrayCopySeries(TFrame_Times,MODE_TIME,Symbol(),TFrame_Period); 
   return(0); 
  } 
//+------------------------------------------------------------------+
//| HTF iteration function                                           | 
//+------------------------------------------------------------------+
int start() 
  { 
   //----+ Введение целых переменных
   int TFlimit,MaxBar,MaxBarS,bar,bar0,bar1,Dbar,MaxBarTF,TFbar,limit; 
   //----+ Введение переменных с плавающей точкой
   double Vel0,Vel1,trend,sum,price,lsum;
   //----
   //---- определение максимальных значений номеров баров в циклах
   MaxBar=Bars-1; 
   MaxBarTF=iBarShift(NULL,TFrame_Period,Time[MaxBar-1],false)-2;
   MaxBarS=iBarShift(NULL,0,TFrame_Times[MaxBarTF+1],false)-Smooth;
   
   //----
   //----+ Получение уже посчитанных баров
   //---- Поиск последнего непосчитанного бара
   if (time1!=0)
     {
       TFlimit=iBarShift(NULL,TFrame_Period,time1,false); 
       if (TFlimit<=0)
        {
         TFlimit=MaxBarTF;
         Print("Последний непосчитанный бар не найден");
         Print("Будет произведён расчёт индикатора на всех барах");
        }
     }
   else TFlimit=MaxBarTF;
   //---- Сохранение времени открытия последнего непосчитанного бара
   time1=TFrame_Times[1]; 
   //----
   //---- инициализация нуля
   if (TFlimit>=MaxBarTF)
     {
      TFlimit=MaxBarTF;
      limit=(TFlimit+1)*NTF+1;//limit=iBarShift(NULL,0,TFrame_Times[TFlimit+1],false)+1;
      for(int nnn=MaxBar;nnn>limit;nnn--)
        {
         Vel_Buffer [nnn]=EmptyValue;
         Ind_Buffer0[nnn]=EmptyValue;
         Ind_Buffer1[nnn]=EmptyValue;
         Ind_Buffer2[nnn]=EmptyValue;
         Ind_Buffer3[nnn]=EmptyValue;
        }  
     }
   else limit=(TFlimit+1)*NTF+2;//limit=iBarShift(NULL,0,TFrame_Times[TFlimit+1],true)+1;
   //---- 
 
   if (limit>MaxBarS)
     {
      for(int xxx=limit;xxx>MaxBarS;xxx--)
         {
         Vel_Buffer [xxx]=EmptyValue;
         Ind_Buffer0[xxx]=EmptyValue;
         Ind_Buffer1[xxx]=EmptyValue;
         Ind_Buffer2[xxx]=EmptyValue;
         Ind_Buffer3[xxx]=EmptyValue;
        }  
      limit=MaxBarS;
     }   
   //----+ +--------------------+
   
   //----+ ОСНОВНОЙ ЦИКЛ ВЫЧИСЛЕНИЯ ИНДИКАТОРА 
   for(TFbar=TFlimit;TFbar>=-1;TFbar--)  
      {  
        if (TFbar!=-1)bar=iBarShift(NULL,0,TFrame_Times[TFbar],false);else bar=0; 
        Vel_Buffer[bar]=INDICATOR(TFbar+1);
        if ((TFbar==0)&&(bar==0))break;
      }
   //---- линейная интерполяция отсутствующих значений  
   if (TFlimit==MaxBarTF)TFlimit--;    
   for(TFbar=TFlimit;TFbar>=-1;TFbar--) 
      {
       //---- определение точек и интервала интерполяции
       if (TFbar!=-1)bar0=iBarShift(NULL,0,TFrame_Times[TFbar],false);else bar0=0;
       bar1=iBarShift(NULL,0,TFrame_Times[TFbar+1],false);
       Dbar=bar1-bar0;
       //---- определение значений в точках интерполяции
       Vel1=Vel_Buffer[bar1];
       Vel0=Vel_Buffer[bar0];
       //---- проверка на отсутствие ошибки
       if((Vel1==0)||( Vel0==0)||(Dbar==0))
         { 
           Print("Ошибка при получении значений в точках интерполяции");
           Print("Будет произведён пересчёт индикатора на всех барах");
           return(-1);
         }
       //---- линейная интерполяция
       for(int iii=Dbar-1;iii>0;iii--) Vel_Buffer[bar0+iii]=Vel1+(Vel0-Vel1)*(Dbar-iii)/Dbar;
       if ((TFbar==0)&&(bar0==0))break;
      } 
   //----  
   //---- LWMA сглаживание полученного мувинга 
   if (Smooth> 1)
    {
     sum=0;
     lsum=0;
     bar=limit+Smooth;
     for(int sss=1;sss<=Smooth;sss++,bar--)
      {
      price=Vel_Buffer[bar];
      sum+=price*sss;
      lsum+=price;
      }
     sss=Smooth;
     for(bar=limit;bar>=0;bar--)   
      {
       Ind_Buffer0[bar]=sum/weight;
       if(bar==0) break;
       price=Vel_Buffer[bar];
       sum=sum-lsum+price*Smooth;
       lsum-=Vel_Buffer[bar+sss];
       lsum+=price;
      }
    }
   //----  
   if (Smooth<=1)for(bar=limit;bar>=0;bar--)Ind_Buffer0[bar]=Vel_Buffer [bar];  
      
   //---- расчёт индикаторов тренда
   if (Trend_Visible==true)
      {
        //---- инициализация нуля
        for(int kkk=limit;kkk>=0;kkk--) 
          {
            Ind_Buffer1[kkk]=EmptyValue;
            Ind_Buffer2[kkk]=EmptyValue;
            Ind_Buffer3[kkk]=EmptyValue;
          }
        //----  
        if (TFlimit==MaxBarTF-1)TFlimit--; 
       for(TFbar=TFlimit+1;TFbar>=-1;TFbar--) 
          {
           if (TFbar!=-1)bar0=iBarShift(NULL,0,TFrame_Times[TFbar],false);else bar0=0;
           bar1=iBarShift(NULL,0,TFrame_Times[TFbar+1],false);
           //---- трёхцветный код
          trend=Ind_Buffer0[bar0]-Ind_Buffer0[bar1];
          if (MathAbs(trend)<MINIMUM)trend=0;
          if (trend>0)Ind_Buffer1[bar0]=Ind_Buffer0[bar0];
          else if (trend<0)Ind_Buffer2[bar0]=Ind_Buffer0[bar0];
          else Ind_Buffer3[bar0]=Ind_Buffer0[bar0];
          if ((TFbar==0)&&(bar0==0))break;
          //---- 
         }
      } 
   //---- завершение вычислений значений индикатора
    return(0);
  }
//+--------------------------------------------------------------------+

