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

 
fxsaber #:

Je ne sais pas comment conserver la fonctionnalité (sous-zone et méthode) et la convivialité. Peut-être cette option répondrait-elle à vos besoins.


Application.

C'était si rapide et maintenant ça marche très bien, merci !


To Russia with love❤️ ! ;-)

 
Il fut un temps où il était facile d'écrire une telle macro dans MQL5.
class MqlRatestime
{
public:
  static void f( MqlRates &Value ) { Print(Value.time); }
};

class MqlTicktime
{
public:
  static void f( MqlTick &Value ) { Print(Value.time); }
};

void OnStart()
{  
  MqlRates Rates;
  MqlTick Tick;
  
  MACROS(Rates, time); // MqlRatestime::f(Rates);
  MACROS(Tick, time);  // MqlTicktime::f(Tick);
}


Est-ce possible dans la version actuelle de MQL5 ? Je n'avais pas l'ingéniosité nécessaire pour surmonter cet obstacle :

template declarations are allowed on global, namespace or class scope only
 
fxsaber #:
Il fut un temps où il était facile d'écrire une telle macro dans MQL5.


Est-ce possible dans la version actuelle de MQL5 ? Je n'ai pas eu la débrouillardise nécessaire pour surmonter cet obstacle :

Je ne comprends pas la tâche - avez-vous besoin que la classe MqlRatest (son modèle) soit déclarée dans une macro de substitution ?
 
mktr8591 #:
Je ne comprends pas la tâche - vous avez besoin que la classe MqlRatest (son modèle) soit déclarée dans la macro-substitution ?
Il me semble qu'il est nécessaire d'avoir une substitution de macro différente pour les paramètres de type différent.
Seulement, je ne comprends pas pourquoi cela devrait être fait avec la substitution de macro au lieu de la surcharge de fonction.
 
mktr8591 #:
Je ne comprends pas la tâche - vous avez besoin que la classe MqlRatest (son modèle) soit déclarée dans la macro-substitution ?

Non, les classes sont déjà déclarées. Les commentaires précisent le résultat que vous souhaitez obtenir. L'entrée de la macro est un objet, et la sortie est une classe qui contient le nom du type de cet objet.

 
Sergey Gridnev #:
Il me semble qu'il est nécessaire d'avoir une substitution de macro différente pour les paramètres de différents types.
Seulement, je ne comprends pas pourquoi cela devrait être fait en utilisant la substitution de macro plutôt que la surcharge de fonction.

La tâche est née de celle-ci.

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

Particularités de mql5, trucs et astuces

fxsaber, 2022.02.11 15:44

ArraySortStruct_Define(MqlRates, open)
ArraySortStruct_Define(MqlRates, high)
ArraySortStruct_Define(MqlRates, time)

void OnStart()
{
  MqlRates Rates[];
  
  CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары
  
  Print("\nБары без сортировки - как получили.");
  ArrayPrint(Rates);
  
  Print("\nСортируем по open-цене.");
  ArraySortStruct(MqlRates, Rates, open);
  ArrayPrint(Rates);

  Print("\nСортируем по high-цене.");
  ArraySortStruct(MqlRates, Rates, high);
  ArrayPrint(Rates);

  Print("\nСортируем по времени.");
  ArraySortStruct(MqlRates, Rates, time);
  ArrayPrint(Rates);
}

J'ai coloré le paramètre d'entrée, dans lequel je dois spécifier le type. Dans cette macro, j'obtiens trois paramètres d'entrée. Et j'en voudrais deux - sans type.

 
fxsaber #:

Non, les classes sont déjà déclarées. Les commentaires précisent le résultat que vous souhaitez obtenir. L'entrée de la macro est un objet, et la sortie est une classe qui contient le nom du type de cet objet.

Je ne sais pas comment résoudre ce problème.

Et pour ArraySortStruct avec deux paramètres - voici comment cela fonctionne :

#define  ArraySortStruct(ARRAY, FIELD) SortOnField_##FIELD::SORT::Sort(ARRAY)

 ArraySortStruct_Define(SortOnField_, open)
ArraySortStruct_Define(SortOnField_, high)
ArraySortStruct_Define(SortOnField_, time)


void OnStart()
  {

   MqlRates Rates[];

   CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары

   Print("\nБары без сортировки - как получили.");
   ArrayPrint(Rates);

   Print("\nСортируем по open-цене.");
   ArraySortStruct(Rates, open);
   ArrayPrint(Rates);

   Print("\nСортируем по high-цене.");
   ArraySortStruct(Rates, high);
   ArrayPrint(Rates);

   Print("\nСортируем по времени.");
   ArraySortStruct(Rates, time);
   ArrayPrint(Rates);
  }
 
mktr8591 #:

Et à ArraySortStruct avec deux paramètres - c'est ainsi que cela fonctionne :

Vous avez raison, merci ! J'ai trop forcé sur un endroit plat. Je vais laisser votre variante pour le tri.

// Сортировка массива структур и указателей на объекты по полю.
#define  ArraySortStruct_Define(FIELD)                                            \
namespace SortOnField_##FIELD                                                    \
{                                                                                \
  class SORT                                                                     \
  {                                                                              \
  private:                                                                       \
    template <typename T>                                                        \
    static void Swap( T &Array[], const int i, const int j )                     \
    {                                                                            \
      const T Temp = Array[i];                                                   \
                                                                                 \
      Array[i] = Array[j];                                                       \
      Array[j] = Temp;                                                           \
                                                                                 \
      return;                                                                    \
    }                                                                            \
                                                                                 \
    template <typename T>                                                        \
    static int Partition( T &Array[], const int Start, const int End )           \
    {                                                                            \
      int Marker = Start;                                                        \
                                                                                 \
      for (int i = Start; i <= End; i++)                                         \
        if (Array[i].##FIELD <= Array[End].##FIELD)                              \
        {                                                                        \
          SORT::Swap(Array, i, Marker);                                          \
                                                                                 \
          Marker++;                                                              \
        }                                                                        \
                                                                                 \
       return(Marker - 1);                                                       \
    }                                                                            \
                                                                                 \
    template <typename T>                                                        \
    static void QuickSort( T &Array[], const int Start, const int End )          \
    {                                                                            \
      if (Start < End)                                                           \
      {                                                                          \
        const int Pivot = Partition(Array, Start, End);                          \
                                                                                 \
        SORT::QuickSort(Array, Start, Pivot - 1);                                \
        SORT::QuickSort(Array, Pivot + 1, End);                                  \
      }                                                                          \
                                                                                 \
      return;                                                                    \
    }                                                                            \
                                                                                 \
  public:                                                                        \
    template <typename T>                                                        \
    static void Sort( T &Array[], int Count = WHOLE_ARRAY, const int Start = 0 ) \
    {                                                                            \
      if (Count == WHOLE_ARRAY)                                                  \
        Count = ::ArraySize(Array);                                              \
                                                                                 \
      SORT::QuickSort(Array, Start, Start + Count - 1);                          \
                                                                                 \
      return;                                                                    \
    }                                                                            \
  };                                                                             \
}

#define  ArraySortStruct(ARRAY, FIELD) SortOnField_##FIELD::SORT::Sort(ARRAY)


Application.

ArraySortStruct_Define(open)
ArraySortStruct_Define(high)
ArraySortStruct_Define(time)

void OnStart()
{
  MqlRates Rates[];
  
  CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары
  
  Print("\nБары без сортировки - как получили.");
  ArrayPrint(Rates);
  
  Print("\nСортируем по open-цене.");
  ArraySortStruct(Rates, open);
  ArrayPrint(Rates);
  
  Print("\nСортируем по high-цене.");
  ArraySortStruct(Rates, high);
  ArrayPrint(Rates);
  
  Print("\nСортируем по времени.");
  ArraySortStruct(Rates, time);
  ArrayPrint(Rates);
}


ZZY C'est dommage, par sous-domaine ou par méthode, ça ne marche pas.

 
Ce n'est peut-être pas une nouvelle pour tout le monde, mais c'est inattendu pour moi.
Si une DLL est utilisée simultanément dans différents programmes MT5,
gardez à l'esprit qu'elle est chargée une fois par le premier programme en cours d'exécution qui l'utilise.
En d'autres termes, l'environnement DLL se trouve dans un processus commun, quel que soit le nombre de fois où vous l'importez.
Quel est le piège ? Les pointeurs globaux utilisés dans la DLL sont tous dans le même espace de processus partagé.
Et c'est très pratique.
 
Roman #:
Ce n'est peut-être pas une nouvelle pour tout le monde mais c'est inattendu pour moi.
Si la DLL est utilisée simultanément dans différents programmes MT5,
, n'oubliez pas qu'elle est chargée une fois par le premier programme qui l'utilise.
En d'autres termes, l'état de la DLL se trouve dans un processus commun, quel que soit le nombre de fois où vous l'importez.
Quel est le piège ? Les pointeurs globaux utilisés dans la DLL sont tous dans le même espace de processus partagé.
Et c'est très pratique.

Ce n'est pas nouveau, c'est la façon dont cela a toujours fonctionné depuis la naissance.

Ce n'est que si les données sont plus grandes que __atomique__ que l'accès doit être enveloppé/protégé avec des sections critiques (ou mutex vers std::thread terminal).