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

 
Tri facile d'un ensemble de structures
#property strict

// Сортировка массива структур и указателей на объекты по (под-) полю/методу.
#define  ArraySortStruct(ARRAY, 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;                                                                    \
    }                                                                            \
  };                                                                             \
                                                                                 \
  SORT::Sort(ARRAY);                                                             \
}


Application

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


Résultat

Бары без сортировки - как получили.
                 [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
[0] 2019.05.01 14:00:00 0.94437 0.94496 0.94420 0.94494           985       12             0
[1] 2019.05.01 15:00:00 0.94494 0.94512 0.94313 0.94322          2593       13             0
[2] 2019.05.01 16:00:00 0.94322 0.94350 0.94272 0.94272          2020       12             0
[3] 2019.05.01 17:00:00 0.94272 0.94439 0.94267 0.94433          3922       11             0
[4] 2019.05.01 18:00:00 0.94434 0.94474 0.94423 0.94437          1004       13             0

Сортируем по open-цене.
                 [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
[0] 2019.05.01 17:00:00 0.94272 0.94439 0.94267 0.94433          3922       11             0
[1] 2019.05.01 16:00:00 0.94322 0.94350 0.94272 0.94272          2020       12             0
[2] 2019.05.01 18:00:00 0.94434 0.94474 0.94423 0.94437          1004       13             0
[3] 2019.05.01 14:00:00 0.94437 0.94496 0.94420 0.94494           985       12             0
[4] 2019.05.01 15:00:00 0.94494 0.94512 0.94313 0.94322          2593       13             0

Сортируем по high-цене.
                 [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
[0] 2019.05.01 16:00:00 0.94322 0.94350 0.94272 0.94272          2020       12             0
[1] 2019.05.01 17:00:00 0.94272 0.94439 0.94267 0.94433          3922       11             0
[2] 2019.05.01 18:00:00 0.94434 0.94474 0.94423 0.94437          1004       13             0
[3] 2019.05.01 14:00:00 0.94437 0.94496 0.94420 0.94494           985       12             0
[4] 2019.05.01 15:00:00 0.94494 0.94512 0.94313 0.94322          2593       13             0

Сортируем по времени.
                 [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
[0] 2019.05.01 14:00:00 0.94437 0.94496 0.94420 0.94494           985       12             0
[1] 2019.05.01 15:00:00 0.94494 0.94512 0.94313 0.94322          2593       13             0
[2] 2019.05.01 16:00:00 0.94322 0.94350 0.94272 0.94272          2020       12             0
[3] 2019.05.01 17:00:00 0.94272 0.94439 0.94267 0.94433          3922       11             0
[4] 2019.05.01 18:00:00 0.94434 0.94474 0.94423 0.94437          1004       13             0
 
fxsaber:
Pratique pour trier un tableau de structures


      if (Count == WHOLE_ARRAY)                                                  \
        Count = ::ArraySize(Array) - Start; 

Le jaune a souligné les choses manquantes, et il me semble que c'est mieux dans l'ordre des arguments, d'abord Start, et ensuite Count.

À propos, il est probablement plus rationnel de trier les tableaux de structures par index (je veux dire réarranger les index, pas les structures elles-mêmes), mais cela dépend de la taille de la structure, bien sûr.

 
Alexey Navoykov:

J'ai souligné en jaune ce qui manquait.

Merci, ça m'a manqué.

Je pense qu'il est préférable de commencer par Start et ensuite Count dans l'ordre des arguments.

Le signal est emprunté à MT4-ArraySort.

D'ailleurs, il serait probablement plus raisonnable de trier les tableaux de structures par index (je veux dire réarranger les index, pas les structures elles-mêmes).

C'est la première chose qui m'est venue à l'esprit, mais j'y ai renoncé. Parce qu'il faut utiliser ArrayCopy du tableau initial et du tableau d'index. Et ceci est une mémoire supplémentaire. Et la machine ne peut pas se permettre un tel tri d'un tableau, par exemple, de millions d'éléments MqlTick.

Nous aurions pu inclure deux variantes de tri, mais je ne l'ai pas fait dans le code source. Dans la démonstration, le plus précieux est peut-être la facilité d'utilisation et la méthode de mise en œuvre. Après l'avoir étudié, il est déjà clair comment ajouter à vos besoins et faire un analogue pour d'autres fonctions de tableaux avec des structures (ArrayMaximum, etc.).

ArraySort - Операции с массивами - Справочник MQL4
ArraySort - Операции с массивами - Справочник MQL4
  • docs.mql4.com
//| Script program start function                                    |
 
fxsaber:
Pratique pour trier un tableau de structures


Application


Résultat

Comment convertir ce code en une simple classe sans utiliser #define ?

 
Vladimir Pastushak:

Comment convertir ce code en une simple classe sans utiliser #define ?

Tu ne peux pas. ArraySortStruct est censé être utilisé comme une fonction sans entrer dans la façon dont il est organisé.

Il suffit de jeter un peu d'enludnik dans son code source et de l'oublier. Ensuite, une "fonction" très pratique pour tout débutant (et pas seulement) est toujours à portée de main.

 
Folks, jeter dans une référence si elle est telle, besoin du drapeau de l'heure d'ouverture de la soirée (supplémentaire) de la session de négociation sur FORTS MEX, et comme tous les regardé à travers mais n'a pas trouvé, ne veulent pas écrire une béquille définition à 19:00 ou 19:05 ouvrira la session de négociation
 

Un nombre aléatoire de 0 à max avec une probabilité égale :

uint get_rand(uint max)
{
   static bool f = false;
   if ( ! f ) {
      f = true;
      srand(GetTickCount());
   }  
   uint limit = (max+1) * ((32767+1) / (max+1));
   uint val;
   while ((val = rand()) >= limit);
   return val % (max+1);
}
 
Renat Fatkhullin:

Le multi-buffer permet d'accélérer l'éditeur et est sûr.

Il n'écrit rien sur le disque et ne conserve que les données en mémoire.

à quelle cote pourrai-je insérer une image sur le site web ?
 
Vict:

Un nombre aléatoire de 0 à max avec une probabilité égale :

Votre fonction est 100% équivalente :

uint get_rand(uint max)
  {
   static bool f = true;
   if (f) {f = ~f; srand(GetTickCount());} 
   return rand() % (max+1);
  }

parce que, premièrement.

uint limit = (max+1) * (32767+1 / (max+1));

se simplifie en

uint limit = (max+1) * 32767+1; // т.е. при даже max=0 limit =32768

donc, deuxièmement

while ((val = rand()) >= limit);

est toujours exécuté une fois.

La complexité est une déclaration détaillée de la simplicité. ))

 
Nikolai Semko:

Votre fonction est 100% équivalente :

parce que, premièrement.

se simplifie en

donc, deuxièmement

est toujours exécuté une fois.

La complexité est une déclaration détaillée de la simplicité. ))

Vous êtes très prévenant, merci. J'ai fait une erreur, je n'ai pas mis de parenthèses, j'utiliserais donc la fonction "injuste".

SZZ : corrections apportées au message original.