Caractéristiques du langage mql5, subtilités et techniques - page 54

 

Caractéristiques des structures héritées

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 vous voulez savoir si le drapeau "Illimité" est activé dans Settings --> Charts --> Max bars dans la fenêtre, utilisez cette construction:

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

Quand je ne veux pas qu'une méthode publique s'allume (quand on tape un point après le nom de l'objet, par exemple), je fais de cette méthode un opérateur public. Cependant, il n'est pas toujours possible d'utiliser une telle béquille.

 
fxsaber:

Quand je ne veux pas qu'une méthode publique s'allume (quand on tape un point après le nom de l'objet, par exemple), je fais de cette méthode un opérateur public. Cependant, il n'est pas toujours possible d'utiliser une telle béquille.

Y a-t-il un exemple dans le code ? S'il vous plaît.

 
Artyom Trishkin:

Y a-t-il un exemple dans le code ? S'il vous plaît.

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 sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading

Particularités du langage mql5, subtilités et astuces

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

N'est-ce pas

class A
{
 private:
 void AddCalculate(void) const
  {
   Print(__FUNCSIG__);
  }
 public:
 int GetValue(void) const
  {
   this.AddCalculate();
   return(0);
  }
 
};
Ce n'est pas la même chose ?


 
Alexey Viktorov:

Et ceci.

Ce n'est pas la même chose ?

Non, bien sûr que non. Les champs Valeur1, Valeur2, ... sont nombreux ; GetValue1() et GetValue2() sont les mêmes. Il n'est pas rationnel d'effectuer des calculs supplémentaires à chaque GetValue. Il est inutile d'effectuer des calculs, même dans un GetValue appelé plusieurs fois.

 

Je n'ai pas réussi à trouver comment définir la taille d'un champ de tableau d'une structure simple. Alors j'ai fait cette béquille.

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


J'ai utilisé des macros, pour faire court. Dans MQL5, il n'y a probablement pas d'autre moyen. Est-ce une solution normale en C++ ? Comme le modèle <typesize S>.

 

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégie

Bibliothèques : MT4Orders

fxsaber, 2017.09.14 08:52

Le déclencheur SL/TP a été posté sur le forum avant même les drapeaux de MQL5 Reason. Sa logique montre clairement que lorsque les niveaux SL/TP/SO d'une position ouverte sont acceptés par le serveur de trading, un ordre de marché correspondant est généré, qui se trouve dans le tableau des ordres ouverts du MT5 jusqu'à son exécution.


Par conséquent, dans MT5, même sur un MQL5 pur, la modification/suppression de tels ordres n'est pas possible, et la logique de négociation dans MT5 exige de vérifier si un ordre ouvert est effectivement gelé ou non.


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


...Vous pouvez voir que pendant plus d'un quart de seconde, l'ordre TP était suspendu parmi les ordres ouverts. Toute tentative de le modifier/supprimer aurait provoqué des erreurs.

Soyez conscient de cette fonctionnalité de MT5.

 
fxsaber:

Quand je ne veux pas qu'une méthode publique s'allume (quand on tape un point après le nom de l'objet, par exemple), je fais de cette méthode un opérateur public. Cependant, il n'est pas toujours possible d'utiliser une telle béquille.

En fait, c'est une sorte de méga-béquille. Comment allez-vous analyser plus tard votre code contenant des opérateurs aussi peu informatifs qui ne savent pas ce qu'ils font ?

Ce doit être une erreur de conception. Si une classe n'est pas initialement destinée à être modifiée de l'extérieur mais qu'elle ne contient que des méthodes Get, elle doit être identique. Toutes les modifications sont effectuées à travers les classes qui en ont hérité.

Une autre variante pratique serait l'héritage protégé, lorsque la classe de base contient toutes les méthodes et que la classe héritée n'affiche que les méthodes Get. Et lorsque cela est nécessaire, vous pouvez l'intégrer à la classe de base. Mais Metaeditor n'a toujours pas corrigé le bug, toutes ces méthodes seront mises dans la liste même si elles ne sont pas disponibles.

Il n'est pas rationnel d'effectuer des calculs supplémentaires sur chaque GetValue. Même un GetValue appelé plusieurs fois ne doit pas effectuer de calculs.

Alors qu'est-ce qui vous empêche d'utiliser la méthode Recalculate() ? Si c'est ce qui fait que la classe fonctionne logiquement, parce que la classe elle-même ne peut pas définir quand il est nécessaire de recalculer, cela signifie que la classe est contrôlée par un utilisateur.