Features of the mql5 language, subtleties and tricks - page 54

 

Features of inherited structures

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

If you want to know if the "Unlimited" flag is enabled in Settings --> Charts --> Max Bars in the window, I use this construction:

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

When I don't want any public method to light up (when typing a dot after the object name, for example), I make this method a public operator. However, it is not always possible to use such a crutch.

 
fxsaber:

When I don't want any public method to light up (when typing a dot after the object name, for example), I make this method a public operator. But it's not always possible to use such a crutch.

Is there an example in the code? Please.

 
Artyom Trishkin:

Is there an example in the code? Please.

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

Forum on trading, automated trading systems and trading strategies testing

Peculiarities of mql5 language, tips and tricks

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

Isn't this

class A
{
 private:
 void AddCalculate(void) const
  {
   Print(__FUNCSIG__);
  }
 public:
 int GetValue(void) const
  {
   this.AddCalculate();
   return(0);
  }
 
};
Isn't this the same thing?


 
Alexey Viktorov:

And this.

is it not the same?

No, of course. The fields Value1, Value2, ... are a lot, GetValue1() and GetValue2() are the same. It is not rational to do additional calculations at every GetValue. Even one GetValue called more than once does not need calculations.

 

I couldn't figure out how to be able to set the size of an array field of a simple structure. That's why I made this crutch.

// Простая структура - не имеет сложных объектов
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());
}


Well, it's done via macros. In MQL5 there is probably no other way. Is this a normal solution in C++? Like template <typesize S>.

 

Forum on trading, automated trading systems and testing trading strategies

Libraries: MT4Orders

fxsaber, 2017.09.14 08:52

The SL/TP trigger was posted on the forum even before Reason flags appeared in MQL5. Its logic clearly showed that when SL/TP/SO levels of an open position are accepted by the trading server, the corresponding market order is generated, which is in the MT5 table of open orders until it is executed.


Therefore, in MT5, even in pure MQL5, modifying/deleting such orders is not possible, and the trading logic in MT5 requires checking whether an open order is actually frozen or not.


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


...You can see that the TP order was hanging among the open ones for more than a quarter of a second. Any attempt to modify/delete it would cause errors.

Keep this feature of MT5 in mind.

 
fxsaber:

When I don't want any public method to light up (when typing a dot after the object name, for example), I make this method a public operator. But it's not always possible to use such a crutch.

This is a kind of mega crutch. How will you ever be able to parse your code that has so many uninformative operators that you cannot understand what they are doing?

This must be a design mistake. If the class is not initially intended to be changed from the outside and contains only Get-methods, it must be like that. And all modifications are carried out through the classes inherited from it.

Another convenient variant would be protected inheritance, when the base class contains all methods and in an inherited class you only expose the Get methods. And when needed, you can inherit them back to the base class. But Metaeditor still has not fixed the bug, all these methods will be dumped to the list even if they are not available.

It is not rational to make additional calculations on each GetValue. Even on one GetValue called more than once, the calculations are useless.

So, what prevents you from using the Recalculate() method? If that's what makes the class work logically, because the class itself can't define when it's necessary to recalculate, it means that the class is controlled by a user.

Reason: