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

 
fxsaber:

Este es un problema menor. Sí, el optimizador del compilador aún no sabe cómo optimizar esos momentos de cadena. Pero el problema de la ralentización es la asignación de cadenas.

Creo que es la principal. ¿Qué sería más eficiente: una asignación de cadenas más rápida o su exclusión del código? Claro que hay casos en los que necesitamos la asignación de cadenas en sí, pero ¿con qué frecuencia la necesitamos? En la gran mayoría de los casos, sólo se trata de variables temporales.

Y la rapidez con la que se pueden implementar estas operaciones de cadena también es una cuestión. Lo haces sonar como si se pudiera acelerar muchas veces. Lo dudo. Ya han optimizado-sobre-optimizado todo allí muchas veces. Supongamos que consiguen exprimir otro 20-30%, no supondrá ninguna diferencia.

Por cierto, ¿no intentaste declarar la variable de cadena como constante?

Así que si estás escribiendo algo como esto.

if ((OrderSymbol() == Symb) && (OrderMagicNumber == Magic))

siempre es mejor meter la cláusula OrderSymbol al final de la condición general.

Bueno, por supuesto. Y no tiene nada que ver con OrderSymbol, o MQL. Las operaciones de cadena son costosas por sí mismas, por lo que no deberías usarlas en vano.

 

Y así en medio

fxsaber:

Por ejemplo, si ejecutamos una ejecución de ticks reales en FIBO durante un mes, será de aproximadamente 1 millón de ticks. Si en cada tic obtienes el valor de PositionGetString y lo comparas con algo, el rendimiento será aceptable, pero si primero asignas el resultado de la función a una variable de cadena y luego lo comparas, la duración de la ejecución aumentará aproximadamente un segundo.


Si parece poca cosa, es una visión equivocada. Cuando un EA de este tipo se ejecuta en modo de optimización durante varios miles de pases, ese segundo extra se traduce en horas adicionales de tiempo de espera. Es decir, una asignación de cadena inofensiva puede causar horas adicionales de espera durante la optimización. Tenga cuidado y tenga en cuenta este matiz.

Espero que usted mismo entienda que este enfoque es muy ineficiente. ¿Por qué debemos obtener PositionGetString en cada tic? ¿Qué puede cambiar ahí? Sobre todo teniendo en cuenta que tú mismo abriste esta posición, es decir, que ya se sabe todo de antemano.

Por tanto, si hablamos de optimizar el rendimiento, primero debemos optimizar la propia lógica del programa.

 
Alexey Navoykov:

Y la rapidez con la que se pueden acelerar estas operaciones de cadena también es una cuestión. Lo haces sonar como si se pudiera acelerar muchas veces. Lo dudo. Ya han optimizado-sobre-optimizado todo allí muchas veces. Incluso si consigues exprimir un 20-30% más, no supondrá ninguna diferencia.

A veces.

Por cierto, ¿no has probado a declarar una variable de cadena como una constante?

Sí, lo hice.
 
Alexey Navoykov:

¿Por qué obtener PositionGetString en cada tick? ¿Qué puede cambiar ahí? Sobre todo teniendo en cuenta que tú mismo abriste este puesto, es decir, que ya se sabe todo de antemano.

Pues bien, si hablamos de optimizar el rendimiento, primero debemos optimizar la propia lógica del programa.

Un robot de combate con tal lógica: no debería haber posiciones abiertas en EURUSD en tal intervalo de tiempo. Si hay alguna, ciérrala.

Usted tiene una posición abierta en el GBPUSD. ¿Cómo podemos cumplir la condición anterior sin comprobar OrderSymbol en cada tick?

¿O sugieres escribir una versión especial del Asesor Experto sólo para el probador? Aquí, una persona ha comprado un robot de combate y lo está probando. ¿Cómo explicar en el mercado que todo está optimizado por la velocidad?

 
fxsaber:

Un robot de combate con esta lógica - no debería haber posiciones abiertas en EURUSD en este intervalo de tiempo. Si los hay, ciérralos.

Usted tiene una posición abierta en el GBPUSD. ¿Cómo podemos cumplir la condición anterior sin comprobar OrderSymbol en cada tick?

¿O sugieres escribir una versión especial del Asesor Experto sólo para el probador? Aquí, una persona ha comprado un robot de combate y lo está probando. ¿Debemos escribir en el Mercado que todo está especialmente optimizado por la velocidad para el probador?

Pues bien, basta con comprobar sólo las entradas de las posiciones abiertas en ese momento (y mantener así una matriz de las mismas). Si hay un nuevo billete, hay que realizar todas las demás comprobaciones con él. ¿Por qué debemos comprobar lo mismo un millón de veces?

Por cierto, MQL5 tiene eventos comerciales. Por lo tanto, no es necesario comprobarlo en cada tic.

 
Alexey Navoykov:

Pues bien, basta con comprobar sólo los tickers de las posiciones abiertas actuales (y mantener un array de ellos en consecuencia).

Esto no será mucho más barato.

Y por cierto, MQL5 tiene eventos comerciales. Por lo tanto, no es necesario comprobar cada garrapata.

A veces se escriben soluciones multiplataforma. Además, no existe ni puede existir ninguna garantía de obtener todos los eventos comerciales.

 
fxsaber:

No sería mucho más barato.

La diferencia entre las operaciones con enteros no es mucho más barata que las operaciones con cadenas? Bueno, como quieras.

 
Alexey Navoykov:

La diferencia entre las operaciones con enteros no es mucho más barata que las operaciones con cadenas? Bueno, como quieras.

No veo por qué lo necesitas, pero me has desconcertado. Y tengo que estar de acuerdo en que la opción con una serie de entradas sería más productiva.

Es cierto que, desde el punto de vista de cierta lógica, tal variante parece muy artificial, basada en un matiz técnico, más que en una construcción lógica del programa.

Pero lo tendré en cuenta igualmente. Por supuesto, nunca he encontrado este enfoque en kodobase.

 

La falta de herencia múltiple en MQL es deprimente, por supuesto. Sin embargo, puedes hacer que funcione de cualquier manera posible - con plantillas y macros - no las necesitarás )

Esto es lo que he hecho. Todas las clases fuente deben ser declaradas como plantillas que definen la clase padre.

class CBase { };  // базовый класс

// Макросы, задающие список наследования:

#define  INHERIT1(T)  T<CBase>

#define  INHERIT2(T1, T2)  T2<INHERIT1(T1)>

#define  INHERIT3(T1, T2, T3)  T3<INHERIT2(T1,T2)>

#define  INHERIT4(T1, T2, T3, T4)  T4<INHERIT3(T1,T2,T3)>


// Различные пользовательские классы:

template<typename TParent>
class A : public TParent { public: void a() { Print("A"); } };

template<typename TParent>
class B : public TParent { public: void b() { Print("B"); } };

template<typename TParent>
class C : public TParent { public: void c() { Print("C"); } };


class X : public INHERIT3(A, B, C)  {  };   // Объявляем класс, наследуемый от A, B, C


template<typename T>
void SomeFunc(B<T>& obj)  { obj.b(); }   // Проверочная функция, принимающая класс B


void OnInit()
{
  X x;
  x.a();
  x.b();
  x.c();
  
  SomeFunc(x);
}

Por supuesto, hay algunas sutilezas, relacionadas con el hecho de que las clases se heredan secuencialmente (en el orden que hemos establecido), en lugar de en paralelo (como en la verdadera herencia múltiple). En particular, tendrán diferentes prioridades cuando se produzca una sobrecarga. Además, si una misma clase de plantilla participa varias veces en la cadena de herencia, serán clases completamente diferentes, no relacionadas entre sí de ninguna manera. Así que tenemos que tener cuidado aquí. Pero no hay problema con las interfaces, se puede heredar sin restricciones.

 
Alexey Navoykov:

La falta de herencia múltiple en MQL es deprimente, por supuesto. Sin embargo, puedes hacer que funcione de cualquier manera posible - con plantillas y macros - no las necesitarás )

Esto es lo que he hecho. Todas las clases fuente deben ser declaradas como plantillas que definen la clase padre.

Por supuesto, hay algunas sutilezas, relacionadas con el hecho de que las clases se heredan secuencialmente (en el orden que hemos establecido), en lugar de concurrentemente (como en la verdadera herencia múltiple). En particular, tendrán diferentes prioridades cuando se produzca una sobrecarga. Además, si una misma clase de plantilla participa varias veces en la cadena de herencia, serán clases completamente diferentes, no relacionadas entre sí de ninguna manera. Así que tenemos que tener cuidado aquí. Pero no hay problemas con las interfaces, puedes heredar sin limitaciones.

Es un buen truco. Todo el truco está en aplicar el patrón a TParent. No lo había visto así antes.