mql4 - SeriesInfoInteger - страница 2

 
Karputov Vladimir:
Если Вы хотите получить данные с другого инструмента и другого таймфрейма, особенно в индикаторе, нужно сначала озаботиться подготовкой данных. Проверить есть ли данные. И только после этого рабоать с этими подготовленными данными. 

Ок. что я неправильно делаю в этом простейшем примере? Я утверждаю что в мкл4 функция SeriesInfoInteger не работает при обращение к другому символу.

Кроме того функция SeriesInfoInteger - "Возвращает информацию о состоянии исторических данных" это из хелпа. Т.е информация уже есть и я её получаю. мне нужно знать кол-во доступных баров, мне не нужно для этого организовывать доступ к истории, так как нет необходимости в ценах опен или глоуз или других исторических данных.

 Я готов согласиться с тем что могу ошибаться, но тогда где?? тыкните пальцем и скажите как сделать правильно, а ссылки на хелп и у меня имеются. 

 
Неужели никто не сталкивался с этим вопросом и не может помочь? 
 
Alexey Oreshkin:
Неужели никто не сталкивался с этим вопросом и не может помочь? 

Дело в том, что не получается воспроизвести указанную ошибку, т. к. проверка

   Print("Bars on EURUSD = ", SeriesInfoInteger("EURUSD", PERIOD_H1, SERIES_BARS_COUNT));

 дает ожидаемый результат:

2015.05.15 14:53:00.118 Test AUDUSD,M5: Bars on EURUSD = 108329

Таким образом, напрашивается вывод, что какие-то проблемы именно в программе. Кстати, попробуйте сделать самое очевидное, что необходимо делать в подобных случаях: распечатайте код ошибки после вызова SeriesInfoInteger.

Также необходимо учесть, что переменная smb в Вашем коде может иметь вовсе не то значение, которое ожидается. Да и указанный таймфрейм (Period()), который берется с текущего графика, может отсутствовать для вызываемого символа. 

 
Игорь Герасько:

Дело в том, что не получается воспроизвести указанную ошибку, т. к. проверка

 дает ожидаемый результат:

Таким образом, напрашивается вывод, что какие-то проблемы именно в программе. Кстати, попробуйте сделать самое очевидное, что необходимо делать в подобных случаях: распечатайте код ошибки после вызова SeriesInfoInteger.

Также необходимо учесть, что переменная smb в Вашем коде может иметь вовсе не то значение, которое ожидается. Да и указанный таймфрейм (Period()), который берется с текущего графика, может отсутствовать для вызываемого символа. 

Весь код программы приведён выше. SeriesInfoInteger выдаёт правильный результат только если я уже открывал график данного символа. Если же я только что открыл терминал, запустил данный код на одном символе с запросом о другом то выдаёт 0. при этом ошибки тоже нет ,GetLasterror также возвращает 0. Но у меня сотни инструментов и открывать вручную их все при каждом перезапуске это не вариант. При всём этом iBars работает отлично. Но тем не менее вопрос решился ещё одним способом - перед вызовом SeriesInfoInteger нужно обратиться к нужному символу на нужном периоде через iClose. Но зачем такие костыли??? вообщем минус в карму разработчикам.

 
Karputov Vladimir:
Вы точно прочли: Организация доступа к данным? Не нравиться мт5 (или если не хочется открыть справку в MetaEditore) - вот ссылка на справку mql4: Организация доступа к данным
Это грубо передрано из справки MQL5, где исправили только номер версии с 5 на 4 в тексте, а остальной текст остался с пятой справки. В МТ4 нет НСС истории, как нет и НС кэша. И проверять там на каждом тике доступность истории вовсе не так жизненно, как в МТ5.
 
Alexey Oreshkin:

Если же я только что открыл терминал, запустил данный код на одном символе с запросом о другом то выдаёт 0. при этом ошибки тоже нет ,GetLasterror также возвращает 0. 

Так именно об этом чуть выше Вам постоянно твердил barabashka. Перед тем, как обращаться к данным, нужно убедиться в их доступности. Да, к сожалению, это костыли. Но в МТ4 нет другого способа, кроме как:

double = iTime(symbol, period, 1);             // Подойдет любая другая таймсерия
if (GetLastError() == ERR_HISTORY_WILL_UPDATED)
{
    // Данные запрашивать еще нельзя, ждем
}
else
{
   // Все ОК.
}

 А потом, для поддержки обновления данных следует обращаться к нужному символу на каждом новом тике. 

К сожалению, за все время существования МТ4 не нашел другой, более красивой возможности осуществлять доступ к данным другого таймфрейма и/или символа. 

 

Решил поднять вновь тему так как здесь мне упорно рекомендовали отслеживать ошибку 4066 перед обращением к истории, но это не является решением проблемы. Вопрос простой - понять что история готова для использования и она является актуальной. Вот мой алгоритм действий:

1.В обзоре рынка добавляю ранее не использованную и не открытую валютную пару. Допустим USDDKK. 

2.Убираю все остальные пары кроме  EURUSD. для удобства. В итоге у меня 2 пары в обзоре рынка: EURUSD и USDDKK. Открыт график EURUSD. График пары USDDKK не открывал

2.На EURUSD кидаю эксперт который запрашивает по текущему периоду историю с  USDDKK.

3.Если GetLastError возвращает не 0 то кручусь в цикле дальше пока ошибка станет =0. По идее теперь данные доступны

4.Обращаюсь к  USDDKK через iClose(Symbol(),Period(),0) (iTime и другие серии тоже пробовал - результат тотже) и получаю не текущие данные !

5.Удалю эксперт и кидаю его на EURUSD снова и опять же запрашиваю историю с USDDKK - и вуаля, всё работает !

Нашёл подобные темы аж с 2006 года, перепробовал всё что нашёл но ничего не работает. Да и ответа нигде небыло. 

  

Пробовал использовать ArrayCopySeries, ArrayCopyRates и наверное тыщу других вариантов - не работает !

вот как пример древней темы, там есть и описание этого же вопроса - http://forum.mql4.com/ru/5525, но нигде нет точного ответа что делать. 

Для особо страждущих вот код. Запускаю на H1

#property strict

void OnTick()
  {
      for(int i=SymbolsTotal(true)-1;i>=0;i--)
         if (SymbolSelect(SymbolName(i,true),true))     
            CHECK_HISTORY_DATA(SymbolName(i,true),1000);
      ExpertRemove();
  }

/*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
обработка ошибки при запросе данных. Коды ошибок:
4066 - данные готовятся. ждём
4073 - нет исторических данных
4074 - не хватает памяти для исторических данных
4106 - не известный символ

Корректно работает на периодах до D1 включительно
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
bool CHECK_HISTORY_DATA(string smb1="", uint cndl=0)//cndl - сколько данных нужно дял анализа
   {        
      int TimeStart=(int)TimeCurrent();//нужно чтобы не зависнуть в цикле навечно     
      if (smb1=="") smb1=Symbol();
            
      //Получаем расчётное время формирования текущей свечи
      MqlDateTime tms;
      TimeToStruct(TimeStart,tms);      
      tms.sec=0;
      switch(Period())
        {
         case  PERIOD_D1:tms.hour=0;tms.min=0;break;
         case  PERIOD_H4:tms.hour=tms.hour-(int)MathMod(tms.hour,4);tms.min=0;break;
         case  PERIOD_H1:tms.min=0;break;
         case  PERIOD_M30:tms.min=tms.min-(int)MathMod(tms.min,30);break;
         case  PERIOD_M15:tms.min=tms.min-(int)MathMod(tms.min,15);break;
         case  PERIOD_M5:tms.min=tms.min-(int)MathMod(tms.min,5);break;
        }      
      datetime StartCandle=StructToTime(tms);//Время должного формирования текущей свечи                      
                  
      while(true){
         if (TimeCurrent()-TimeStart>=20)return(false);//ждём не более 20 секунд на пару в любом случае
         
         datetime tm1[];         
         int cndl1=ArrayCopySeries(tm1,MODE_TIME,smb1);         
         int er1=GetLastError();

         Print(__FUNCTION__,": Символ: "+smb1+" Ошибка доступа к данным: "+(string)er1);
         Print(__FUNCTION__,": Символ: "+smb1+" Расчётное время текущей свечи: "+TimeToString(StartCandle));
         Print(__FUNCTION__,": Символ: "+smb1+" Полученное время текущей свечи: "+TimeToString(tm1[0]));  
         Print(__FUNCTION__,": Символ: "+smb1+" iTime 0: "+TimeToString(iTime(smb1,Period(),0))); 
         Print(__FUNCTION__,": Символ: "+smb1+" iClose 0: "+DoubleToString(iClose(smb1,Period(),0),5)); 

         if (er1==0){
            if (tm1[0]==StartCandle){Print(__FUNCTION__,": Символ: "+smb1+" ДАННЫЕ АКТУАЛЬНЫ!");return(true);}
            if (cndl1<=(int)cndl) {Print(__FUNCTION__,": Символ: "+smb1+" Полученных данных слишком мало");return(true);}
         }
         
         Sleep(3000);
      }       
      return(true);
   } 
Запрет торговли в одном баре. - MQL4 форум
  • www.mql5.com
Запрет торговли в одном баре. - MQL4 форум
 
Alexey Oreshkin:

4.Обращаюсь к  USDDKK через iClose(Symbol(),Period(),0) (iTime и другие серии тоже пробовал - результат тотже) и получаю не текущие данные !

Если эксперт работает на EURUSD, а Вы пытаетесь прочесть данные с USDDKK вот так:

iClose(Symbol(),Period(),0)

 то непонятно, почему ожидаете получить данные с USDDKK. Ведь этим способом будут получены данные с EURUSD.

 

Специально только что проверил на символе, который никогда не использовал, следующий код:

int OnInit()
{
   // Запрос на подкачку истории
   GetSymbolData("EURPLN", PERIOD_H1, 5);
   return INIT_SUCCEEDED;
}
double GetSymbolData(string symbol, ENUM_TIMEFRAMES tf, int barIndex)
{
   double price = iClose(symbol, tf, barIndex);
   int error = GetLastError();
   if (error == ERR_HISTORY_WILL_UPDATED || error == ERR_UNKNOWN_SYMBOL)
      return -1.0;
      
   return price;
}
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[])
{
   double price = GetSymbolData("EURPLN", PERIOD_H1, 5);
   if (price > 0.0)
      Print("EURPLN bar 5. Close price = ", price);
   else
      Print("Ожидание обновления...");
      
   return(rates_total);
}

 Результат:

0       11:09:10.323    Custom indicator TestInd USDCHF,H1: loaded successfully
0       11:09:10.325    TestInd USDCHF,H1: initialized
0       11:09:10.325    TestInd USDCHF,H1: Ожидание обновления...
0       11:09:11.278    TestInd USDCHF,H1: EURPLN bar 5. Close price = 4.1881
 
Игорь Герасько:

Специально только что проверил на символе, который никогда не использовал, следующий код:

 Результат:

У меня вроде нигде нет такого : iClose(Symbol(),Period(),0), но на самом деле уже не важно так как с вопросом разобрался - сделал как и рекомендовано в хелпе - использую событийную модель и всё стало норм. В этом и была проблема - не обновлялись данные, несмотря на отсутствие ошибки. Теперь уже возникли другие проблемы, но уже стараюсь сам решать. Как то от форума помощи пока незаметил. Толи все заняты простенькими роботами на машках, толи мультивалютной торговлей никто серьёзно не занимается или, к чему я склоняюсь, пишут на VS. Это всё таки универсальнее и не приходиться роботов после переписывать под разные биржи.
Причина обращения: