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

 

Características de las estructuras heredadas

struct A
{
private: 
  int i;
};

struct B : public A
{
  int i; // A::i в private, поэтому никакого пересечения по именам
};

void OnStart()
{
  A a;
  B b;
  
  Print(sizeof(a)); // 4
  Print(sizeof(b)); // 8 - при любом наследовании размер только увеличивается
  
  // Кастинг в обе стороны без union
  a = b;
  b = a;
}
 

Si quiere saber si la bandera "Ilimitado" está activada en Configuración --> Gráficos --> Barras máximas en la ventana, utilice esta construcción:

   int max_bars=TerminalInfoInteger(TERMINAL_MAXBARS);
   if(max_bars<1 e7)
     {
      Print("Макс.баров в окне должно быть Unlimited!");
      return false;
     }
 

Cuando no quiero que un método público se ilumine (al escribir un punto después del nombre del objeto, por ejemplo), hago que este método sea un operador público. Sin embargo, no siempre es posible utilizar esa muleta.

 
fxsaber:

Cuando no quiero que un método público se ilumine (al escribir un punto después del nombre del objeto, por ejemplo), hago que este método sea un operador público. Sin embargo, no siempre es posible utilizar esa muleta.

¿Hay algún ejemplo en el código? Por favor.

 
Artyom Trishkin:

¿Hay algún ejemplo en el código? Por favor.

struct A
{
private:  
  int Value;
  
public:
  int GetValue( void ) const
  {
    return(this.Value);
  }
};

struct B : public A
{
private:
  // Делает доп. расчеты
  void AddCalculate( void )
  {
    Print(__FUNCSIG__);
  }
  
public:
  // Так "спрятали" метод доп. расчетов
  void operator ~( void )
  {
    this.AddCalculate();
  }
};

void OnStart()
{
  A a;
  B b;
  
  b = a; // После присвоения требуется вызвать доп. расчеты.
  
  ~b;    // Провели доп. расчеты
  
  b.GetValue(); // После точки попрежнему виден только GetValue()
}
 

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

Peculiaridades del lenguaje mql5, sutilezas y trucos

fxsaber, 2017.09.08 13:20

struct A
{
private:  
  int Value;
  
public:
  int GetValue( void ) const
  {
    return(this.Value);
  }
};

struct B : public A
{
private:
  // Делает доп. расчеты
  void AddCalculate( void )
  {
    Print(__FUNCSIG__);
  }
  
public:
  // Так "спрятали" метод доп. расчетов
  void operator ~( void )
  {
    this.AddCalculate();
  }
};

void OnStart()
{
  A a;
  B b;
  
  b = a; // После присвоения требуется вызвать доп. расчеты.
  
  ~b;    // Провели доп. расчеты
  
  b.GetValue(); // После точки попрежнему виден только GetValue()
}

¿No es esto

class A
{
 private:
 void AddCalculate(void) const
  {
   Print(__FUNCSIG__);
  }
 public:
 int GetValue(void) const
  {
   this.AddCalculate();
   return(0);
  }
 
};
¿No es esto lo mismo?


 
Alexey Viktorov:

Y esto.

¿No es lo mismo?

No, claro que no. Campos Valor1, Valor2, ... son muchos; GetValue1() y GetValue2() son los mismos. No es racional realizar cálculos adicionales en cada GetValue. No tiene sentido realizar cálculos incluso en un GetValue llamado más de una vez.

 

No he podido averiguar cómo poder establecer el tamaño de un campo de matriz de una estructura simple. Así que hice esta muleta.

// Простая структура - не имеет сложных объектов
template <typename T>
struct STRING // : public T
{
  int i;
  uchar Array[sizeof(T) - sizeof(int)];

  void operator =( const string Str )
  {
    StringToCharArray(Str, this.Array);    
  }
  
  template <typename T1>
  void operator =( const T1 &Str )
  {
    ArrayCopy(this.Array, Str.Array);
  }
  
  string ToString( void ) const
  {
    return(CharArrayToString(this.Array));
  }

// много методов, работающих с this.Array и this.i
// ....

};

#define  SET_STRING(SIZE) \
  struct STRUCT##SIZE    \
  {                      \
    uchar Array[SIZE];   \
  };                     \
                         \
  STRING<STRUCT##SIZE>

void OnStart()
{  
  SET_STRING(20) Str[1];  // Массив "строк", каждая длиной 20 байтов
  SET_STRING(50) Str2[2]; // Массив "строк", каждая длиной 50 байтов
  
  Str[0] = "Hello World!";
  Str2[0] = Str[0];
  
  Print(sizeof(Str));
  Print(sizeof(Str2));
  
  Print(Str[0].ToString());
  Print(Str2[0].ToString());
}


Usé macros, para abreviar. En MQL5 probablemente no hay otra manera. ¿Es esta una solución normal en C++? Como la plantilla <typesize S>.

 

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

Bibliotecas: MT4Orders

fxsaber, 2017.09.14 08:52

El disparador SL/TP fue publicado en el foro incluso antes de las banderas MQL5 Reason. Su lógica mostraba claramente que cuando los niveles SL/TP/SO de una posición abierta son aceptados por el servidor de operaciones, la orden de mercado correspondiente se genera y está en la tabla de órdenes abiertas de MT5 hasta que se ejecuta.


Por lo tanto, en MT5, incluso en MQL5 puro, la modificación/eliminación de dichas órdenes no es posible, y la lógica de trading en MT5 requiere comprobar si una orden abierta está realmente congelada o no.


// Триггер SL/TP/SO
void OnTradeTransaction ( const MqlTradeTransaction &Trans, const MqlTradeRequest &Request, const MqlTradeResult &Result )
{ 
  if ((Trans.type == TRADE_TRANSACTION_ORDER_ADD) && OrderSelect(Trans.order))
  {
    const ENUM_ORDER_REASON Reason = (ENUM_ORDER_REASON)OrderGetInteger(ORDER_REASON);
    
    if (Reason == ORDER_REASON_TP)
      Print("Position #" + (string)Trans.position + " - triggered TP.");    
    else if (Reason == ORDER_REASON_SL)
      Print("Position #" + (string)Trans.position + " - triggered SL.");    
    else if (Reason == ORDER_REASON_SO)
      Print("Position #" + (string)Trans.position + " - triggered StopOut.");    
  }
}


...Podemos ver que durante más de un cuarto de segundo la orden TP estuvo colgada entre las abiertas. Cualquier intento de modificar/borrarlo habría provocado errores.

Tenga en cuenta esta característica de MT5.

 
fxsaber:

Cuando no quiero que un método público se ilumine (al escribir un punto después del nombre del objeto, por ejemplo), hago que este método sea un operador público. Sin embargo, no siempre es posible utilizar esa muleta.

En realidad es una especie de mega muleta. ¿Cómo va a analizar más tarde su código que contiene operadores tan poco informativos que no puede entender lo que hacen?

Debe ser un error de diseño. Si una clase no está pensada inicialmente para ser modificada desde el exterior, sino que sólo contiene métodos Get, debería ser la misma. Todas las modificaciones se realizan a través de las clases que se heredan de él.

Otra variante conveniente sería la herencia protegida, cuando la clase base contiene todos los métodos y la clase heredada muestra sólo los métodos Get. Y cuando sea necesario, puedes lanzarlo a la clase base. Pero el Metaeditor aún no ha corregido el error, todos estos métodos serán volcados a la lista aunque no estén disponibles.

No es racional hacer cálculos adicionales en cada GetValue. Incluso un GetValue llamado más de una vez no necesita realizar cálculos.

Entonces, ¿qué le impide utilizar el método Recalcular()? Si eso es lo que hace que la clase funcione lógicamente, porque la propia clase no puede definir cuándo es necesario recalcular, significa que la clase está controlada por un usuario.