[SERVICE DESK] ¡Error al obtener la hora de la TF superior en el temporizador! - página 8

 
Igor Makanu:

3. punto interesante de análisis, lo que devuelve CopyClose(), lo he comprobado yo mismo, si no hay archivo .hst para el TF solicitado, CopyClose() nunca devuelve más de 2048 - es decir, este es el valor máximo que se puede descargar?

No. 2048 es la parte de los datos que se descargan del servidor cuando no hay ningún archivo en el cliente.

 
вSlava:

No. 2048 es un trozo de datos que se descarga del servidor cuando no hay datos en el cliente.

Hm, he estado haciendo MQLs durante mucho tiempo, pero todavía es inesperado para mí

Bien, aquí hay un ejemplo de la ayuda:https://www.mql5.com/ru/docs/series/timeseries_access

dice que:

La siguiente comprobación importante es verificar el tipo de programa desde el que se llama a la función. Recordemos que el envío de una solicitud de actualización de series temporales con el mismo periodo que el indicador que llama a la actualización es altamente indeseable. La no conveniencia de solicitar datos del mismo periodo de tiempo que el del indicador viene determinada por el hecho de que la actualización de los datos históricos se realiza en el mismo hilo en el que trabaja el indicador. Por lo tanto, existe una alta probabilidad de que se produzca un choque. Para comprobarlo, utilizamos la funciónMQL5InfoInteger() con el modificadorMQL5_PROGRAM_TYPE.

Es decir, el ejemplohttps://www.mql5.com/ru/code/449

no es adecuado para cargar los datos del historial en el indicador MT4, y cómo puedo descargar todo el historial por el indicador, si no hay un archivo .hst preparado, es decir, el indicador inicializa la carga del historial por su propio símbolo

cómo puedo saber que aquí "descargué" todo el historial igual a iBars(Symbol(),PERIOD_CURRENT);

iBars() también devolverá un valor incorrecto? - todavía no hay historia, por lo que no hay iBars()

parece que en MT5 el historial se descarga sin problemas, sólo hay que esperar y comprobar el estado de los datos históricos, pero en MT4?

PD: en kodobase ayer estuve buscando un indicador multidivisa que funcionara correctamente para MT4, pero los códigos no son susceptibles de imitación, en muchos ejemplos de kodobase, en general no hay paginación del historial en el indicador

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

En los cuatrillizos, la "tecla de inicio fue presionada". No hay otra manera. Si llevas un tiempo estudiando el tema, deberías recordar la frase "ladrillo en el teclado"

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:

Puedes consultar mi descargador gratuito.

 
Alexey Kozitsyn:

Puedes ver mi descargador gratuito.

¿Cómo sugieres que mire tu código? Sé cómo descargar el historial, pero no sé cómo comprobar el indicador de descarga.

Slava:

En el cuádruple "pulse la tecla de inicio". No hay otra manera. Si llevas mucho tiempo estudiando el tema, deberías recordar la frase "ladrillo en el teclado"

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

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

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

Cuando empecé a usar MQL durante los últimos años no aprendí nada de MQL, desde este año estoy realmente sorprendido de que los desarrolladores hayan hecho la compatibilidad entre MT5 y MT4 tanto como sea posible y hayan mejorado el rendimiento de MQL4 - a pesar de que se nos dijo antes que MT4 como proyecto no se desarrollará más, sólo hay errores para ser corregidos

y aquí era una esperanza que no encontré información sobre la carga automática de la historia en el indicador MT4

Básicamente, si usted quiere garantizar la descarga de todo el historial en MT4 y sin controles adicionales, entonces es más fácil de usar el código dfix - escribir el bar datetime t=0 en el archivo .hst;

 
Igor Makanu:

¿Cómo sugieres que vea tu código?

Creía que sólo necesitabas que el historial se cargara automáticamente...

 

Muy a mi pesar, tengo que volver a tratar el tema de la obtención de datos de TF senior en MT4 una vez más. Esta vez debido a que las técnicas sugeridas aquí no funcionaron.

Este es el código que utilizamos:

#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 los datos de paginación como me aconsejaron:

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

[SERVICESDESK] ¡Error al obtener la hora de la TF más antigua en el temporizador!

Slava, 2018.09.27 06:20

Se ha discutido muchas veces. 12 páginas en "error 4066".

Y te han aconsejado correctamente que envíes la solicitud en OnInit y la analices en OnCalculate.

¿Para qué necesitas un temporizador de milisegundos? Está impidiendo que el terminal del cliente se inicie normalmente. No son los mensajes del viento los que interfieren con tu temporizador, es tu temporizador el que interfiere con todos. Una vez más: LOS INDICADORES EN EL TERMINAL MT4 DEL CLIENTE TRABAJAN EN POTENCIA DE INTERFAZ.

La implementación es exactamente así: la primera solicitud de datos tiene lugar en OnInit(). Luego, esperamos a que se establezca la conexión con el servidor de comercio, entonces en OnCalculate()! obtenemos los datos del TF alto. Hoy tenemos el resultado en el primer lanzamiento:

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

Como podemos ver en el registro, obtuvimos valores erróneos de la hora y la hora del día.

Sí, los desarrolladores(@Slava) pueden notar que no he aplicado todos los consejos que me dieron. Es decir, sigo ejecutando el temporizador rápido en OnInit(), aunque originalmente me aconsejaron ejecutar el temporizador lento. Sin embargo, en este caso, se hace a propósito. Si el temporizador rápido se inicia en el hilo de la interfaz y puede ralentizar la recuperación de datos de otros indicadores - esto es un gran problema. La documentación no contiene ninguna advertencia al respecto, se puede poner un programa con un temporizador rápido que puede convertirse en una especie de "virus" y causar "averías" de otros programas.

En vista de lo anterior, creo que deberíamos introducir restricciones al temporizador de milisegundos o especificar en la documentación de EventSetMillisecondTimer() que la función no puede iniciarse en OnInit() para permitir que el terminal se levante normalmente en el arranque.

 
Hoy en la apertura del día la situación es similar, el error se ha repetido. Banco de pruebas: un gráfico, tres indicadores en él. Dos no utilizan temporizador, el tercero sí. Todos han recibido datos incorrectos al cargar. Ahora he quitado el indicador que utiliza un temporizador del gráfico y veré qué pasa.
 

Ahora viene la parte divertida. El código no tiene temporizadores:

#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 );
  }
//+------------------------------------------------------------------+

Y sigues sin conseguir el resultado que quieres. Los desarrolladores(@Slava), por favor, comenten. Es imposible obtener datos correctos cuando se carga el terminal desde varios TFs superiores. La condición obligatoria es que el terminal debe estar apagado más de una hora después del apagado (porque obtenemos los datos de la barra durante una hora). Y, por supuesto, el arranque en TF menos de una hora.

El temporizador resultó no estar involucrado.
 
Alexey, estás consultando los datos de los TFs mayores en el Inite. Todavía no hay conexión, lo más probable es que haya devuelto un error. Intenta hacer una petición con la primera garrapata que llega.
No puedo comprobarlo, estoy en el campo y no me he traído la tablet.
Razón de la queja: