Скачать MetaTrader 5

Time[0] во время смены таймфрейма

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
ivan
505
ivan  

Я вижу, что иногда, в короткое время после смены таймфрейма, Time[0] меняется. Причём 100% до появления нового нулевого бара (например, переключаем на 15-минутки. до наступления нового 15-минутного бара еще далеко). То есть, при смене таймфрейма, история, соответствующая новому периоду, подгружается или пересчитывается, причем таким образом, что Time[0] не является временем открытия текущего бара, а просто является первым элементом массива. И только спустя непродолжительное время Time[0] "стабилизируется" и  становится настоящим временем открытия текущего бара. Это очень неудобно, например, если программа хочет засечь бар, на котором она начала работать на новом таймфрейме - как его засекать-то, если начальные значения времени неадекватны? Кто-нибудь сталкивался с подобным? Код не выкладываю, т.к., во-первых, он элементарен, а во-вторых, проблема возникает спорадически, видимо, в зависимости от подгрузки истории при переключении таймфрейма. 

Если описанная проблема полностью исключена по построению mt4, буду признателен, если это подтвердит кто-то из модераторов.

 

Vitalie Postolache
12318
Vitalie Postolache  
iTime(NULL,timeframe,0) будет правильней, если не хочется таких выкрутасов, всегда показывает время открытия свечи именно того ТФ, который нужен, неважно на какой ТФ перескочил график.
ivan
505
ivan  

Спасибо, но это тоже не работает: смотрите, прилагаю простейший код - индикатор - он делает 2 вещи:

1. Записывает время первого тика time0 (в момент инициализации индикатора на любом таймфрейме)

2. Вычисляет и отображает  комментарием сдвиг найденного времени TheShift=iBarShift(NULL,0,time0,false); опция false означает, насколько я понимаю, что будет найден бар, время начала которого наиболее близко к time0. 

В норме, при переключении на новый таймфрейм должно быть TheShift=0 или 1 и только спустя много времени TheShift=2,3 и т.д. когда начнут приходить новые бары. Но я вижу, что TheShift может скакнуть и на 25 и на 88, и т.д. 

Такая вот .. вещь.

 

//+------------------------------------------------------------------+
//|                                          TimeFrameSwitchTest.mq4 |
//|                                                          qomment |
//|                             https://www.mql5.com/ru/users/qomment |
//+------------------------------------------------------------------+
#property copyright "qomment"
#property link      "https://www.mql5.com/ru/users/qomment"
#property version   "1.00"
#property strict
#property indicator_chart_window

int OnCalculateCounter=0; // считаем тики
datetime time0; // время первого тика
bool time0switch=0; // переключатель
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   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[])
  {
  
  if(!time0switch)
  {
  ResetLastError();
  time0=iTime(NULL,0,0);
  if(!GetLastError())
  time0switch=1;  
  }
  
  if(time0switch)
  {
  int TheShift=iBarShift(NULL,0,time0,false);
  if(TheShift!=-1)
  Comment("TimeFrame=",Period()," OnCalculateCounter=",OnCalculateCounter," TheShift=",TheShift);
  }

  OnCalculateCounter++;
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

  }
//+------------------------------------------------------------------+
keekkenen
1135
keekkenen  

TheShift всегда будет 0, потому что в time0 будет всегда (в момент вычисления TheShift) время текущего бара

 iBarShift будет возвращать 0, т.к. бар со временем time0 всегда будет находиться и это 0-й бар

Ihor Herasko
9631
Ihor Herasko  
qomment:

1. Записывает время первого тика time0 (в момент инициализации индикатора на любом таймфрейме) 

Нужно брать не любой таймфрейм, а один конкретный, т. е. в iTime должен быть не 0 на месте таймфрейма, а константное значение, используемое при работе индикатора на любом таймфрейме.
ivan
505
ivan  
keekkenen:

TheShift всегда будет 0, потому что в time0 будет всегда (в момент вычисления TheShift) время текущего бара

 iBarShift будет возвращать 0, т.к. бар со временем time0 всегда будет находиться и это 0-й бар


Нет. В том то и дело. Попробуйте код и убедитесь. Только проблема будет возникать не всегда, скажем в 5% случаев, так что надо активно попереключать фреймы и т.д. 
ivan
505
ivan  
Scriptong:
Нужно брать не любой таймфрейм, а один конкретный, т. е. в iTime должен быть не 0 на месте таймфрейма, а константное значение, используемое при работе индикатора на любом таймфрейме.


А что, при вызове iBarShift(NULL,0,time0,false) он не в конкретном таймфрейме считает??? посмотрите код.
Ihor Herasko
9631
Ihor Herasko  
qomment:

А что, при вызове iBarShift(NULL,0,time0,false) он не в конкретном таймфрейме считает??? посмотрите код.


В своем сообщении я не упоминал iBarShift. Речь шла о функции iTime. В приведенном коде этой функции передается 0 - текущий таймфрейм. Именно в этом и проблема - нужно использовать заранее определенный таймфрейм. Причем получить значение нужно именно после подкачки данных. Проверяется это так:

input ENUM_TIMEFRAMES i_tf = PERIOD_H1;


datetime time;
int error = ERR_HISTORY_WILL_UPDATED;
while (error == ERR_HISTORY_WILL_UPDATED)
{
   time = iTime(NULL, i_tf, 0);
   error = GetLastError();
   Sleep(1000);
}
ivan
505
ivan  
Scriptong:


В своем сообщении я не упоминал iBarShift. Речь шла о функции iTime. В приведенном коде этой функции передается 0 - текущий таймфрейм. Именно в этом и проблема - нужно использовать заранее определенный таймфрейм. Причем получить значение нужно именно после подкачки данных. Проверяется это так:

 


Большое спасибо. Насчёт iBarShift - моя неточность в ответе, я имел ввиду iTime конечно. Посмотрю Ваш вариант проверки подкачки. Правда Sleep в индикаторах не работает - надо как-то по-другому будет проверять. Кроме того, кажется, Вы согласны, что во время подкачки могут быть ошибки, то есть даже iTime(NULL, i_tf,0) может скакать? Именно в этом был мой вопрос. Получается, в любой кастомный индикатор имеет смысл вставлять такую процедуру - проверку подкачки данных при переключении таймфрейма. 

Ihor Herasko
9631
Ihor Herasko  
qomment:


Большое спасибо. Насчёт iBarShift - моя неточность в ответе, я имел ввиду iTime конечно. Посмотрю Ваш вариант проверки подкачки. Правда Sleep в индикаторах не работает - надо как-то по-другому будет проверять. Кроме того, кажется, Вы согласны, что во время подкачки могут быть ошибки, то есть даже iTime(NULL, i_tf,0) может скакать? Именно в этом был мой вопрос. Получается, в любой кастомный индикатор имеет смысл вставлять такую процедуру - проверку подкачки данных при переключении таймфрейма. 

 


Факт подкачки данных никем не оспаривался - в МТ4 история по таймфреймам закачивается асинхронно. Это в МТ5 все строится на минутных данных. Было предложено несколько вариантов решения проблемы. 

В индикаторе функция Sleep, да, не поможет. Там приходится разделять приведенную функцию на две части: 

int OnInit()
{
   ...
   iTime(NULL, i_tf, 0);                              // Запуск процесса обновления нужного таймфрейма
   ...
}

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[])
{
   datetime time = iTime(NULL, i_tf, 0);
   if (GetLastError() == ERR_HISTORY_WILL_UPDATED)                    // Расчет значений индикатора не запускает до тех пор, пока не будет окончен процесс подкачки истории
      return prev_calculated;
   ...
   return rates_total;
}
ivan
505
ivan  
Scriptong:


Факт подкачки данных никем не оспаривался - в МТ4 история по таймфреймам закачивается асинхронно. Это в МТ5 все строится на минутных данных. Было предложено несколько вариантов решения проблемы. 

В индикаторе функция Sleep, да, не поможет. Там приходится разделять приведенную функцию на две части: 

 

Насколько я понял, асинхронно - в данном случае значит "беспорядочно". То есть порядок загрузки баров может не соответствовать упорядочению их времен открытия. И "все про это знают", только в официальном хелпе про это - ни слова (вроде бы). 

Ещё раз спасибо, ERR_HISTORY_WILL_UPDATED - полезна. При этом с помощью этого кода ошибки проверяется загрузка всей истории - несмотря на то , что для индикатора нужны например самые поздние 100 баров. Приходится ждать несколько секунд, вместо того, чтобы сразу начать оперировать со 100 барами. Но нет, они могут еще измениться в процессе подгрузки. Правильно?

Еще вопрос и заранее еще большее спасибо - в чём разница между iTime(NULL,0,0) и iTime(NULL, i_tf,0) если i_tf соответствует текущему таймфрейму? По идее никакой (если верить официальному хелпу). Кроме того, если определять  i_tf руками, то пропадает смысл переключения таймфремов в терминале - программа просто будет работать на текущем таймфрейме и всё. 

12
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий