Aprender y escribir juntos en MQL5 - página 35

 

¿Quién sabe si puedo pasar una función a un no miembro de una clase como argumento a una referencia (dirección) a otra función que no es miembro de ninguna clase?

O bien, ¿puedo pasar a una función miembro de una clase como argumento una referencia (dirección) a otra función que no es miembro de ninguna clase?

Документация по MQL5: Основы языка / Типы данных / Структуры и классы
Документация по MQL5: Основы языка / Типы данных / Структуры и классы
  • www.mql5.com
Основы языка / Типы данных / Структуры и классы - Документация по MQL5
 
victorg:

¿Quién sabe si puedo pasar una función a un no miembro de una clase como argumento a una referencia (dirección) a otra función que no es miembro de ninguna clase?

O bien, ¿puedo pasar a una función miembro de una clase como argumento una referencia (dirección) a otra función que no es miembro de ninguna clase?

No. No.

No se puede. En MQL5 no existe la noción de "una dirección de función" o "una referencia de función".

 

Gracias.

Otra pregunta.

Hay dos archivos con código en mql5.El primer archivo es el principal - indicador o script. El segundo archivo esmqh.

// f_01.mqh
double extfunc(int a);
//-------------------------------------
double example(void)
  {
  double a;
  a=extfunc(35);
  return(a);
  }
//-------------------------------------
Elsegundo archivomqh se conecta al principio con el principal. La compilación del archivo principal transcurre sin errores ni advertencias. Pero cuando trato de compilar el archivo mqh por separado me sale ' function must have a body'.Mi pregunta es, ¿cómo puedo decirle al compilador que no hay nada malo con la función, pero su cuerpo está en un archivo diferente?


Документация по MQL5: Файловые операции / FileMove
Документация по MQL5: Файловые операции / FileMove
  • www.mql5.com
Файловые операции / FileMove - Документация по MQL5
 
victorg:

Elsegundoarchivo mqh se incluye al principio del archivo principal. La compilación del archivo principal transcurre sin errores ni advertencias. Pero al intentar compilar el archivo mqh por separado obtenemos ' la función debe tener uncuerpo '.Mi pregunta es: ¿cómo decirle al compilador que no hay nada malo en la función pero que su cuerpo está en un archivo diferente?
No hay manera. No lo destroces, no facilita la comprensión al leer el código.
 
Yedelkin:

Puede que esté exagerando, pero aquí hay otra pregunta. Antes de enviar una solicitud para colocar una orden de mercado (para abrir una posición), pongo a cero un ticket de operación, es decir, hago que result.deal=0. ¿Podemos esperar que el servidor devuelva un ticket de operación nulo en la estructura de respuesta MqlTradeResult, pero que un poco más tarde se ejecute la operación y se abra la posición? ¿O la devolución de un ticket de operación nulo por parte del servidor garantiza que la posición no pudo ser abierta y no se abrirá más en base a esta solicitud?

OK, debido a la falta de respuesta y en virtud de esta línea

struct MqlTradeResult
{
ulong deal; // Billete para repartir, si se hizo
};

Concluyo que la devolución de un ticket de transacción nulo por parte del servidor garantiza que la posición no puede ser abierta y no se abrirá más en base a esta solicitud.

 

No entiendo muy bien la estructura del foro, si no está ahí, por favor diríjanme en la dirección correcta

Dado que no soy un especialista, pero me interesa la programación y procediendo desde mis propias inclinaciones en el proceso de formación, estoy tratando de entender mediante el análisis del código existente

Para simplificar, he cogido un trozo de código personalizado de MA , e intento entender lo que ocurre en él (lo he reflejado en los comentarios)

En general, si no es difícil, por favor, comentar el código, quiero entender lo que sucede después de cada comando. Gracias.

void CalcularSimpleMA(int tarifas_total,int prev_calculado,int inicio,const double &precio[])//Lo he calculado &precio[].

  {
   int i,limit;
//--- first calculation or number of bars was changed
   if(prev_calculated==0)// first calculation
     {
      limit=InpMAPeriod+begin;                                               //почему переменная begin=0 ???
      //--- set empty value for first limit bars
      for(i=0;i<limit-1;i++) ExtLineBuffer[i]=0.0;                            //здесь инициализируются значения индикатора на барах с индексами от 0 до limit-1 ??? крайне правых на графике???
      //--- calculate first visible value
      double firstValue=0;                                                    //при инициализации переменной имеющей тип double не обязательно использовать значения типа double???
      for(i=begin;i<limit;i++)
         firstValue+=price[i];                                               //разобрался, здесь идет накопление переданной цены
      firstValue/=InpMAPeriod;
      ExtLineBuffer[limit-1]=firstValue;                                      
     }
   else limit=prev_calculated-1;                                              //в результате чего prev_calcutated не должно равняться 0, если индикатор поместили на оффлайн график?
//--- main loop
   for(i=limit;i<rates_total && !IsStopped();i++)                              //цикл для индикатора на баре с индексами от limit до последнего на графике
      ExtLineBuffer[i]=ExtLineBuffer[i-1]+(price[i]-price[i-InpMAPeriod])/InpMAPeriod;
//---
  }

lo pongo en la impresión y veo que los valores en el ExtLineBuffer se asignan desde el índice límite-1hasta el índice tasas_total-1, pero en el gráfico el indicador se dibuja en todo el espacio, hmm, entonces ¿dónde está la asignación de valores al buffer del indicador en el intervalo de 1 a límite-1?

Документация по MQL5: Основы языка / Операции и выражения / Операции присваивания
Документация по MQL5: Основы языка / Операции и выражения / Операции присваивания
  • www.mql5.com
Основы языка / Операции и выражения / Операции присваивания - Документация по MQL5
 
Profi_R:

No entiendo muy bien la estructura del foro, si no está ahí, por favor diríjanme en la dirección correcta

Dado que no soy un especialista, pero me interesa la programación y procediendo desde mis propias inclinaciones en el proceso de formación, estoy tratando de entender mediante el análisis del código existente

Para simplificar, he cogido un trozo de código personalizado de MA , e intento entender lo que ocurre en él (lo he reflejado en los comentarios)

Quiero entender lo que sucede después de cada comando. Gracias.

No comentaré en detalle, puede ser suficiente para corregir el error básico de tu percepción, y luego tú mismo armarás el rompecabezas, eso es mucho más útil.

Entonces, la base de tu confusión es que muchos indicadores en mql5 (este en particular) están escritos sin indexar los buffers de los indicadores, es decir, con el valor AsSeries=false.

Significa que el índice de la barra más antigua del historial = 0 y la más "fresca" = RatesTotal-1.

// ¿Está claro algo?

El objetivo de este enfoque es ganar algo de velocidad, ya que la indexación no requiere un recálculo [oculto] al acceder al buffer (sigue siendo "hardware")

// Tal vez la creencia (errónea) de que la indexación para los búferes de los indicadores se produce SIEMPRE desde el final de la historia hasta el principio. Esto es siempre cierto en mql4, pero no es necesario en mql5.

// Aquí, la dirección de la indexación es siempre desde el principio de la historia hasta su final por defecto. Para invertir la indexación, debe utilizar la función SetAsSeries(...) de forma explícita.

// Nota, los desarrolladores no recomiendan utilizar los valores por defecto (en caso de que cambien) y utilizar SIEMPRE la función SetAsSeries() para establecer la dirección de indexación.

void CalcularSimpleMA(int tarifas_total,int prev_calculado,int inicio,const double &precio[])//ordené &precio[]

lo pongo en la impresión y veo que los valores en el ExtLineBuffer están asignados desde el índice límite-1hasta el índice tasas_total-1, pero en el gráfico el indicador se dibuja en todo el espacio, hmm, entonces ¿dónde está el valor asignado al buffer del indicador en el intervalo de 1 a límite-1?

Creo que puedes averiguarlo por tu cuenta, pero por si acaso, mañana lo volveré a comprobar.
 
MetaDriver: ..

Gracias por sus comentarios).

He leído sobre el orden de la directividad en los arrays y las recomendaciones de especificar explícitamente la directividad en la ayuda, pero tenía algunas dudas, que se han eliminado después de la desinstalación de los datos intermedios en las variables.

Hasta ahora, sólo se determina la direccionalidad, es decir, el comentario sobre la inicialización era incorrecto y los valores del búfer del indicador se inicializan en el rango especificado en el lado izquierdo del gráfico.

Todavía hay preguntas sobre

1. la variable begin, ¿es el terminal responsable de su valor pasado al manejador de eventos?

2. ¿se puede pasar una variable de tipo double a tipo int?

3. parece que el terminal también es responsable del valor de la variable prev_calculado

4. no está claro dónde tiene lugar el cálculo del indicador en el intervalo de 0 a límite-1

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
Основы языка / Функции / Функции обработки событий - Документация по MQL5
 
Profi_R:

Todavía hay preguntas sobre

1. la variable begin, ¿es el terminal responsable de su valor enviado al manejador de eventos?

3. parece que el valor de la variable prev_calculado también es responsable del terminal

Lo más probable es que la función en cuestión haya sido escrita para la primera forma de llamada a la función OnCalculate(). Véase la referencia.

Profi_R:

Todavía tenemos preguntas sobre

2. ¿Se puede sustituir una variable de tipo double por un valor de tipo int?

Sí, puedes hacerlo. Véase la sección sobre la conversión implícita de tipos. El compilador a menudo dará una advertencia sobre la posible pérdida de datos cuando se utiliza la conversión de tipo implícita.

Profi_R:

Todavía hay preguntas sobre

4. No entiendo dónde se calcula el indicador en el intervalo de 0 a límite-1.

¿Estas líneas responden a su pregunta?

//--- set empty value for first limit bars
      for(i=0;i<limit-1;i++) ExtLineBuffer[i]=0.0;                            
//--- calculate first visible value
... и далее по коду
?
 
Profi_R:

Gracias por sus comentarios).

He leído sobre el orden de la directividad en los arrays y las recomendaciones de especificar explícitamente la directividad en la ayuda, pero tenía algunas dudas, que se han eliminado después de la desinstalación de los datos intermedios en las variables.

Hasta ahora, sólo se determina la direccionalidad, es decir, el comentario sobre la inicialización era incorrecto y los valores del búfer del indicador se inicializan en el rango especificado en el lado izquierdo del gráfico.

DE ACUERDO.

Todavía hay preguntas sobre

1. la variable begin, ¿es el terminal responsable de su valor enviado al manejador de eventos?

Sí, el terminal es responsable de su transmisión al indicador.


Este parámetro indica al indicador cuántos valores históricos iniciales de la serie de entrada deben ser ignorados (saltados), porque son incorrectos y no deben participar en los cálculos. ¿De dónde puede venir esa incorrección, cuál es su origen? Está relacionado con la posibilidad de crear indicadores que se calculen no sobre los datos del precio, sino sobre los datos proporcionados por otros indicadores. En MT5 hay tres mecanismos que permiten recibir datos de otro indicador para la entrada de un indicador.

Método 1. secuencia de pasos:

Cree un asa para el indicador de entrada utilizando una de las funciones iIndicator(...) o IndicatorCreate(...).

2. según sea necesario, tomar sus valores de sus buffers utilizando la función CopyBuffer(...).

La segunda forma. Es necesario si en el primer caso queremos pasar no una serie de precios, sino una serie de indicadores al indicador de entrada . Es decir, en este caso vamos a recibir los valores calculados por el indicador de entrada (2) que toma los datos de otro indicador (1) en su propia entrada. Es decir, queremos construir la cadena indicador-total-indicador.

Secuencia de pasos:

1. crear un manejador para el primer (1) indicador de entrada utilizando una de las funciones iIndicator(...) o la función IndicatorCreate(...).

2. crear un manejador del segundo (2) indicador utilizando el mismo método, pero especificando el manejador del primero (1) como último parámetro(applied_price) al crearlo.

Utilice la función CopyBuffer(...) para recuperar sus valores de los buffers de los indicadores según sea necesario.

El tercer método también se utiliza para construir cadenas de indicadores, pero, a diferencia del método anterior, la fuente de datos (secuencia de entrada) no se fija antes de la compilación, sino que puede ser establecida por un usuario directamente en el terminal, especificando el parámetro adecuado en el momento de iniciar el indicador.

Le dejaré que entienda estos mecanismos por sí mismo. He proporcionado muchos enlaces directos en el texto anterior a los lugares clave de la documentación que le ayudarán a hacerlo.

Centrémonos sólo en los parámetros de la forma corta de la llamada de OnCalculate():

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])

Su propósito está claramente documentado. Aquí sólo quiero explicar la propia necesidad (razonabilidad) de pasarlos a esta función. Con el primer y el último parámetro, espero que todo quede suficientemente claro. Para realizar los cálculos, debemos tener un buffer con datos de entrada (precio[]) y conocer su longitud actual . (no olvides que su longitud aumenta a medida que las comillas llenan el terminal).

Pero además, debemos saber desde el principio de la fila de entrada que sus datos son estrictamente correctos o que los valores iniciales deben ser ignorados debido a su (posible o garantizada) incorrección. En la mayoría de los casos, la incorrección está garantizada cuando los datos de entrada son la salida de otro indicador, pero ¿cómo si no? La mayoría de los indicadores, para calcular el valor en cualquier barra, deben utilizar una cierta cantidad de datos históricos. Pero, ¿dónde pueden encontrarse "al principio del tiempo"? No están presentes allí, y por lo tanto se ven obligados a empezar a generar sus valores de salida no desde la barra histórica inicial, sino más tarde (a la derecha), desde la barra a la izquierda de la cual ya existe la cantidad necesaria de datos históricos.

Ahora, gracias a los detalles que he descrito anteriormente, la respuesta a la pregunta

¿de dónde viene su valor? // estamos hablando del parámetro begin

La respuesta es: a pesar de que este parámetro es pasado en la función por el terminal, ¡el indicador de entrada debe ocuparse de su contenido! El propio terminal puede comprobar sólo las filas de entrada de precios (en este caso el valor de begin será 0 y este es un valor correcto).Por lo tanto, cuando escriba cualquier indicador (excepto los puramente experimentales), debe asegurarse de que informa al terminal sobre el índice del comienzo de los datos correctos en su búfer de salida ¿Está claro? De lo contrario, los "descendientes" de este indicador pueden comer datos incorrectos muy desagradables y, en algunos casos, incluso pueden enfermar... :) Ahora, cómo hacerlo, se utiliza la función PlotIndexSetInteger(), especificando el identificador de la propiedad PLOT_DRAW_BEGIN. ¡Importante! Para que la propiedad del indicador generado sea 100% correcta, se debe hacer una sola llamada a PlotIndexSetInteger(....PLOT_DRAW_BEGIN, ...) en OnInit() ¿Por qué? Porque nuestro indicador puede formarse a su vez sobre los datos de otro indicador, que tiene una sangría inicial en el historial. Es decir, tenemos un valor no nulo de begin en el historial de entrada, y no hay posibilidad de recibirlo en OnInit().

  PlotIndexSetInteger(MySymbol,PLOT_DRAW_BEGIN,MyBeginPeriod-1+begin);

Y tenemos que hacerlo (preferiblemente una vez) en OnCalculate(), porque en OnInit el valor de begin es desconocido.

Lo que, por supuesto, nos deja con el derecho de hacer una llamada preliminar (aunque no muy significativa) también

  PlotIndexSetInteger(MySymbol,PLOT_DRAW_BEGIN,MyBeginPeriod);

en OnInit().

Esto es exactamente lo que se hace en ese indicador (Custom Moving Average.mq5) del que tomaste la muestra para estudiar.

2. ¿puede una variable de tipo double ser de tipo int?

Sí, una variable de tipo double puede ser inicializada sin problemas con un valor de tipo int, si está definida por una constante. // que es exactamente lo que podemos hacer en su ejemplo.

3. Parece que el terminal también es responsable del valor de la variable prev_calculado

Aquí hay una sutileza. En la mayoría de los casos, este valor será igual al valor devuelto por la función OnCalculate() en la llamada anterior. En otras palabras, de hecho, está en sus manos. :) Por otro lado, en la primera llamada habrá un valor cero. Y además, el valor puede ser puesto a cero (por el terminal) siempre, cuando el terminal lo quiera. Por ejemplo, esto puede ocurrir durante la corrección de las cotizaciones por parte de un corredor, durante el reinicio de la comunicación después de una pausa, durante la reinicialización de un indicador anterior (de entrada), etc.

4. no está claro en qué punto del intervalo de 0 a límite-1 se calcula el indicador

En este caso, estos valores no se pueden calcular correctamente (no tenemos suficiente historial para los cálculos), por lo que simplemente se les asigna un valor cero.

// Preferiría asignarles los datos de entrada correspondientes, pero eso no cambia la esencia del asunto.

Razón de la queja: