Características del lenguaje mql5, sutilezas y técnicas - página 31

 
Artyom Trishkin:

¿Has mirado siquiera el código que te estoy mostrando? ¿Lo has hecho?

No estaba preguntando cómo llenar el buffer del indicador, sino por qué se devuelven valores vacíos si tomo valores de AO no de la barra actual.
Lo tengo - no hay historia, se está cargando, y mientras se carga AO de un marco de tiempo no nativo devuelve el error "no hay datos".

Quiero comprobar si el historial está completamente cargado para no entrar en el ciclo del indicador.

Si utiliza CopyBuffer en el indicador para recibir datos de otro indicador, debe

  1. Voltee el búfer del indicador para que la barra más a la derecha del gráfico corresponda al índice "0" en el búfer del indicador.
  2. Así, "la barra actual" en el indicador "iMTF_AO.mq5" será la BARRA MÁS A LA DERECHA del gráfico, y corresponderá al índice "0" en el buffer del indicador "Buffer[]"
  3. Y para obtener la "barra actual" del indicador (CopyBuffer(handle,0,shift,1,array)) el parámetro "shift" debe ser igual a "0".

Si no quiere voltear el buffer del indicador, haga esto (temporalmente): AO(0) - para entender cómo obtener valores de otro indicador desde un INDICADOR. Es posible que obtenga un error una o dos veces, pero eso es hasta que se construya la serie temporal, y entonces los valores serán estables.

 
Artyom Trishkin:
¿Has visto mi respuesta? ¿Lo has probado?
 
Vladimir Karputov:

Si utilizas CopyBuffer en un indicador para recuperar datos de otro indicador, debes:

  1. Invierta su buffer de indicadores para que la barra más a la derecha del gráfico corresponda al índice "0" en el buffer de indicadores.
  2. Así, "la barra actual" en el indicador "iMTF_AO.mq5" será la BARRA MÁS A LA DERECHA del gráfico, y corresponderá al índice "0" en el buffer del indicador "Buffer[]"
  3. Y para obtener la "barra actual" del indicador (CopyBuffer(handle,0,shift,1,array)) el parámetro "shift" debe ser igual a "0".

Si no quiere voltear el buffer del indicador, haga esto (temporalmente): AO(0) - para entender cómo obtener valores de otro indicador desde un INDICADOR. Es posible que obtenga un error una o dos veces, pero eso es hasta que se construya una serie temporal, y entonces los valores serán estables.

1. Mi código lo tiene, y estaba allí de inmediato:

   ArraySetAsSeries(Buffer,true);
   int bars=Bars(NULL,PeriodForWork);
   datetime time_limit=GetTime(Symbol(),PeriodForWork,bars-1);
   int limit_p=GetBarShift(Symbol(),Period(),time_limit);
   if(rates_total<1) return(0);

2. lo hace.

3. el desplazamiento es igual al índice del ciclo i. Y el bucle va desde el principio de los datos históricos (rates_total-1) hasta el final (hasta los datos actuales)

Otra cuestión es que debemos calcular estos datos con respecto a un TF no nativo para no obtener datos de barras perdidas. Y tenemos que determinar antes del ciclo que la historia de la TF deseada está totalmente sincronizada.

 
Artyom Trishkin:

1. Mi código lo tiene, y lo tuvo enseguida:

2. Es lo que hay.

3. el desplazamiento es igual al índice del ciclo i. Y el bucle va desde el principio de los datos históricos (rates_total-1) hasta el final (a los datos actuales)

Otra cuestión es que tenemos que calcular estos datos en relación con un marco temporal no nativo para no obtener datos de las barras que faltan. Y debemos determinar antes del bucle que el historial del marco temporal necesario está completamente sincronizado.


Reformular el bucle para llamar a AO: poner de "0" a algún valor (ahora de algún valor a cero). Cuando se producen los errores - comparar a la vez: el número de barras calculadas ("limit_p") y rates_total del indicador actual.


Añadido: y aquí estas líneas borran todos los esfuerzos de "límite" calculado (si nos referimos al marco temporal no nativo):

   if(limit>1) 
     {
      limit=rates_total-1;
     }

A grandes rasgos, al principio (cuando se accedía a un marco temporal no nativo) "límite" era igual a 156, pero por debajo de BACK! y "límite" se convertía en "154566666666".



 
Alexey Kozitsyn:
¿Has probado la sincronización? Además, los desarrolladores aconsejan mantener actualizados los datos del TF/símbolo requerido a través del temporizador.

No, aún no lo he probado. He visto sobre el apoyo de la relevancia de los datos, recuerdo - lo sé.

Pero inicialmente es necesario salir de OnCalculate() si los datos de la fecha especificada y la fecha actual no están sincronizados todavía.

Entiendo lo de la actual:

if(rates_total<1) return(0);

Sobre dado - es necesario comprobar su Bars() - su número en lugar de rates_total.

Pero no sé sobre el límite - se puede comprobar en el marco de tiempo actual (como un ejemplo de otro indicador):

   int limit=rates_total-prev_calculated;
   if(limit>1) {
      limit=rates_total-4;
      ArrayInitialize(BufferAoDN,EMPTY_VALUE);
      ArrayInitialize(BufferAoUP,EMPTY_VALUE);
      ArrayInitialize(BufferMacdDN,EMPTY_VALUE);
      ArrayInitialize(BufferMacdUP,EMPTY_VALUE);
      ArrayInitialize(BufferRsiDN,EMPTY_VALUE);
      ArrayInitialize(BufferRsiUP,EMPTY_VALUE);
      ArrayInitialize(BufferStochDN,EMPTY_VALUE);
      ArrayInitialize(BufferStochUP,EMPTY_VALUE);
      }

Pero en este indicador de prueba obtenemos datos tanto del marco temporal actual (muestra los cálculos en OnCalculate()) como del especificado - para obtener datos de AO del marco temporal especificado.

Todavía no recuerdo cómo calcular todos los datos necesarios para el número de barras - porque el bucle debe comenzar con la barra correspondiente al tiempo de la barra de la historia con los primeros datos existentes de la actual o la especificada - donde es menos - a partir de esa barra comenzamos el bucle. El límite también debería calcularse correctamente para detectar la aparición de una nueva barra, lo que debería llevar a un recálculo completo o a un recálculo de la barra actual solamente (dependiendo de lo que haya ocurrido: la apertura de una nueva barra o la carga del historial).

Tal vez, estoy tratando de pensar en todo a la vez, y pienso en un montón de cosas innecesarias...

 
Vladimir Karputov:


Reformular la llamada del bucle a AO: poner de "0" y a algún valor (ahora de algún valor a cero). Cuando se produzcan errores - compare a la vez: el número de barras calculadas ("limit_p") y rates_total del indicador actual.


Añadido: y estas líneas borran todos los esfuerzos del "límite" calculado (si se refiere a un marco temporal no nativo):

A grandes rasgos, al principio (al dirigirse a un marco temporal no nativo) "límite" se convirtió en 156, y por debajo de BATCH! y "límite" ya se convirtió en "154566666666"

Sí, lo escribí enseguida que metí la pata aquí a toda prisa.

Pero no voy a cambiar el bucle - hay un indicador bastante complicado en el que todo se construye en el cálculo de la historia desde el principio hasta el final - es más fácil volver a calcular los límites y obtener los datos que reescribir todo el indicador - toda su lógica.

 
Artyom Trishkin:

No, aún no lo he probado. He visto sobre el apoyo de la relevancia de los datos, recuerdo - lo sé.

Pero inicialmente es necesario salir de OnCalculate() si los datos de la fecha especificada y la fecha actual no están sincronizados todavía.

El actual está claro:

No es exactamente así. Cuando cargue inicialmente el terminal con el indicador puede que no obtenga lo que espera. Durante el día y si hay interrupciones en la conexión, también puede haber errores.

Sobre la salida de OnCalculate(): La primera petición Bars() debe hacerse en la etapa de inicialización, luego en OnCalculate() comprobar la sincronización de los TFs actuales y necesarios. Si no hay sincronización, abandona.

 
Artyom Trishkin:

Sí, eso es lo que he dicho enseguida, que la he liado parda.

No quiero cambiar el bucle, hay un indicador bastante complicado, que se basa en el cálculo de la historia desde el principio hasta el final - es más fácil volver a calcular los límites y recibir los datos correctamente, que reescribir todo el indicador - toda su lógica.

Artem, ¿qué quieres decir con "desde el principio hasta el final"?

¿Crees que voltear todas las matrices es la mejor salida?

Por qué

ArraySetAsSeries(Buffer,true);

si sólo está copiando un valor?

Cuando se copia la TF que no es la actual, es mejor pasar la hora de la barra necesaria a la función CopyBuffer(). De lo contrario, no copiará la barra que desea.

 
Alexey Viktorov:

1. artyom, ¿qué quieres decir con "desde el principio hasta el final"?

2. ¿Cree que la mejor manera de salir es volteando todas las matrices?

3. Por qué

4. ¿Si sólo copias un valor?

Al copiar el tiempo de la barra requerida a la función CopyBuffer() que no es el marco de tiempo actual, es mejor pasarlo. De lo contrario, no se copiará la barra que quieras.

1. El inicio de los datos históricos es la primera barra del historial con el menor tiempo de apertura, el final de los datos históricos es la barra actual.

2. Estoy copiando de un 4 a un 5.

Pues porque en Buffer[] los datos se escriben en bucle desde rates_total-1 hasta 0. Si no lo hacemos como una serie temporal, se mostrará hacia atrás y hacia delante en el gráfico.

4. Quiero copiar un valor en un momento del tiempo, que corresponde a los datos de la barra i de un marco temporal determinado.

Mira lo lacónico y fácil que es obtener los datos de no el marco temporal actual en mql4. Me pregunto cómo es posible recibir los datos del indicador en mql5 y que no funcione - siempre hay un error 4806 si paso el timeframe que no corresponde al timeframe del gráfico en el que trabaja el indicador en la función de recepción de datos AO.

//+------------------------------------------------------------------+
double GetDataAO(string sy, int timeframe, int shift) {
   double array[1];
   ZeroMemory(array);
#ifdef __MQL4__
   array[0]=iAO(sy,timeframe,shift);
#else 
   ResetLastError();
   if(CopyBuffer(handle_ao,0,shift,1,array)==WRONG_VALUE) {
      Print(__FUNCTION__," > Error: ",GetLastError());
      return(0);
      }
#endif 
   return(array[0]);
}
//+------------------------------------------------------------------+

Al mismo tiempo, en OnInit() se crea el manejador del indicador que corresponde al precio actual del que queremos recibir datos:

handle_ao=iAO(symbol,periodForWork);

Es decir, en cualquier momento, no importa cómo cambiemos la f, el mango se crea con la necesaria (seleccionada en los ajustes)f. Pero los datos de AO sólo pueden obtenerse si la función seleccionada en los ajustes y la función actual coinciden. Si no coinciden, la función siempre devuelve cero.

La pregunta es: ¿por qué?

 
Artyom Trishkin:

1. El inicio de los datos históricos es la primera barra de la historia con el tiempo de apertura más corto, el final de los datos históricos es la barra actual.

2. Estoy reescribiendo de cuatro a cinco.

Pues porque en Buffer[] los datos se escriben en bucle desde rates_total-1 hasta 0. Si no lo hacemos como una serie temporal, se mostrará hacia atrás y hacia delante en el gráfico.

4. Copio un valor a la vez que corresponde a los datos de la barra i del marco temporal dado.

Mira lo conciso y fácil que es obtener los datos no del currentfactor en mql4; es exitoso y todo funciona como estaba previsto. Me pregunto cómo es posible recibir los datos del indicador en mql5 y que no funcione - siempre hay un error 4806 si paso el timeframe que no corresponde al timeframe del gráfico en el que trabaja el indicador en la función de recepción de datos AO.

Al mismo tiempo, en OnInit() se crea el manejador del indicador que corresponde al precio actual del que queremos recibir datos:

Es decir, en cualquier momento, no importa cómo cambiemos la f, el mango se crea con la necesaria (seleccionada en los ajustes)f. Pero los datos de AO sólo pueden obtenerse si la función seleccionada en los ajustes y la función actual coinciden. Si no coinciden, la función siempre devuelve cero.

La pregunta: ¿Por qué?

1. Sólo una aclaración. Ahora entiendo que estamos hablando de lo mismo.

Lo entiendo, pero no estoy de acuerdo en que sea necesario invertir las matrices. ¿Es necesario tener un indicador para dos terminales? Casi como hacer 2en1 una guadaña y un hacha.

3. según tengo entendido Buffer[] es utilizado por el receptor en la función CopyBuffer() para obtener sólo 1 valor de indicador.

4. No has prestado atención a lo más importante. El inicio de la copia del valor del indicador no debe ser determinado por el índice de la barra, sino por el momento de la barra i-ésima.

int  CopyBuffer( 
   int       indicator_handle,     // handle индикатора 
   int       buffer_num,           // номер буфера индикатора 
   datetime  start_time,           // с какой даты 
   int       count,                // сколько копируем 
   double    buffer[]              // массив, куда будут скопированы данные 
   );