И всё-таки есть ли полный аналог функции iBarShift для MT5 или как его заменить?

 

Поиск по статьям и форуму дал несколько вариантов, но все они имеют одну проблему. После нажатия на кнопку "обновить" контекстного меню графика, все значения смещаются вперёд. На скринах пример.

  после обновить -> 

 

Буквально с первых дней развития MT5 была написана весьма полезная статья: https://www.mql5.com/ru/articles/81 -- в ней показаны аналоги всех функций MQL4 и как их в MQL5 корректно заменить

Переход с MQL4 на MQL5
Переход с MQL4 на MQL5
  • 2010.05.11
  • Sergey Pavlov
  • www.mql5.com
Данная статья, построенная в форме справочника по функциям MQL4, призвана помочь переходу с MQL4 на MQL5. Для каждой функции языка MQL4 приведено описание и представлен способ ее реализации на MQL5, что позволит вам значительно ускорить перевод своих программ с MQL4 на MQL5. Для удобства функции разбиты на группы, как в документации по MQL4.
 
Andrey F. Zelinsky:

Буквально с первых дней развития MT5 была написана весьма полезная статья: https://www.mql5.com/ru/articles/81 -- в ней показаны аналоги всех функций MQL4 и как их в MQL5 корректно заменить

Я в курсе об этой статье, но как уже писал выше, всё что тут (на сайте) можно явно найти не работает в описанной ситуации.

Собственно вот код используемого аналога, результаты ошибок заменил на 0 вместо -1, мне так нужно:

int iBarShift(datetime time,bool exact=false) { datetime LastBar;
   if(!SeriesInfoInteger(_Symbol,_Period,SERIES_LASTBAR_DATE,LastBar)) { datetime opentimelastbar[1]; if(CopyTime(_Symbol,_Period,0,1,opentimelastbar)==1) LastBar=opentimelastbar[0]; else return(0); }
   if(time>LastBar) return(0);
   int shift=Bars(_Symbol,_Period,time,LastBar); datetime checkcandle[1];
   if(CopyTime(_Symbol,_Period,time,1,checkcandle)==1) {
      if(checkcandle[0]==time) return(shift-1); else if(exact && time>checkcandle[0]+PeriodSeconds(_Period)) return(0); else return(shift);}
return(0); }
 

Как-то fxsaber показал замечательное решение, которое уже встроено в МТ5. Это использование перегрузки функции Bars(). Чтобы найти индекс бара по времени, достаточно знать время открытия бара с индексом 1:

datetime timeOfFirstBar = ....; // Получить через CopyTime или другими способами
datetime knownTime = ...; // Известное время, для которого требуется найти индекс бара
int barIndex = Bars(Symbol(), Period(), knownTime, timeOfFirstBar);

Единственное, что требуется учесть, так это тот факт, что knownTime должно попадать четко на время открытия бара (или быть чуть "правее" него). Иначе результат будет на 1 меньше.
 

 
Ihor Herasko:

Как-то fxsaber показал замечательное решение, которое уже встроено в МТ5. Это использование перегрузки функции Bars(). Чтобы найти индекс бара по времени, достаточно знать время открытия бара с индексом 1:

datetime timeOfFirstBar = ....; // Получить через CopyTime или другими способами
datetime knownTime = ...; // Известное время, для которого требуется найти индекс бара
int barIndex = Bars(Symbol(), Period(), knownTime, timeOfFirstBar);

Единственное, что требуется учесть, так это тот факт, что knownTime должно попадать четко на время открытия бара (или быть чуть "правее" него). Иначе результат будет на 1 меньше.
 

Спасибо, этот вариант я видел среди форумных тем, как раз пробую...
 
Ihor Herasko:

Как-то fxsaber показал замечательное решение, которое уже встроено в МТ5. Это использование перегрузки функции Bars(). Чтобы найти индекс бара по времени, достаточно знать время открытия бара с индексом 1:

datetime timeOfFirstBar = ....; // Получить через CopyTime или другими способами
datetime knownTime = ...; // Известное время, для которого требуется найти индекс бара
int barIndex = Bars(Symbol(), Period(), knownTime, timeOfFirstBar);

Единственное, что требуется учесть, так это тот факт, что knownTime должно попадать четко на время открытия бара (или быть чуть "правее" него). Иначе результат будет на 1 меньше.
 

Прошу прощения. Имел в виду чуть "левее" по графику.
 

Можно пример из документации подправить под свои нужды.


#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//---- plot Numeration
#property indicator_label1  "Numeration"
#property indicator_type1   DRAW_LINE
#property indicator_color1  CLR_NONE
//--- indicator buffers
double         NumerationBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,NumerationBuffer,INDICATOR_DATA);
//--- установим индексацию для буфера как в таймсерии
   ArraySetAsSeries(NumerationBuffer,true);
//--- установим точность отборажения в DataWindow
   IndicatorSetInteger(INDICATOR_DIGITS,0);
//--- как будет выглядеть в DataWindow имя индикаторного массива
   PlotIndexSetString(0,PLOT_LABEL,"Bar #");
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---  будем хранить время открытия текущего нулевого бара
   static datetime currentBarTimeOpen=0;
//--- перевернем доступ к массиву time[] - сделаем как в таймсерии
   ArraySetAsSeries(time,true);
//--- если время нулевого бара отличается от того, что мы храним
   if(currentBarTimeOpen!=time[0])
     {
     //--- пронумеруем все бары от текущего момента вглубь графика
      for(int i=rates_total-1;i>=0;i--) NumerationBuffer[i]=i;
      currentBarTimeOpen=time[0];
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
Документация по MQL5: Операции с массивами / ArraySetAsSeries
Документация по MQL5: Операции с массивами / ArraySetAsSeries
  • www.mql5.com
Операции с массивами / ArraySetAsSeries - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 

Вот же. От fxsaber:

//+------------------------------------------------------------------+
int GetBarShift(const string symbol_name, const ENUM_TIMEFRAMES timeframe, const datetime time) {
   int res=-1;
   datetime last_bar;
   if(SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE,last_bar)) {
      if(time>last_bar) res=0;
      else {
         const int shift=Bars(symbol_name,timeframe,time,last_bar);
         if(shift>0) res=shift-1;
         }
      }
   return(res);
}
//+------------------------------------------------------------------+
 
Artyom Trishkin:

Вот же. От fxsaber:

//+------------------------------------------------------------------+
int GetBarShift(const string symbol_name, const ENUM_TIMEFRAMES timeframe, const datetime time) {
   int res=-1;
   datetime last_bar;
   if(SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE,last_bar)) {
      if(time>last_bar) res=0;
      else {
         const int shift=Bars(symbol_name,timeframe,time,last_bar);
         if(shift>0) res=shift-1;
         }
      }
   return(res);
}
//+------------------------------------------------------------------+
У вас нет параметра exact, кроме того данная конструкция напоминает приведённый мною выше кусок текущего кода, который не работает в описанной ситуации.
 
Alexey Viktorov:

Можно пример из документации подправить под свои нужды.


#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//---- plot Numeration
#property indicator_label1  "Numeration"
#property indicator_type1   DRAW_LINE
#property indicator_color1  CLR_NONE
//--- indicator buffers
double         NumerationBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,NumerationBuffer,INDICATOR_DATA);
//--- установим индексацию для буфера как в таймсерии
   ArraySetAsSeries(NumerationBuffer,true);
//--- установим точность отборажения в DataWindow
   IndicatorSetInteger(INDICATOR_DIGITS,0);
//--- как будет выглядеть в DataWindow имя индикаторного массива
   PlotIndexSetString(0,PLOT_LABEL,"Bar #");
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---  будем хранить время открытия текущего нулевого бара
   static datetime currentBarTimeOpen=0;
//--- перевернем доступ к массиву time[] - сделаем как в таймсерии
   ArraySetAsSeries(time,true);
//--- если время нулевого бара отличается от того, что мы храним
   if(currentBarTimeOpen!=time[0])
     {
     //--- пронумеруем все бары от текущего момента вглубь графика
      for(int i=rates_total-1;i>=0;i--) NumerationBuffer[i]=i;
      currentBarTimeOpen=time[0];
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

Не совсем понял, как данный пример поможет в нахождении номера бара по времени? Не проще ли тогда этим циклом по массиву time найти номер нужного бара? Только вот такая программа будет работать очень медленно...

 
Sergey Efimenko:

Не совсем понял, как данный пример поможет в нахождении номера бара по времени? Не проще ли тогда этим циклом по массиву time найти номер нужного бара? Только вот такая программа будет работать очень медленно...

А просто не надо не трезвым подходить к компу. Тогда и советов таких будет меньше.

Или чтобы понять нужно тоже нетрезвым читать:))))))))

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