Способ найти бар на другом таймфреме

 
Нужно решить к примеру такую задачу - индикатор MACD к примеру на M15 идет вниз. Эта пятнашка находится в прошлой пятнице. Нужно определить поворачивает ли MACD на H4 в той же самой пятнице. Количество баров [i] в данном случае разное. Как это можно сделать? Подскажите хотя бы функцию или переменную.
 
посмотрите, как находится бар на другом таймфрейме в примере, соответствующем функции ArraBsearch
 
Спасибо.
А можно при этом использовать проконверченный график 3-х часовки?
То есть можно ли указать PERIOD_H3?
 
А вот в тему индикатор, но не могу найти ошибку, подвешивает МТ:
//+------------------------------------------------------------------+
//|                                                   PriceChanel_ut.mq4  |
//|                                        Copyright © 2005, Profi_R  |
//|                                                                                    |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, Profi_R"
#property link  

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 DodgerBlue
#property indicator_color2 DodgerBlue
//---- input parameters
extern int       Range=6;
extern int       timeFrame=1440;
//---- buffers
double UpBuffer[];
double DnBuffer[];
//---- 

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   string PeriodName;  //хранит имя таймфрейма
   switch(timeFrame) // присвоение значения TimeFrame в зависимости от выбранного в параметрах
   {
      case 1     : timeFrame=PERIOD_M1;  break; //в том же порядке, что и кнопки на панели
      case 5     : timeFrame=PERIOD_M5;  break;
      case 15    : timeFrame=PERIOD_M15; break;
      case 30    : timeFrame=PERIOD_M30; break;
      case 60    : timeFrame=PERIOD_H1;  break;
      case 240   : timeFrame=PERIOD_H4;  break;
      case 1440  : timeFrame=PERIOD_D1;  break;
      case 10080 : timeFrame=PERIOD_W1;  break;
      case 43200 : timeFrame=PERIOD_MN1; break;
      default    : timeFrame=Period();   break;
   }
   switch(timeFrame) // получение имени таймфрейма
   {
      case PERIOD_M1  : PeriodName="M1";  break;
      case PERIOD_M5  : PeriodName="M5";  break;
      case PERIOD_M15 : PeriodName="M15"; break;
      case PERIOD_M30 : PeriodName="M30"; break;
      case PERIOD_H1  : PeriodName="H1";  break;
      case PERIOD_H4  : PeriodName="H4";  break;
      case PERIOD_D1  : PeriodName="D1";  break;
      case PERIOD_W1  : PeriodName="W1";  break;
      case PERIOD_MN1 : PeriodName="MN1"; break;
   }
   if (timeFrame<Period()) //нельзя прорисовать индикатор меньшего таймфрейма на большем
   {
      SetIndexDrawBegin(0,Bars);  //очистка от мусора
      SetIndexDrawBegin(1,Bars);
      Alert("Требуется график с меньшим таймфреймом");
      return(0);
   }

//---- indicators
   IndicatorBuffers(2);
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,UpBuffer);
   SetIndexLabel(0,"Up Channel ("+PeriodName+","+Range+")");
   SetIndexDrawBegin(0,0);
   
   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(1,UpBuffer);
   SetIndexLabel(1,"Down Channel ("+PeriodName+","+Range+")");
   SetIndexDrawBegin(1,0);

//---- name for DataWindow and indicator subwindow label
   string short_name; //обявление переменной short_name типа "строковый"
   short_name="PriceChannel("+PeriodName+","+Range+")";
   //для отображения на графике присвоим индикатору краткое наименование
   IndicatorShortName(short_name);
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int cb;
   int counted_bars=IndicatorCounted();
//---- 
   for(cb=Bars-1-counted_bars;cb>=0;cb--)
   {
      UpBuffer[cb]=iCustom(NULL,timeFrame,"PChannel",Range,0,CorrespBar(cb,timeFrame));
      DnBuffer[cb]=iCustom(NULL,timeFrame,"PChannel",Range,1,CorrespBar(cb,timeFrame));
   }   
//----
   return(0);
  }
//+------------------------------------------------------------------+

//**********************************************************************************//
// Функция возвращает индекс бара на большем таймфрейме соответсвующий переданному  //
//**********************************************************************************//
int CorrespBar(int cb, int tf)
  {
//---- 
   int i,rez;
   for(i=0;i<=cb;i++)
   {
      if(Time[cb]>=iTime(Symbol(),tf,i))
      {
         rez=i;
         break;
      }
   }
//----
   return(rez);
  }
//+------------------------------------------------------------------+



пытался вывести контрольные значения в лог, но лог создается просто гигантским. Ошибка где-то в функции, потому что если в старте закоментировать вычисление буферов и вместо них сделать вывод номеров бара на текущем и большем таймфрейме, то тормоза остаются, да и значения неверные (те что возвращает функция)

 
ошибки вроде и нет. при первоначальном запуске (в случае counted_bars==0) у Вас очень долго считаются вызовы CorrespBar. чтобы такого не было, мы и сделали функцию ArrayBsearch
кстати, в приведённом коде совершенно неоправдан вызов iTime. лучше использовать функцию ArrayCopySeries и доступаться к элементам массива, причём массив объявить на глобальном уровне (хотя можно и параметром передать) и скопировать его перед главным циклом
 
ошибки вроде и нет.


а результат не только задерживается , но к тому же и неверен (верхней линии вообще не видно, а нижняя рисуется выше свечек (может я не правильно понял 0 и 1 в iCustom(NULL,timeFrame,"PChannel",Range,0,CorrespBar(cb,timeFrame)) - это индексы буферов PChannel?

при первоначальном запуске (в случае counted_bars==0) у Вас очень долго считаются вызовы CorrespBar. чтобы такого не было, мы и сделали функцию ArrayBsearch кстати,


с массивами тоже работает не ахти, да ArrayBsearch будет искать совпадающую по времени, а если не найдет таковую, то вовзвратит ближайшею к последней, а не ту в интервал которой входит наша свечка, т.е. нужна будет дополнительная обработка (Ранее тема работы с массивами уже поднималась "Предложение по улучшению." , но этот вариант неэффективен потому что: например я хочу отрисовать показания индикатора с дневок на получасовках, у меня есть история по дневкам за 20 лет, по получасовкам за 2 года (в одной дневке содержится 48 получасовок т.е. максимум необходимой дневной истории составляет 2 года / 48 = 0,041(7) года, а я буду держать массив с 20 летней историей, а процент использования массива составит 0,208(3) %), да и последующая обработка тоже не прибавит резвости расчетам. Еще тогда предлагался вариант функции возвращающей индекс соответсвующей свечи с другого таймфрейма, а по нему можно было бы узнать и High и Low и остальные параметры, но вы почему-то предпочли добавить несколько функций, как видно не решивший проблему. А вариант индикатора с использованием массива и поиска по нему у меня есть , но тоже жутко тормозной.

в приведённом коде совершенно неоправдан вызов iTime.


???
 
Одну ошибку я нашел:
SetIndexBuffer(0,UpBuffer);
SetIndexBuffer(1,UpBuffer); - здесь должно быть DnBuffer
 
Вроде заработало , но не может же быть что все дело было только в этом? И быстрее чем с массивами, правда все равно очень тормозно.
 
Оптимизировал, так гораздо быстрее:
//+------------------------------------------------------------------+
//|                                               PriceChanel_ut.mq4 |
//|                                        Copyright © 2005, Profi_R |
//|                                               |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, Profi_R"
#property link      ""

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 DodgerBlue
#property indicator_color2 DodgerBlue
//---- input parameters
extern int       Range=6;
extern int       timeFrame=1440;
//---- buffers
double UpBuffer[];
double DnBuffer[];
//---- 
datetime bigtftime;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   datetime bigtftime=Time[Bars-1];
   string PeriodName;  //хранит имя таймфрейма
   switch(timeFrame) // присвоение значения TimeFrame в зависимости от выбранного в параметрах
   {
      case 1     : timeFrame=PERIOD_M1;  break; //в том же порядке, что и кнопки на панели
      case 5     : timeFrame=PERIOD_M5;  break;
      case 15    : timeFrame=PERIOD_M15; break;
      case 30    : timeFrame=PERIOD_M30; break;
      case 60    : timeFrame=PERIOD_H1;  break;
      case 240   : timeFrame=PERIOD_H4;  break;
      case 1440  : timeFrame=PERIOD_D1;  break;
      case 10080 : timeFrame=PERIOD_W1;  break;
      case 43200 : timeFrame=PERIOD_MN1; break;
      default    : timeFrame=Period();   break;
   }
   switch(timeFrame) // получение имени таймфрейма
   {
      case PERIOD_M1  : PeriodName="M1";  break;
      case PERIOD_M5  : PeriodName="M5";  break;
      case PERIOD_M15 : PeriodName="M15"; break;
      case PERIOD_M30 : PeriodName="M30"; break;
      case PERIOD_H1  : PeriodName="H1";  break;
      case PERIOD_H4  : PeriodName="H4";  break;
      case PERIOD_D1  : PeriodName="D1";  break;
      case PERIOD_W1  : PeriodName="W1";  break;
      case PERIOD_MN1 : PeriodName="MN1"; break;
   }
   if (timeFrame<Period()) //нельзя прорисовать индикатор меньшего таймфрейма на большем
   {
      SetIndexDrawBegin(0,Bars);  //очистка от мусора
      SetIndexDrawBegin(1,Bars);
      Alert("Требуется график с меньшим таймфреймом");
      return(0);
   }

//---- indicators
   IndicatorBuffers(2);
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,UpBuffer);
   SetIndexLabel(0,"Up Channel ("+PeriodName+","+Range+")");
   SetIndexDrawBegin(0,0);
   
   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(1,DnBuffer);
   SetIndexLabel(1,"Down Channel ("+PeriodName+","+Range+")");
   SetIndexDrawBegin(1,0);

//---- name for DataWindow and indicator subwindow label
   string short_name; //обявление переменной short_name типа "строковый"
   short_name="PriceChannel("+PeriodName+","+Range+")";
   //для отображения на графике присвоим индикатору краткое наименование
   IndicatorShortName(short_name);
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int cb;
   int counted_bars=IndicatorCounted();
//---- 
   for(cb=Bars-1-counted_bars;cb>=0;cb--)
   {
      if(timeFrame>Period())
      {
         if(Time[cb]<bigtftime)
         {
            UpBuffer[cb]=UpBuffer[cb+1];
            DnBuffer[cb]=DnBuffer[cb+1];
         }
         else
         {
            UpBuffer[cb]=iCustom(NULL,timeFrame,"PChannel",Range,0,CorrespBar(cb,timeFrame));
            DnBuffer[cb]=iCustom(NULL,timeFrame,"PChannel",Range,1,CorrespBar(cb,timeFrame));
         }
      }
      else
      {
         UpBuffer[cb]=iCustom(NULL,0,"PChannel",Range,0,cb);
         DnBuffer[cb]=iCustom(NULL,0,"PChannel",Range,1,cb);
      }
   }   
//----
   return(0);
  }
//+------------------------------------------------------------------+

//**********************************************************************************//
// Функция возвращает индекс бара на большем таймфрейме соответсвующий переданному  //
//**********************************************************************************//
int CorrespBar(int cb, int tf)
  {
//---- 
   int i,rez;
   for(i=0;i<=Bars-1;i++)
   {
      if(Time[cb]>=iTime(Symbol(),tf,i))
      {
         rez=i;
         bigtftime=iTime(Symbol(),tf,i-1);
         break;
      }
   }
//----
   return(rez);
  }
//+------------------------------------------------------------------+
 
Пересмотрел ранее написанный (с помощью Романа) вариант индикатора, использующий массивы, действительно с маленькими таймфреймами он заработал гораздо быстрее, с большими не уступает вышеприведенным (а может и быстрее, оценивал на "глазок") :) вот его код:
//+------------------------------------------------------------------+
//| PChannel_m.mq4                                                   |
//+------------------------------------------------------------------+

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 DodgerBlue
#property indicator_color2 DodgerBlue
#property indicator_color3 DodgerBlue

extern int Range=6;
extern int TimeFrame=1440;

double UpBuffer[];
double DnBuffer[];
double MdBuffer[];

int i;  //счетчик
string PeriodName;  //хранит имя таймфрейма

int init()
{
string short_name;

SetIndexStyle(0,DRAW_LINE,1,2);
SetIndexBuffer(0,UpBuffer);
SetIndexLabel(0,"Up Channel ("+Range+")");
SetIndexDrawBegin(0,0);

SetIndexStyle(1,DRAW_LINE,1,2);
SetIndexBuffer(1,DnBuffer);
SetIndexLabel(1,"Down Channel ("+Range+")");
SetIndexDrawBegin(1,0);

SetIndexStyle(2,DRAW_LINE,2);
SetIndexBuffer(2,MdBuffer);
SetIndexLabel(2,"Middle Channel");
SetIndexDrawBegin(2,0);

IndicatorShortName(short_name);

switch(TimeFrame) // присвоение значения TimeFrame в зависимости от выбранного в параметрах
  {
  case 1    : TimeFrame=PERIOD_M1;  break; //в том же порядке, что и кнопки на панели
  case 5    : TimeFrame=PERIOD_M5;  break;
  case 15   : TimeFrame=PERIOD_M15; break;
  case 30   : TimeFrame=PERIOD_M30; break;
  case 60   : TimeFrame=PERIOD_H1;  break;
  case 240  : TimeFrame=PERIOD_H4;  break;
  case 1440 : TimeFrame=PERIOD_D1;  break;
  case 10080: TimeFrame=PERIOD_W1;  break;
  case 43200: TimeFrame=PERIOD_MN1; break;
  default   : TimeFrame=Period();   break;
  }

switch(TimeFrame) // получение имени таймфрейма
  {
  case PERIOD_M1    : PeriodName="M1";  break;
  case PERIOD_M5    : PeriodName="M5";  break;
  case PERIOD_M15   : PeriodName="M15"; break;
  case PERIOD_M30   : PeriodName="M30"; break;
  case PERIOD_H1    : PeriodName="H1";  break;
  case PERIOD_H4    : PeriodName="H4";  break;
  case PERIOD_D1    : PeriodName="D1";  break;
  case PERIOD_W1    : PeriodName="W1";  break;
  case PERIOD_MN1   : PeriodName="MN1"; break;
  }
short_name="PriceChannel("+PeriodName+","+Range+")";
return(0);
}

int start()
{
int i,counted_bars=IndicatorCounted();
//---- initial zero
   if(counted_bars<1)
      for(i=1;i<Bars;i++)
      {
         DnBuffer[i]=0.0;
         UpBuffer[i]=0.0;
         MdBuffer[i]=0.0;      
      }
//----
datetime TimeArray[];
double LowArray[],HighArray[];
int y=0;  //счетчик баров другого таймфрейма

if (TimeFrame<Period()) //нельзя прорисовать индикатор меньшего таймфрейма на большем
  {
  SetIndexDrawBegin(0,Bars);  //очистка от мусора
  SetIndexDrawBegin(1,Bars);
  SetIndexDrawBegin(2,Bars);
  Comment("Требуется график с меньшим таймфреймом");
  return(0);
  }
//получение времени начала каждого бара с другого таймфрейма
ArrayCopySeries(TimeArray,MODE_TIME,Symbol(),TimeFrame);
//получение всех Low оттуда же
ArrayCopySeries(LowArray,MODE_LOW,Symbol(),TimeFrame);
//аналогично High
ArrayCopySeries(HighArray,MODE_HIGH,Symbol(),TimeFrame);

for(i=0,y=0;i<Bars-counted_bars;i++)
  {
  //если время начала бара нашего таймфрейма меньше времени начала бара другого таймфрейма, 
  //то переходим к следующему бару на другом таймфрейме (отсчет в обратном порядке)
  if (Time[i]<TimeArray[y]) y++;
  //|выбирает бар с минимальным/максимальным значением с другого таймфрейма,
  DnBuffer[i]=LowArray[Lowest(NULL,TimeFrame,MODE_LOW,Range,y)];
  //|и по номеру бара вытаскивает соответствующее значение из массивов
  UpBuffer[i]=HighArray[Highest(NULL,TimeFrame,MODE_HIGH,Range,y)];
  //|LowArray и HighArray
  MdBuffer[i]=(UpBuffer[i]+DnBuffer[i])/2;
  }
Comment("PriceChannel по т-ф ", PeriodName, " с периодом ", Range);
return(0);
}