Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 54

 

Caratteristiche delle strutture ereditate

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 vuoi sapere se il flag "Unlimited" è abilitato in Settings --> Charts --> Max bars nella finestra, usa questa costruzione:

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

Quando non voglio che un metodo pubblico si illumini (quando si digita un punto dopo il nome dell'oggetto, per esempio), rendo questo metodo un operatore pubblico. Tuttavia, non è sempre possibile utilizzare tale stampella.

 
fxsaber:

Quando non voglio che un metodo pubblico si illumini (quando si digita un punto dopo il nome dell'oggetto, per esempio), rendo questo metodo un operatore pubblico. Tuttavia, non è sempre possibile utilizzare una tale stampella.

C'è un esempio nel codice? Per favore.

 
Artyom Trishkin:

C'è un esempio nel codice? Per favore.

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 sul trading, sistemi di trading automatico e test di strategie di trading

Peculiarità del linguaggio mql5, sottigliezze e trucchi

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

Non è questo

class A
{
 private:
 void AddCalculate(void) const
  {
   Print(__FUNCSIG__);
  }
 public:
 int GetValue(void) const
  {
   this.AddCalculate();
   return(0);
  }
 
};
Non è la stessa cosa?


 
Alexey Viktorov:

E questo.

Non è la stessa cosa?

No, certo che no. Campi Valore1, Valore2, ... sono molti; GetValue1() e GetValue2() sono uguali. Non è razionale eseguire ulteriori calcoli ad ogni GetValue. Non ha senso eseguire calcoli anche in un GetValue chiamato più di una volta.

 

Non riuscivo a capire come poter impostare la dimensione di un campo array di una struttura semplice. Così ho fatto questa stampella.

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


Ho usato le macro, per farla breve. In MQL5 probabilmente non c'è altro modo. È una soluzione normale in C++? Come template <typesize S>.

 

Forum sul trading, sistemi di trading automatico e test di strategia

Biblioteche: MT4Orders

fxsaber, 2017.09.14 08:52

Il trigger SL/TP è stato postato sul forum anche prima delle bandiere di MQL5 Reason. La sua logica mostrava chiaramente che quando i livelli SL/TP/SO di una posizione aperta vengono accettati dal server di trading, l'ordine di mercato corrispondente viene generato e rimane nella tabella MT5 degli ordini aperti fino a quando non viene eseguito.


Quindi in MT5 anche su MQL5 puro la modifica/cancellazione di tali ordini non è possibile, e la logica di trading in MT5 richiede di controllare se un ordine aperto è effettivamente congelato o meno.


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


...Potete vedere che per più di un quarto di secondo l'ordine TP è rimasto sospeso tra quelli aperti. Qualsiasi tentativo di modificarlo/cancellarlo avrebbe causato degli errori.

Siate consapevoli di questa caratteristica di MT5.

 
fxsaber:

Quando non voglio che un metodo pubblico si illumini (quando si digita un punto dopo il nome dell'oggetto, per esempio), rendo questo metodo un operatore pubblico. Tuttavia, non è sempre possibile utilizzare una tale stampella.

In realtà è una specie di mega stampella. Come analizzerete in seguito il vostro codice contenente operatori così poco informativi che non sanno cosa stanno facendo?

Deve essere un errore di progettazione. Se una classe non è inizialmente destinata ad essere modificata dall'esterno, ma contiene solo metodi Get, dovrebbe essere la stessa. Tutte le modifiche vengono effettuate attraverso le classi ereditate da esso.

Un'altra variante conveniente sarebbe l'ereditarietà protetta, quando la classe base contiene tutti i metodi e la classe ereditata mostra solo i metodi Get. E quando è necessario, si può fare il cast alla classe base. Ma Metaeditor non ha ancora risolto il bug, tutti questi metodi saranno scaricati nella lista anche se non sono disponibili.

Non è razionale fare calcoli aggiuntivi su ogni GetValue. Anche un GetValue chiamato più di una volta non ha bisogno di eseguire calcoli.

Quindi cosa vi impedisce di usare il metodo Recalculate()? Se è questo che fa funzionare logicamente la classe, perché la classe stessa non può definire quando è necessario ricalcolare, significa che la classe è controllata da un utente.