Как получить номер бара по времени входа в позицию?

 

Приветствую!

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

В MQL4 такая функция был (iBarShift), а в 5-й версии её, судя по всему, нет.

Подскажите, пожалуйста, её просто переименовали или совсем убрали?  Может быть есть альтернативные функции, которые делают то, что мне нужно?

 
varenich:

Приветствую!

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

В MQL4 такая функция был (iBarShift), а в 5-й версии её, судя по всему, нет.

Подскажите, пожалуйста, её просто переименовали или совсем убрали?  Может быть есть альтернативные функции, которые делают то, что мне нужно?

//+------------------------------------------------------------------+
int GetBarShift(string symbol_name,ENUM_TIMEFRAMES timeframe,datetime time) {
   if(time<0) return(-1);
   //---
   datetime array[], time0;
   if(CopyTime(symbol_name,timeframe,0,1,array)<0) return(-1);
   time0=array[0];
   if(CopyTime(symbol_name,timeframe,time0,time,array)<0) return(-1);
   datetime temptime=GetTime(symbol_name,timeframe,ArraySize(array)-1);
   if(array[0]==temptime && temptime<=time) return(ArraySize(array)-1);
   else return(ArraySize(array));
}
//+------------------------------------------------------------------+
 
Artyom Trishkin:
//+------------------------------------------------------------------+
int GetBarShift(string symbol_name,ENUM_TIMEFRAMES timeframe,datetime time) {
   if(time<0) return(-1);
   //---
   datetime array[], time0;
   if(CopyTime(symbol_name,timeframe,0,1,array)<0) return(-1);
   time0=array[0];
   if(CopyTime(symbol_name,timeframe,time0,time,array)<0) return(-1);
   datetime temptime=GetTime(symbol_name,timeframe,ArraySize(array)-1);
   if(array[0]==temptime && temptime<=time) return(ArraySize(array)-1);
   else return(ArraySize(array));
}
//+------------------------------------------------------------------+
Это очень дорого и не полностью. Оптимально
int iBarShift( const string Symb, const ENUM_TIMEFRAMES TimeFrame, const datetime time )
{
  int Res = -1;
  datetime LastBar;

   if (::SeriesInfoInteger(Symb, TimeFrame, ::SERIES_LASTBAR_DATE, LastBar))
   {
      if (time > LastBar)  
        Res = 0;
      else
      {
        const int Shift = ::Bars(Symb, TimeFrame, time, LastBar);
        
        if (Shift > 0)
          Res = Shift - 1;
      }
    }
  
  return(Res);
}
 
fxsaber:
Это очень дорого и не полностью. Оптимально
Чудесно. Благодарю, возьмём на вооружение.
 

Привет!

Спасибо всем за помощь!

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

Всё сработало.

Еще раз спасибо тем, кто откликнулся. 

 
varenich:

Привет!

Спасибо всем за помощь!

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

Всё сработало.

Еще раз спасибо тем, кто откликнулся. 

Bars() возвращает количество баров, но вот смещение не всегда показывает верно. Проверьте.
 
Хм... Век живи - век учись... Я использовал бинарный поиск... А оказывается, его можно заменить такой хорошей функцией (если ИНОГДА возникает ошибка в смещении - это просто надо иметь ввиду, и корректировать возвращаемое значение путем полного перебора в этом случае)
 
Нашел еще один способ - через стандартный класс CiTime: https://www.mql5.com/ru/docs/standardlibrary/technicalindicators/timeseries/citime/citimegetdata
Документация по MQL5: Стандартная библиотека / Классы для работы с индикаторами / Таймсерии / CiTime / GetData
Документация по MQL5: Стандартная библиотека / Классы для работы с индикаторами / Таймсерии / CiTime / GetData
  • www.mql5.com
Стандартная библиотека / Классы для работы с индикаторами / Таймсерии / CiTime / GetData - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
fxsaber:
Это очень дорого и не полностью. Оптимально
int iBarShift( const string Symb, const ENUM_TIMEFRAMES TimeFrame, const datetime time )
{
  int Res = -1;
  datetime LastBar;

   if (::SeriesInfoInteger(Symb, TimeFrame, ::SERIES_LASTBAR_DATE, LastBar))
   {
      if (time > LastBar)  
        Res = 0;
      else
      {
        const int Shift = ::Bars(Symb, TimeFrame, time, LastBar);
        
        if (Shift > 0)
          Res = Shift - 1;
      }
    }
  
  return(Res);
}
Не совсем корректно. В условии time > LastBar должно быть >= . А вообще, спасибо.
 

Модифицировал функцию. Убрал ошибку для случая, когда time = времени открытия бара. Добавил возможность указать порядок нумерации. Добавил возврат времени открытия свечи:

Если есть вариант проще или есть ошибки - напишите, пожалуйста.
 

 
Alexey Kozitsyn:
Если есть вариант проще или есть ошибки - напишите, пожалуйста.

Исправлена ошибка при старте терминала:

//+------------------------------------------------------------------+
//| Номер бара по времени                                            |
//+------------------------------------------------------------------+
int iBarShift( const string symbol,               // Символ
              const ENUM_TIMEFRAMES timeframe,    // Период
              const datetime time,                // Время для нахождения номера бара
              const bool asSeries,                // Флаг порядка нумерации
              datetime &barOpenTime               // Время открытия бара (out)
             )
  {
//--- Искомый номер
   int res=WRONG_VALUE;
//--- Время открытия последнего бара
   datetime lastBar;
//--- Получаем время открытия последнего бара по символу/периоду
   if(SeriesInfoInteger(symbol,timeframe,SERIES_LASTBAR_DATE,lastBar))
     {
      //--- Количество баров в истории
      const int bars=Bars(symbol,timeframe);
      const bool sync = (bool)SeriesInfoInteger( symbol, timeframe, SERIES_SYNCHRONIZED );
      if( bars <= 0 || !sync )                    // Если функция не сработала|история не синхронизирована
         return( res );                           // Возвращаем ложное значение
      //--- Проверка на нулевой бар
      if( time >= lastBar )                       // Если время не больше времени открытия последней свечи
         res =( asSeries ) ? 0 : bars-1;          // Номер последнего бара
      else                                        // Если время меньше времени открытия последней свечи
        {
         //--- Получаем количество баров в истории до времени открытия свечи time
         int shift=Bars(symbol,timeframe,time,lastBar);
         //--- Определяем время открытия бара для времени time
         barOpenTime=GetBarOpenTime(symbol,timeframe,time);
         //--- Проверяем корректность данных
         if(barOpenTime>0 && shift>0) // Если время корректно и количество баров найдено
           {
            //--- Проверяем, совпадает ли время открытия бара с временем time
            shift=(barOpenTime==time) ? shift-1 : shift;   // Изменяем сдвиг при необходимости
            //--- Определяем номер бара в зависимости от индексации баров
            res=(asSeries) ? shift : bars-shift-1;
           }
        }
     }
   else                         // Если значение не получено - ошибка
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": Время открытия последнего бара по "+symbol+
            " "+EnumToString(timeframe)+" не получено!");
//--- Возвращаем номер бара
   return( res );
  }
//+------------------------------------------------------------------+
//| Получаем время открытия свечи по времени time                    |
//+------------------------------------------------------------------+
datetime GetBarOpenTime( const string symbol,              // Символ
                        const ENUM_TIMEFRAMES timeframe,   // Период
                        const datetime time                // Момент времени
                        )
  {
//--- Массив - приемник
   datetime t[1];
//--- Получаем время открытия бара
   if( CopyTime( symbol,timeframe, time, 1, t ) == 1 )     // Если время получено
      return( t[ 0 ] );                                    // Возвращаем время открытия бара
   else                                                    // Если время не получено
     {
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": время открытия свечи для момента "+TimeToString(time,TIME_DATE|TIME_SECONDS)+
            " не получено!");                              // Ошибка
      return(0);                                           // Возвращаем ошибочное значение
     }
  }


 

Причина обращения: