[SERVICE DESK] Errore nell'ottenere il tempo del TF senior nel timer! - pagina 8

 
Igor Makanu:

3. punto interessante di analisi, cosa restituisce CopyClose(), l'ho controllato io stesso, se non c'è un file .hst per il TF richiesto, CopyClose() non restituisce mai più di 2048 - cioè questo è il valore massimo che può essere scaricato?

No. 2048 è la porzione di dati che viene scaricata dal server quando non ci sono file sul client.

 
вSlava:

No. 2048 è un pezzo di dati che viene scaricato dal server quando non ci sono dati sul client.

Hm, faccio MQL da molto tempo, ma è ancora inaspettato per me

OK, ecco un esempio dall'aiuto:https://www.mql5.com/ru/docs/series/timeseries_access

c'è scritto che:

Il prossimo controllo importante è quello di verificare il tipo di programma da cui viene chiamata la funzione. Ricorda che inviare una richiesta di aggiornamento di una serie temporale con lo stesso periodo dell'indicatore che chiama l'aggiornamento è altamente indesiderabile. L'indesiderabilità di richiedere dati dello stesso periodo di tempo di quello dell'indicatore è determinata dal fatto che l'aggiornamento dei dati storici viene eseguito nello stesso thread in cui lavora l'indicatore. Pertanto, c'è un'alta probabilità di uno scontro. Per controllarlo, usiamo la funzioneMQL5InfoInteger() con il modificatoreMQL5_PROGRAM_TYPE.

cioè l'esempiohttps://www.mql5.com/ru/code/449

non è adatto per caricare i dati della storia nell'indicatore MT4, e come posso scaricare l'intera storia dall'indicatore, se non c'è un file .hst preparato, cioè l'indicatore inizializza il caricamento della storia dal proprio simbolo

come posso sapere che qui ho "scaricato" l'intera storia uguale a iBars(Symbol(),PERIOD_CURRENT);

iBars() restituirà anche un valore errato? - non c'è ancora storia, quindi non c'è iBars()

sembra che in MT5 la storia viene scaricata senza problemi, basta aspettare e controllare lo stato dei dati storici, ma in MT4?

PS: in kodobase ieri stavo cercando un indicatore multicurrency correttamente funzionante per MT4, ma i codici non sono soggetti a imitazione, in molti esempi di kodobase, in generale non c'è paginazione storia nell'indicatore

Документация по MQL5: Доступ к таймсериям и индикаторам / Организация доступа к данным
Документация по MQL5: Доступ к таймсериям и индикаторам / Организация доступа к данным
  • www.mql5.com
Прежде чем ценовые данные будут доступны в терминале MetaTrader 5, их необходимо получить и обработать. Для получения данных требуется подключение к торговому серверу MetaTrader 5. Данные поступают с сервера по запросу терминала в виде экономно упакованных блоков минутных баров. Механизм обращения к серверу за данными не зависит от того, каким...
 

Nei quadrupli, il "tasto home è stato premuto". Non c'è altro modo. Se hai studiato l'argomento per un po', dovresti ricordare la frase "mattone sulla tastiera"

https://www.mql5.com/ru/code/9968

https://www.mql5.com/ru/code/9153

https://www.mql5.com/ru/code/9888

ZG_All_Quotings 3.2
ZG_All_Quotings 3.2
  • www.mql5.com
Скайп-чат поддержки продукта: Последние версии библиотек, скриптов и приложений: Сей скрипт продолжение темы закачек котировок обновлением графика. Решил не обновлять старую версию, а выложить заново. Это принципиально новый скрипт. Удалось добиться максимальной надёжности его работы за счёт переноса функций WinAPI в DLL. Скрипт, как и...
 
Igor Makanu:

Puoi controllare il mio downloader gratuito.

 
Alexey Kozitsyn:

Puoi vedere il mio downloader gratuito.

Come mi suggerisci di guardare il tuo codice? So come scaricare la cronologia, ma non so come controllare l'indicatore di download.

Slava:

In quadruplice "premere il tasto home". Non c'è altro modo. Se studiate la materia da molto tempo, dovreste ricordare la frase "mattone sulla tastiera"

https://www.mql5.com/ru/code/9968

https://www.mql5.com/ru/code/9153

https://www.mql5.com/ru/code/9888

Quando ho iniziato ad usare MQL negli ultimi anni non ho imparato affatto MQL, da quest'anno sono davvero sorpreso che gli sviluppatori abbiano reso la compatibilità tra MT5 e MT4 il più possibile e migliorato le prestazioni di MQL4 - anche se ci è stato detto prima che MT4 come progetto non sarà più sviluppato, ci sono solo bug da risolvere

e qui era una speranza che non ho trovato informazioni sul caricamento automatico della storia nell'indicatore MT4

Fondamentalmente, se si vuole garantire il download dell'intera storia in MT4 e senza controlli aggiuntivi, allora è più facile usare il codice dfix - scrivere la barra datetime t=0 nel file .hst;

 
Igor Makanu:

Quindi come mi suggerisci di guardare il tuo codice?

Pensavo che bastasse che la storia fosse caricata automaticamente...

 

Con mio grande rammarico, devo tornare ancora una volta sull'argomento dell'ottenimento di dati TF senior in MT4. Questa volta a causa del fatto che le tecniche suggerite qui non hanno funzionato.

Ecco il codice che usiamo:

#property strict
#property indicator_chart_window
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//--- Время открытия текущего часа, дня и недели
datetime _weekOpenTime = 0;
datetime _hourOpenTime = 0;
datetime _dayOpenTime=0;
//--- Вести лог журнала
const bool inpFileLog=true;
//--- Количество секунд в одном дне
const int SEC_PER_DAY=86400;
//--- Флаг работоспособности индикатора
bool _isWorking=true;
//--- Флаг соединения с торговым сервером (для таймера, получаем в OnCalculate())
bool _isConnected=false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Сбрасываем время открытия текущего часа, дня и недели
   _weekOpenTime= 0;
   _dayOpenTime = 0;
   _hourOpenTime= 0;
//--- Устанавливаем флаг работоспособности
   _isWorking=true;
//--- Сбрасываем флаг установки соединения
   _isConnected=false;
//--- Запускаем таймер
   if(!EventSetMillisecondTimer(20))
     {
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": таймер с частотой 20 не установлен!");
      //--- Устанавливаем флаг неработоспособности индикатора
      _isWorking=false;
     }
//--- Запрос данных
   SeriesInfoInteger(_Symbol,PERIOD_W1,SERIES_LASTBAR_DATE);
   SeriesInfoInteger(_Symbol,PERIOD_D1,SERIES_LASTBAR_DATE);
   SeriesInfoInteger(_Symbol,PERIOD_H1,SERIES_LASTBAR_DATE);
//---
   return( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//|                                                                   |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Выключаем таймер
   EventKillTimer();
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   if(!_isWorking)
      return;
//---
   if(!_isConnected)
      return;
//---
   Print(__FUNCTION__,": Данные старших ТФ загружены!");
//--- Отключаем таймер
   EventKillTimer();
  }
//+------------------------------------------------------------------+
//| 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(!IsConnected())                              // Если не удалось установить связь с сервером
     {
      //--- Сбрасываем флаг соединения с сервером
      _isConnected=false;
      //--- Выходим
      return( 0 );
     }
//--- Проверяем первый запуск индикатора
   if(prev_calculated<=0)
     {
      //--- Проверяем, записано ли время открытия текущей недели
      if(!CheckCurrentWeekOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Проверяем, записано ли время открытия текущего дня
      if(!CheckCurrentDayOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Проверяем, записано ли время открытия текущего часа
      if(!CheckCurrentHourOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Устанавливаем флаг соединения с сервером для запуска таймера
      _isConnected=true;
     }
//---
   return( rates_total );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущей недели             |
//+------------------------------------------------------------------+
bool CheckCurrentWeekOpenTime()
  {
//--- Проверяем, записано ли время
   if(_weekOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия недельного бара
      ResetLastError();
      const datetime weekBarOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_W1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия недельного бара = "+TimeToString(weekBarOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия недельного бара
      if(weekBarOpenTime==0 || err!=0) // Если время бара не получено или история обновляется
         return(false);                              // Возвращаем ложь
      //--- Запоминаем время открытия текущей недели (время открытия недельного бара - воскресенье)
      _weekOpenTime=weekBarOpenTime+SEC_PER_DAY;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущей недели = "+TimeToString(_weekOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия недели ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущего дня                  |
//+------------------------------------------------------------------+
bool CheckCurrentDayOpenTime()
  {
//--- Проверяем, записано ли время
   if(_dayOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия дневного бара
      ResetLastError();
      const datetime tempDayOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_D1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия текущего дня = "+TimeToString(tempDayOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия дневного бара
      if(tempDayOpenTime==0 || err!=0) // Если время бара не получено
         return(false);                                 // Возвращаем ложь
      //--- Сохраняем в глобальную переменную значение открытия текущего дня
      _dayOpenTime=tempDayOpenTime;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущего дня = "+TimeToString(_dayOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия дня ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущего часа              |
//+------------------------------------------------------------------+
bool CheckCurrentHourOpenTime()
  {
//--- Проверяем, записано ли время
   if(_hourOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия часового бара
      ResetLastError();
      const datetime tempHourOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_H1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия текущего часа = "+TimeToString(tempHourOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия часового бара
      if(tempHourOpenTime==0 || err!=0) // Если время бара не получено
         return(false);                                 // Возвращаем ложь
      //---
      _hourOpenTime=tempHourOpenTime;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущего часа = "+TimeToString(_hourOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия часа ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+

Implementa il paging dei dati come mi è stato consigliato:

Forum sul trading, sistemi di trading automatico e test di strategie di trading

[SERVICESDESK] Errore nell'ottenere il tempo del vecchio TF nel timer!

Slava, 2018.09.27 06:20

È stato discusso molte volte. 12 pagine su "errore 4066".

Ed è stato correttamente consigliato di inviare la richiesta in OnInit e analizzarla in OnCalculate.

A cosa vi serve un timer al millisecondo? State impedendo al terminale client di avviarsi normalmente. Non sono i messaggi del vento che interferiscono con il tuo timer, è il tuo timer che interferisce con tutti. Ancora una volta: GLI INDICATORI NEL TERMINALE MT4 DEL CLIENTE LAVORANO IN POTENZIALE DI INTERFACCIA.

L'implementazione è esattamente così: la prima richiesta di dati avviene in OnInit(). Poi, aspettiamo che la connessione con il server commerciale sia stabilita, poi in OnCalculate()! otteniamo i dati del TF alto. Otteniamo il risultato al primo lancio di oggi:

2018.10.04 09:10:56.266 test_isNewDayInOnCalculate EURGBP.e,M1: OnTimer: Данные старших ТФ загружены!
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущего часа = 2018.10.03 09:00. Ошибка #0
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Время открытия текущего часа = 2018.10.03 09:00. Ошибка #0
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущего дня = 2018.10.03 00:00. Ошибка #0
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Время открытия текущего дня = 2018.10.03 00:00. Ошибка #0
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущей недели = 2018.10.01 00:00. Ошибка #0
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Время открытия недельного бара = 2018.09.30 00:00. Ошибка #0

Come possiamo vedere dal log abbiamo ottenuto valori errati di ora e ora del giorno.

Sì, gli sviluppatori(@Slava) possono notare che non ho applicato tutti i consigli che mi sono stati dati. Cioè, eseguo ancora il timer veloce in OnInit(), anche se mi è stato originariamente consigliato di eseguire il timer lento. Tuttavia, in questo caso, è fatto apposta. Se il timer veloce viene avviato nel thread dell'interfaccia e può rallentare il recupero dei dati da altri indicatori - questo è un grosso problema. La documentazione non contiene alcuna avvertenza al riguardo, si può mettere un programma con un timer veloce che può diventare una specie di "virus" e causare "guasti" di altri programmi.

Alla luce di quanto sopra, credo che dovremmo introdurre delle restrizioni sul timer dei millisecondi o specificare nella documentazione di EventSetMillisecondTimer() che la funzione non può essere avviata in OnInit() per permettere al terminale di salire normalmente all'avvio.

 
Oggi all'apertura della giornata la situazione è simile, l'errore si è ripetuto. Testbed: un grafico, tre indicatori su di esso. Due non usano il timer, il terzo sì. Tutti hanno ricevuto dati errati durante il caricamento. Ora ho rimosso l'indicatore che usa un timer dal grafico e vedrò cosa succede.
 

Ora la parte divertente. Il codice è senza timer:

#property strict
#property indicator_chart_window
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//--- Время открытия текущего часа, дня и недели
datetime _weekOpenTime = 0;
datetime _hourOpenTime = 0;
datetime _dayOpenTime=0;
//--- Вести лог журнала
const bool inpFileLog=true;
//--- Количество секунд в одном дне
const int SEC_PER_DAY=86400;
//--- Флаг работоспособности индикатора
bool _isWorking=true;
//--- Флаг соединения с торговым сервером (для таймера, получаем в OnCalculate())
bool _isConnected=false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Сбрасываем время открытия текущего часа, дня и недели
   _weekOpenTime= 0;
   _dayOpenTime = 0;
   _hourOpenTime= 0;
//--- Устанавливаем флаг работоспособности
   _isWorking=true;
//--- Сбрасываем флаг установки соединения
   _isConnected=false;
//--- Запрос данных
   SeriesInfoInteger(_Symbol,PERIOD_W1,SERIES_LASTBAR_DATE);
   SeriesInfoInteger(_Symbol,PERIOD_D1,SERIES_LASTBAR_DATE);
   SeriesInfoInteger(_Symbol,PERIOD_H1,SERIES_LASTBAR_DATE);
//---
   return( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//|                                                                   |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| 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(!IsConnected())                              // Если не удалось установить связь с сервером
     {
      //--- Сбрасываем флаг соединения с сервером
      _isConnected=false;
      //--- Выходим
      return( 0 );
     }
//--- Проверяем первый запуск индикатора
   if(prev_calculated<=0)
     {
      //--- Проверяем, записано ли время открытия текущей недели
      if(!CheckCurrentWeekOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Проверяем, записано ли время открытия текущего дня
      if(!CheckCurrentDayOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Проверяем, записано ли время открытия текущего часа
      if(!CheckCurrentHourOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Устанавливаем флаг соединения с сервером для запуска таймера
      _isConnected=true;
      //---
      Print(__FUNCTION__,": Данные старших ТФ загружены!");
     }
//---
   return( rates_total );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущей недели             |
//+------------------------------------------------------------------+
bool CheckCurrentWeekOpenTime()
  {
//--- Проверяем, записано ли время
   if(_weekOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия недельного бара
      ResetLastError();
      const datetime weekBarOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_W1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия недельного бара = "+TimeToString(weekBarOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия недельного бара
      if(weekBarOpenTime==0 || err!=0) // Если время бара не получено или история обновляется
         return(false);                              // Возвращаем ложь
      //--- Запоминаем время открытия текущей недели (время открытия недельного бара - воскресенье)
      _weekOpenTime=weekBarOpenTime+SEC_PER_DAY;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущей недели = "+TimeToString(_weekOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия недели ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущего дня                  |
//+------------------------------------------------------------------+
bool CheckCurrentDayOpenTime()
  {
//--- Проверяем, записано ли время
   if(_dayOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия дневного бара
      ResetLastError();
      const datetime tempDayOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_D1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия текущего дня = "+TimeToString(tempDayOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия дневного бара
      if(tempDayOpenTime==0 || err!=0) // Если время бара не получено
         return(false);                                 // Возвращаем ложь
      //--- Сохраняем в глобальную переменную значение открытия текущего дня
      _dayOpenTime=tempDayOpenTime;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущего дня = "+TimeToString(_dayOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия дня ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущего часа              |
//+------------------------------------------------------------------+
bool CheckCurrentHourOpenTime()
  {
//--- Проверяем, записано ли время
   if(_hourOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия часового бара
      ResetLastError();
      const datetime tempHourOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_H1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия текущего часа = "+TimeToString(tempHourOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия часового бара
      if(tempHourOpenTime==0 || err!=0) // Если время бара не получено
         return(false);                                 // Возвращаем ложь
      //---
      _hourOpenTime=tempHourOpenTime;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущего часа = "+TimeToString(_hourOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия часа ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+

E ancora non puoi ottenere il risultato che vuoi. Gli sviluppatori(@Slava), per favore commentate. È impossibile ottenere dati corretti quando si carica il terminale da diversi TF superiori. Condizione obbligatoria è che il terminale deve essere spento più di un'ora dopo lo spegnimento (perché otteniamo i dati della barra di un'ora). E, naturalmente, avvio su TF in meno di un'ora.

Il timer si è rivelato non essere coinvolto.
 
Alexey, stai interrogando i dati dei TF senior nell'Inite. Nessuna connessione ancora, molto probabilmente ha restituito un errore. Prova a fare una richiesta con la prima spunta che arriva.
Non posso controllare, sono al cottage e non ho portato il mio tablet con me.