Особенности языка mql5, тонкости и приёмы работы - страница 134

 
Удобная сортировка массива структур
#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);                                                             \
}


Применение

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


Результат

Бары без сортировки - как получили.
                 [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:
Удобная сортировка массива структур


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

Жёлтым выделил недостающее.  Да и лучше по порядку аргументов сначала Start, а потом Count, как мне кажется.

Кстати массивы структур наверно рациональней сортировать по индексам (в смысле индексы переставлять, а не сами структуры),  но это зависит от размера структуры конечно.

 
Alexey Navoykov:

Жёлтым выделил недостающее.

Спасибо, пропустил.

Да и лучше по порядку аргументов сначала Start, а потом Count, как мне кажется.

Сигнатура заимствована из MT4-ArraySort.

Кстати массивы структур наверно рациональней сортировать по индексам (в смысле индексы переставлять, а не сами структуры),  но это зависит от размера структуры конечно.

Это первое, что пришло в голову, но отказался. Т.к. требует использования ArrayCopy исходного массива и массива индексов. А это доп. память. И такую сортировку массива, например, из десятков миллионов MqlTick-элементов машина может не потянуть.

Можно было бы включить два варианта сортировки, но в исходник не стал включать. В демонстрации, наверное, ценное - удобство использование и метод реализации. После изучение становится понятно уже, как дописать под свои нужды и сделать аналог для других функций массивов со структурами (ArrayMaximum и т.д.).

ArraySort - Операции с массивами - Справочник MQL4
ArraySort - Операции с массивами - Справочник MQL4
  • docs.mql4.com
//| Script program start function                                    |
 
fxsaber:
Удобная сортировка массива структур


Применение


Результат

Как этот код преобразовать в простой класс без использования #define ?

 
Vladimir Pastushak:

Как этот код преобразовать в простой класс без использования #define ?

Никак. Предполагается, что используется ArraySortStruct, как функция, без вникания в то, как она устроена.

Просто закинули в какой-нибудь инклудник ее исходник и забыли про него. После чего реально удобная для любого новичка (и не только) "функция" всегда под рукой.

 
народ, киньте в справку ссылку если есть такое, нужен флаг времени открытия вечерней (дополнительной) торговой сессии на FORTS MOEX, а то вроде все просмотрел но не нашел, не хочется писать костыль определения в 19:00 или 19:05 будет открытие торговой сессии
 

Случайное число от 0 до max с равной вероятностью:

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:

Мультибуфер здорово ускоряет работу в редакторе и безопасен.

Он ничего не пишет на диск и держит данные только в памяти.

начиная с какого рейтинга я смогу вставить картинку на сайт?
 
Vict:

Случайное число от 0 до max с равной вероятностью:

Ваша функция на 100% эквивалентна:

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

т.к. во-первых

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

упрощается до

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

стало быть во-вторых

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

всегда выполняется один раз. 

Сложность - подробное изложение простоты. ))

 
Nikolai Semko:

Ваша функция на 100% эквивалентна:

т.к. во-первых

упрощается до

стало быть во-вторых

всегда выполняется один раз. 

Сложность - подробное изложение простоты. ))

Вы очень внимательны, спасибо. Ошибся, не поставил скобки, так и пользовался бы "нечестной" функцией.

ЗЫ: внёс правки в исходное сообщение.

Причина обращения: