[СЕРВИСДЕСК] Ошибка получения времени старшего ТФ в таймере! - страница 6

 
Очень хотелось бы услышать, что на этот счет считают разработчики. 
 
 ResetLastError();
      if(iBarShift(Symbol(),PERIOD_M15,TimeCurrent(),true)==-1)
        {
         Print(__FILE__+": Данные истории по последнему часу отсутствуют! Ошибка #",GetLastError());
         return( false );
        }
      //---
      if(GetLastError()==ERR_NO_ERROR)
        {
         ResetLastError();
         //--- Запоминаем время открытия бара
         _m15OpenTime=iTime(NULL,PERIOD_M15,0);
         //---
         Print(__FILE__,": Актуальное время открытия бара М15 = "+TimeToString(_m15OpenTime)+". Ошибка #",GetLastError());
         //--- Возвращаем истину
         return( true );
        }
 
Alexey Kozitsyn:

Похоже, что самое надежное решение - это действительно дожидаться вызова OnCalculate(), причем с обязательной проверкой установления подключения к торговому серверу. Если же не сделать проверку на подключение (IsConnected()), то даже в OnCalculate() при загрузке терминала получим:

Однако, это не снимает всех вопросов:

1. Почему в документации к IsConnected() не написано, что она должна быть обязательно вызвана перед получением данных (как минимум) старшего ТФ в OnCalculate()?

2. Почему IsConnected() в OnTimer(), по сути, не работает? Ведь разве факт установления соединения с торговым сервером не должен нам говорить о том, что можно получить данные?

3. Раз мы установили соединение с торговым сервером и пытаемся получить данные в OnTimer(), разве не должны функции iTime(), iBarShift(), SeriesInfoInteger() и подобные им функции возвращать ошибки, если данные с этим самым торговым сервером, с которого они берут информацию еще не синхронизированы? А то получается ерунда какая-то, типа один раз мы тебе вернем ошибку 4066, а потом живи как хочешь с теми данными, что есть.

Побщался с разработчиками есть у меня там один знакомый рассказываю по пунктам.

1 Ерунда, вызывать можно когда угодно и из любого места.

2 IsConnected можно вызывать из любого места кодаи он работает, но это функция которая ни чего не пишет в стек ошибок она возвращает истино/ложно и всё. Учитывая что процедура соединения достаточно (минимум 1 сек)длинная а IsConnected срабатывает уже в момент начала логина то в условиях старта терминала необходимо обязательно проверять статус соединения и дожидаться начала потока котировок. 

3 Данные функции также ни чего не пишут в стек ошибок они сами возвращают результат работы. 

Почему мы получали 4066 это ошибка была от функции TimeCurrent. Произошёл логин терминал запросил время с сервера в зависимости от качества соединения на это тоже уходит какое-то время не забывайте у нас быстрый таймер. А дальше мы получили 4066 по нашему запросу от TimeCurrent. А затем мы получили время и наши функции начали нормально работать они сами возвращают ошибку в результате своей работы минуя стек ошибок. 

Как рекомендация в подобной ситуации, быстрый таймер и старт терминала, обязательно проверять что мы начали получать данные с сервера. Мой вариант немного костыльный, правильно было бы получить сигнал от OnCalculate о начале приёма данных.

 
Все проще. 
 
Alexey Kozitsyn:

Что Вы предлагаете для решения проблемы (есть ли она, по Вашему)? Ждать пока будет 1-2 раза вызван OnCalculate()?

Да, именно. В OnInit() просто делаете обращение к нужным ТФ без проверки результата (на него там нельзя полагаться), а уже в OnCalculate вызывать функцию IsTFDataReady(). Как только для всех запрашиваемых ТФ возвращено true, можно приступать к выполнению алгоритма индикатора.

 
Alexey Kozitsyn:

1. Почему в документации к IsConnected() не написано, что она должна быть обязательно вызвана перед получением данных (как минимум) старшего ТФ в OnCalculate()?

IsConnected() достаточно хитрая функция. Она возвращает состояние только одного из подключений к серверу. А ведь терминал использует не одно подключение. Одних только торговых потоков 8. Поэтому даже если IsConnected() вернет true, то не совсем понятно, что это означает. По крайней мере, нельзя рассчитывать на то, что таймсерии будут запрошены и построены. Вот если IsConnected() вернет false, то тут можно быть уверенным, что терминал еще в оффлайн. 

Вообще, что за задача решается, для которой настолько принципиально наличие подключения терминала? В моем понимании индикатор - инструмент визуализации данных. Тех данных, которые имеются. Придут новые данные, он обновит визуализацию. От него вроде не должна требоваться проверка актуальности данных. Это задача терминала.

 
Igor Makanu:

наверное речь идет все таки о MQL5, там подготовка OHLC идет не так как в МТ4

Я говорю об МТ4. Года 2-3  назад вылавливал баг с Time[0]. Разработчики вроде бы починили, но потом, со временем, снова он проявился. Проблема в том, что однозначно воспроизвести этот баг невозможно.

 
Ihor Herasko:

IsConnected() достаточно хитрая функция. Она возвращает состояние только одного из подключений к серверу. А ведь терминал использует не одно подключение. Одних только торговых потоков 8. Поэтому даже если IsConnected() вернет true, то не совсем понятно, что это означает. По крайней мере, нельзя рассчитывать на то, что таймсерии будут запрошены и построены. Вот если IsConnected() вернет false, то тут можно быть уверенным, что терминал еще в оффлайн. 

Вообще, что за задача решается, для которой настолько принципиально наличие подключения терминала? В моем понимании индикатор - инструмент визуализации данных. Тех данных, которые имеются. Придут новые данные, он обновит визуализацию. От него вроде не должна требоваться проверка актуальности данных. Это задача терминала.

в индикаторах, действительно, не припомню необходимость проверки соединения с сервером, что есть в истории, то и рисуем, подгрузилась история, значит пересчитаем все индикаторные буфера заново

в советнике сделал и пользуюсь вот такую ф-цию, в принципе устраивает и проверяет соединение с сервером корректно:

bool ServerDisable(int count=10){
   if(IsTesting()||IsOptimization())return(false);
   for(int i=0;i<count;i++){
      if(IsConnected())
         if(IsTradeAllowed())
            if(!IsTradeContextBusy()){RefreshRates(); return(false);}
      Sleep(157);
   }
   Print(__FUNCTION__," Торговый сервер не отвечает");
return(true);}

специально использую в ней Sleep(), чтобы передавать управление терминалу, и потом опять проверяю соединение с сервером и возможность торговли

 
Ihor Herasko:

Я говорю об МТ4. Года 2-3  назад вылавливал баг с Time[0]. Разработчики вроде бы починили, но потом, со временем, снова он проявился. Проблема в том, что однозначно воспроизвести этот баг невозможно.

если не затруднит, вот по теме топика - корректная подгрузка истории со старшего ТФ, вот индикатор: "нужно нарисовать МАшку" со старшего ТФ на барах младшего ТФ, сделал в течении 5 минут, работать будет на 98% точно корректно, где вот в этом коде 2% "подводные камни" которые и вызовут баги ?

интересует корректный код под МТ4

#property copyright "IgorM"
#property link      "https://www.mql5.com/ru/users/igorm"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot line1
#property indicator_label1  "line1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input ENUM_TIMEFRAMES   TimeFrame   =  PERIOD_H4;
input int               MAPeriod    =  25;
//--- indicator buffers
double         BufMA[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   double cl[];
//--- indicator buffers mapping
   SetIndexBuffer(0,BufMA);
   IndicatorDigits(Digits);
// запускаем подгрузку истории и выходим, даже не проверяя подгружена она или нет, история тут еще не нужна
   CopyClose(_Symbol,TimeFrame,0,iBars(_Symbol,TimeFrame),cl);
//---
   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[])
  {
//---
   int i,limit,resultcopy;
   double closetf[];
   if(prev_calculated==0)
     {
      resultcopy=CopyClose(_Symbol,TimeFrame,0,iBars(_Symbol,TimeFrame),closetf);
      if(resultcopy<0)
        {
         Print("Подгрузка истории....");
         return(0);
        }
      if(resultcopy<MAPeriod)
        {
         Comment("Большой период МА!!!, в истории доступно ", resultcopy," баров");
         return(resultcopy);
        }
      limit=resultcopy-1;
        }else{
      resultcopy=CopyClose(_Symbol,TimeFrame,0,iBars(_Symbol,TimeFrame),closetf);
      if(resultcopy<0)
        {
         Print("Подгрузка истории....");
         return(0);
        }
      if(resultcopy<MAPeriod)
        {
         Comment("Большой период МА!!!, в истории доступно ", resultcopy," баров");
         return(resultcopy);
        }
      limit=resultcopy-prev_calculated+1;
     }
   limit = fmin(rates_total-1,limit);
// основной цикл расчета индикатора
   for(i=limit; i>=0 && !IsStopped(); i--)
     {
      BufMA[i]=iMA(_Symbol,TimeFrame,MAPeriod,0,MODE_SMA,PRICE_CLOSE,i);
     }
//---
   return(resultcopy);

  }
 
Vitaly Gorbunov:

Побщался с разработчиками есть у меня там один знакомый рассказываю по пунктам.

1 Ерунда, вызывать можно когда угодно и из любого места.

2 IsConnected можно вызывать из любого места кодаи он работает, но это функция которая ни чего не пишет в стек ошибок она возвращает истино/ложно и всё. Учитывая что процедура соединения достаточно (минимум 1 сек)длинная а IsConnected срабатывает уже в момент начала логина то в условиях старта терминала необходимо обязательно проверять статус соединения и дожидаться начала потока котировок. 

3 Данные функции также ни чего не пишут в стек ошибок они сами возвращают результат работы. 

Почему мы получали 4066 это ошибка была от функции TimeCurrent. Произошёл логин терминал запросил время с сервера в зависимости от качества соединения на это тоже уходит какое-то время не забывайте у нас быстрый таймер. А дальше мы получили 4066 по нашему запросу от TimeCurrent. А затем мы получили время и наши функции начали нормально работать они сами возвращают ошибку в результате своей работы минуя стек ошибок. 

Как рекомендация в подобной ситуации, быстрый таймер и старт терминала, обязательно проверять что мы начали получать данные с сервера. Мой вариант немного костыльный, правильно было бы получить сигнал от OnCalculate о начале приёма данных.

1. Внимательно читайте, что я пишу. Говорю уже не первый раз! Я не говорил про запрет вызова где-то!

Вы хотите сказать, что все функции iBarShift(), iTime(), SeriesInfo...() запрашивают время TimeCurrent()?

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