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

 
Vitaly Gorbunov:
El método iBarShift permite encontrar agujeros en el historial, pero es necesario comprobar el historial a intervalos. He escrito un procedimiento para mí que hace esto, y después de eso me he olvidado de las lagunas en los programas de MtF.
No se trata de detectar "agujeros". La persona quería obtener el último compás del historial. Y éste no es necesariamente el compás actual en el tiempo.
 
Vitaly Gorbunov:
Los datos se cargan con el error 4066, y luego es la culpa de la metaquotov, lo más probable es que los datos recibidos se procesa para esta situación, el error no fue inventado. Y hasta ahí, todo tiene sentido.

Que un error "no se haya inventado" no significa que no exista.

 
Alexey Navoykov:
No se trata de detectar "agujeros". La persona quería obtener la última barra del historial. Y ésta no es necesariamente la barra de tiempo actual.

No se trata de iBarShift(). Envía los mismos errores que iTime() y SeriesInfoInteger(). La muletilla aquí está en comparar el tiempo obtenido durante la inicialización y luego compararlo con el tiempo del temporizador. Eso es lo que permitió obtener los datos reales correctos al cargar el terminal, no IBarShift().

Sí, y si la hora es las 15:00:45 (por ejemplo), y no hay ningún tick en la barra de las 15:00 todavía y si la hora de apertura de la barra de la última hora es las 14:00 - todo es correcto, creo. Y si el sistema devuelve las 13:00, es un problema.

 
Alexey Kozitsyn:

1. Igor, ¿has mirado el código? ¿De dónde saco algo en OnInit()?

En su caso se ejecutan una o varias llamadas OnTimer justo después de OnInit(). Todavía no hay ningún evento OnCalculate().

2. ¿Qué controles? ¿Dónde está escrito que el indicador debe utilizar OnCalculate() al menos una vez para funcionar correctamente?

Aquí tenemos que entender la lógica del terminal. OnInit() se llama inmediatamente al conectar el indicador al gráfico. Al iniciar el terminal, la conexión del indicador con el gráfico se realiza justo después de crear la ventana del gráfico. En este momento, el terminal ni siquiera ha enviado la solicitud al servidor.

El primer OnCalculate() se llama después de que se hayan leído las cotizaciones disponibles localmente. En algunos casos raros sucede que no hay nada a nivel local. En este caso, al dirigirse a Time[0], los indicadores salen del array. Por lo tanto, es mejor utilizar la función iTime o similar.

El segundo y el siguiente OnCalculate() ocurren en la carga del historial o en la llegada de los ticks reales.

 
Ihor Herasko:

El primer OnCalculate() se llama después de leer las cotizaciones disponibles localmente. En algunos casos raros sucede que no hay nada a nivel local. En este caso, al referirse a Time[0], los indicadores salen del array. Por lo tanto, es mejor utilizar la función iTime o similar.

Supongo que estamos hablando de MQL5, la preparación de OHLC es diferente allí que en MT4

Llevo mucho tiempo escribiendo indicadores basados en una plantilla:

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;
   if(prev_calculated==0)
     {
      limit=rates_total-1;    //--- Первый вызов индикатора или смена таймфрейма или подгрузка данных из истории
     }
   else limit=rates_total-prev_calculated+1;
   for(i=limit;i>=0;i--)      //---- Основной цикл расчета
     {                        
     }
   return(rates_total);
  }

Nunca he tenido un "crash del indicador" en matrices OHLC en MT4, creo que MT4 no ejecutará OnCalculate() hasta que un gráfico esté preparado por primera vez, y si el historial está cargado, no lo he comprobado, pero prev_calculated==0 , en MT5 será como escribiste - necesitas comprobaciones adicionales para ver si los datos OHLC ya están preparados

 
Ihor Herasko:

En su caso se ejecutarán una o más llamadas OnTimer justo después de OnInit(). Todavía no hay ningún evento OnCalculate().

Aquí hay que entender la lógica del terminal. OnInit() se llama inmediatamente al conectar el indicador al gráfico. Al iniciar el terminal, la conexión del indicador con el gráfico se realiza justo después de crear la ventana del gráfico. En este momento, el terminal ni siquiera ha enviado la solicitud al servidor.

La primera llamada a OnCalculate() se realiza después de que se hayan leído localmente las cotizaciones disponibles. En algunos casos raros sucede que no hay nada a nivel local. En este caso, al dirigirse a Time[0], los indicadores salen del array. Por lo tanto, es mejor utilizar la función iTime o similar.

El segundo y el siguiente OnCalculate() ocurren en la carga del historial o en la llegada de los ticks reales.

¿Qué sugieres para resolver el problema (existe, en tu opinión)? ¿Esperar hasta que OnCalculate() sea llamado 1-2 veces?

 
Alexey Kozitsyn:

¿Qué sugieres para resolver el problema (existe, en tu opinión)? ¿Esperar hasta que OnCalculate() sea llamado 1-2 veces?

Puede intentarcopiar el valorprev_calculated==0a una variable en el ámbito global y ver en OnTimer() si el indicador ha sido calculado.OnCalculate() - se calculará en cualquier caso, sospecho que si los datos del TF no estaban listos, entoncesreturn(rates_total) devolverá 0, que será en la siguiente llamada deOnCalculate() signoprev_calculated==0, aproximadamente así:

void OnTimer(){
   if(Global_prev_calculated==0)return;
}
 
Igor Makanu:

puedes intentarcopiar el valorprev_calculated==0a una variable en el ámbito global y ver en OnTimer() si el indicador fue calculado; escribí arriba que nunca vi ningún error con cálculo incorrecto en MT4OnCalculate() - se calculará en cualquier caso, sospecho que si los datos de TF no estaban listos, entoncesreturn(rates_total) devolverá 0, que será en la siguiente llamada deOnCalculate() un signoprev_calculated==0

Parece que la solución más fiable es realmente esperar a la llamada de OnCalculate() con la comprobación obligatoria de la conexión con el servidor de comercio. Si no comprobamos la conexión (IsConnected()), entonces la obtendremos incluso en OnCalculate() cuando se cargue el terminal:

2018.09.21 23:45:27.128 test_isNewDayInOnCalculate_iBarShift() EURGBP.e,M1: test_isNewDayInOnCalculate_iBarShift().mq4: Актуальное время открытия бара М15 = 2018.09.21 21:30. Ошибка #0
2018.09.21 23:45:25.990 test_isNewDayInOnCalculate_iBarShift() EURGBP.e,M1: initialized
2018.09.21 23:45:25.975 Custom indicator test_isNewDayInOnCalculate_iBarShift() EURGBP.e,M1: loaded successfully

Sin embargo, no elimina todos los interrogantes:

1. ¿Por qué no se dice en la documentación de IsConnected() que debe llamarse necesariamente antes de recibir los datos (al menos) del TF superior en OnCalculate()?

2. ¿Por qué no funciona IsConnected() en OnTimer()? ¿No se supone que el hecho de establecer la conexión con un servidor comercial nos indica que se pueden obtener datos?

3. Una vez que hemos establecido una conexión con el servidor de operaciones y estamos intentando recibir datos en OnTimer(), ¿no deberían las funciones iTime(), iBarShift(), SeriesInfoInteger() y funciones similares a ellas devolver errores si los datos de este servidor de operaciones en particular, del que toman información, no están todavía sincronizados? De lo contrario, resulta una tontería: devolvemos el error 4066 una vez y luego utilizamos los datos actuales de la forma que queramos.

 
Alexey Kozitsyn:

Sin embargo, esto no elimina todos los interrogantes:

1. ¿Por qué la documentación de IsConnected() no dice que debe llamarse necesariamente antes de recibir los datos (al menos) del TF superior en OnCalculate()?

2. ¿Por qué no funciona IsConnected() en OnTimer()? ¿No se supone que el hecho de establecer la conexión con un servidor comercial nos indica que se pueden obtener datos?

3. Una vez que hemos establecido una conexión con el servidor de operaciones y estamos intentando recibir datos en OnTimer(), ¿no deberían las funciones iTime(), iBarShift(), SeriesInfoInteger() y funciones similares a ellas devolver errores si los datos de este servidor de operaciones concreto, del que toman información, no están todavía sincronizados? De lo contrario, parece una tontería, como si devolviéramos un error 4066 una vez y luego utilizáramos los datos existentes de la forma que queramos.

1. Bueno, nadie canceló el caso de la llamada del indicador en los datos históricos, si usted necesita para trabajar en línea, a continuación, comprobar la conexión, si no, o más bien no es importante, entonces mi versión de la plantilla funciona. 2. El grupo de la función IsConnected() es realmente un poco complicado, se cruzan IsTradeContextBusy() y IsConnected() sí mismo a veces y IsTradeAllowed()... Creo que hacen trampa en el lado del servidor y desconectan los terminales a la hora de las noticias o alguna otra manipulación

2,3. funciona, pero se olvida que GetLastError() restablecerá su estado después de una llamada y tal vez para actualizar el estado GetLastError() necesita transferir el control a la terminal, tal vez la terminal no tuvo tiempo de restablecer el estado IsConnected() en GetLastError() antes de su llamada desde el timer.... Creo que la función OnTimer() no está pensada para recibir datos: "MQL4 Reference / Status Check" - Se llamará a OnTimer(), pero las variables del entorno de la terminal no se actualizan, yen OnCalculate() se garantiza la preparación de todos los datos de la terminal cuando llega el tick

 
Igor Makanu:

1. bueno, nadie ha anulado el caso de llamar al indicador sobre datos históricos...

2,3. funciona, pero se olvida que GetLastError() restablecerá su estado después de la llamada, y tal vez para actualizar el estado GetLastError() necesita pasar el control a la terminal, tal vez la terminal no tiene tiempo para restablecer el estado IsConnected() en GetLastError() antes de su llamada desde timer.... Creo que la función OnTimer() no está pensada para recibir datos: "MQL4 Reference / Status Check" -OnTimer() será llamado, pero las variables del entorno del terminal no se actualizan, y se garantiza que el terminal preparará todos los datos cuando llegue el tick-OnCalculate().

1. ¿Crees que si el compás número 0 tiene una hora incorrecta, el resto del historial tendrá una hora correcta)?

2,3. Si las funciones de acceso a los datos no tienen tiempo suficiente para establecer algún error significativo, que lo comuniquen de alguna manera, pero desde luego no devolviendo un código de error = 0 (sin error). El resto del "quizás" son sólo conjeturas. Y sin pruebas no hay nada que hablar.

La función OnTimer() no está pensada para obtener datos...

Sin comentarios.

Se llamará a OnTimer() pero las variables de entorno del terminal no se actualizarán necesariamente

¿Para qué necesitamos el error 4066?