Características da linguagem mql5, subtilezas e técnicas - página 134

 
Classificação fácil de um conjunto de estruturas
#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);                                                             \
}


Aplicação

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


Resultado

Бары без сортировки - как получили.
                 [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:
Classificar manualmente um conjunto de estruturas


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

O amarelo realçou as coisas em falta, e parece-me que é melhor por ordem de argumentos, primeiro Começar, e depois Contar.

A propósito, é provavelmente mais racional ordenar os conjuntos de estruturas por índices (reajustar índices, não as estruturas em si), mas depende do tamanho da estrutura, é claro.

 
Alexey Navoykov:

Destaquei em amarelo o que faltava.

Obrigado, perdi-o.

Penso que é melhor começar por Start e depois contar por ordem de argumentos.

O sinal é emprestado do MT4-ArraySort.

A propósito, seria provavelmente mais razoável ordenar os conjuntos de estruturas por índices (reordenar índices, não as estruturas em si).

Esta foi a primeira coisa que me veio à cabeça, mas desisti dela. Porque requer a utilização do ArrayCopy da matriz inicial e da matriz de índices. E isto é memória adicional. E a máquina não se pode dar ao luxo de uma tal ordenação, por exemplo, de milhões de MqlTick-elements.

Poderíamos ter incluído duas variantes de ordenação, mas não o fiz no código fonte. Na demonstração, talvez, o mais valioso seja a usabilidade e o método de implementação. Depois de o estudar, já está claro como adicionar às suas necessidades e fazer um análogo para outras funções de matrizes com estruturas (ArrayMaximum, etc.).

ArraySort - Операции с массивами - Справочник MQL4
ArraySort - Операции с массивами - Справочник MQL4
  • docs.mql4.com
//| Script program start function                                    |
 
fxsaber:
Classificar manualmente um conjunto de estruturas


Aplicação


Resultado

Como converter este código para uma classe simples sem usar #define ?

 
Vladimir Pastushak:

Como converter este código para uma classe simples sem usar #define ?

Não pode. ArraySortStruct é suposto ser usado como função sem entrar na forma como está organizado.

Basta atirar um pouco de enludnik o seu código fonte e esquecê-lo. Depois disso, uma "função" realmente útil para qualquer principiante (e não só) está sempre à mão.

 
As pessoas, se houver uma referência, precisam da bandeira da hora de abertura da sessão de negociação da noite (adicional) no FORTS MOEX, e como todos procuraram mas não encontraram, não querem escrever uma definição de muleta às 19:00 ou 19:05 abrirá a sessão de negociação
 

Um número aleatório de 0 a máximo com igual probabilidade:

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:

O multibuffer é óptimo para acelerar o editor e é seguro.

Não grava nada no disco e apenas guarda dados na memória.

com que classificação poderei inserir uma fotografia no sítio web?
 
Vict:

Um número aleatório de 0 a máximo com igual probabilidade:

A sua função é 100% equivalente:

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

porque, em primeiro lugar.

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

simplifica para

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

portanto, em segundo lugar

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

é sempre realizado uma vez.

A complexidade é uma declaração detalhada de simplicidade. ))

 
Nikolai Semko:

A sua função é 100% equivalente:

porque, em primeiro lugar.

simplifica para

portanto, em segundo lugar

é sempre realizado uma vez.

A complexidade é uma declaração detalhada de simplicidade. ))

É muito atencioso, obrigado. Cometi um erro, não coloquei parênteses, por isso usaria a função "injusta".

SZZ: fez correcções ao posto original.