Características da linguagem mql5, subtilezas e técnicas - página 54

 

Características das estruturas herdadas

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;
}
 

Se você quiser saber se a bandeira "Unlimited" está ativada em Settings --> Charts --> Max bars in the window, use esta construção:

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

Quando não quero um método público para iluminar (ao digitar um ponto após o nome do objeto, por exemplo), eu faço deste método um operador público. No entanto, nem sempre é possível usar uma muleta deste tipo.

 
fxsaber:

Quando não quero um método público para iluminar (ao digitar um ponto após o nome do objeto, por exemplo), eu faço deste método um operador público. No entanto, nem sempre é possível usar uma muleta destas.

Há um exemplo no código? Por favor, por favor.

 
Artyom Trishkin:

Há um exemplo no código? Por favor, 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()
}
 

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação

Peculiaridades da linguagem mql5, sutilezas e truques

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()
}

Isto não é...

class A
{
 private:
 void AddCalculate(void) const
  {
   Print(__FUNCSIG__);
  }
 public:
 int GetValue(void) const
  {
   this.AddCalculate();
   return(0);
  }
 
};
Isto não é a mesma coisa?


 
Alexey Viktorov:

E isto.

Não é a mesma coisa?

Não, claro que não. Campos Valor1, Valor2, ... são muitos; GetValue1() e GetValue2() são o mesmo. Não é racional fazer cálculos adicionais a cada GetValue. Não faz sentido fazer cálculos mesmo em um GetValue chamado mais de uma vez.

 

Não consegui descobrir como definir o tamanho de um campo de matriz de uma estrutura simples. Por isso, fiz 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());
}


Eu usei macros, para encurtar. Na MQL5 provavelmente não há outra maneira. Esta é uma solução normal em C++? Como o modelo <tipo S>.

 

Fórum sobre negociação, sistemas de negociação automatizados e testes estratégicos

Bibliotecas: MT4Orders

fxsaber, 2017.09.14 08:52

O gatilho SL/TP foi postado no fórum mesmo antes das bandeiras MQL5 Reason flags. Sua lógica mostrou claramente que quando os níveis SL/TP/SO de uma posição aberta são aceitos pelo servidor de negociação, uma ordem de mercado correspondente é gerada, que está na tabela MT5 de ordens abertas até que ela seja executada.


Portanto, na MT5 mesmo na MQL5 pura, a modificação/eliminação de tais ordens não é possível, e a lógica de negociação na MT5 requer verificar se uma ordem aberta está realmente congelada ou não.


// Триггер 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.");    
  }
}


...Você pode ver que por mais de um quarto de segundo a ordem TP estava pendurada entre as abertas. Qualquer tentativa de modificar/apagar teria causado erros.

Esteja atento a esta característica do MT5.

 
fxsaber:

Quando não quero um método público para acender (ao digitar um ponto após o nome do objeto, por exemplo), eu faço deste método um operador público. No entanto, nem sempre é possível usar uma muleta destas.

Na verdade, é uma espécie de mega muleta. Como você vai analisar seu código mais tarde contendo operadores tão pouco informativos que você não consegue entender o que eles estão fazendo?

Deve ser um erro de desenho. Se uma classe não se destina inicialmente a ser mudada do exterior, mas contém apenas métodos Get-methods, ela deve ser a mesma. Todas as modificações são realizadas através das classes herdadas da mesma.

Outra variante conveniente seria a herança protegida, quando a classe base contém todos os métodos e a classe herdada exibe apenas os métodos Get. E quando for necessário, pode lançá-lo para a classe base. Mas o Metaeditor ainda não corrigiu o bug, todos estes métodos serão despejados na lista, mesmo que não estejam disponíveis.

Não é racional fazer cálculos adicionais sobre cada GetValue. Mesmo um GetValue chamado mais de uma vez não precisa fazer cálculos.

Então o que o impede de usar o método Recalculate()? Se é isso que faz a classe funcionar logicamente, porque a própria classe não pode definir quando é necessário recalcular, isso significa que a classe é controlada por um usuário.