Mql5 dilinin özellikleri, incelikleri ve çalışma yöntemleri - sayfa 222

 
Maxim Kuznetsov # :

Bu haber değil, doğuştan hep böyle çalışıyorlar.

yalnızca veriler __atomic__'den büyükse, kritik bölümlerle (veya std::thread terminalindeki muteks) ona erişmek/korumak gerekir

Eh, böyle bir davranışı bilmiyordum ve içe aktarırken ayrı bir işlem bekliyordum.
Yüklenen her MT5 programında global DLL işaretçilerinin yeni olacağını düşündüğümden.
Mantığı anlamak için terlemem gerekti, hatanın neden bellekten uçup gittiğini merak ettim.
Ama nedenini yazarak (yazdırarak) anladığımda, DLL ile çalışmak için tüm mimari plan farklı şekilde inşa edildi.
Kahretsin, muteksler konusunda haklısın, bunu düşünmedin. Bahşiş için teşekkürler.

 
fxsaber # : ZY Yazık, bir alt alanda veya bir yöntemde imkansız.

Evet. Yöntemin parametresi olmasa da, bunu yapabilirsiniz:

 // Сортировка массива структур и указателей на объекты по методу.
#define ArraySortStruct_DefineMethod(METHOD)                                     \
namespace SortOnMethod_ ##METHOD                                                   \
{                                                                                \
   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]. ##METHOD() <= Array[End]. ##METHOD())                         \
        {                                                                        \
          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 ArraySortStructMet(ARRAY, METHOD) SortOnMethod_ ##METHOD::SORT::Sort(ARRAY)

Başvuru:

 #include <fxsaber\TypeToBytes.mqh>

struct MqlRates2: public MqlRates
  {
   double             Open() { return open;}
  };

ArraySortStruct_DefineMethod(Open)

void OnStart ()
  {
   MqlRates Rates[];

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

   MqlRates2 Rates2[];
   _ArrayCopy(Rates2, Rates);


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

  }
 

Gecikmelerin kısmi yürütülmesi ile ORDER_TIME_SETUP_MSC alanı değişir.

Sonuç olarak, DEAL_TIME_MSC , sırasının ORDER_TIME_SETUP_MSC'sinden daha az olabilir.

 

Özel bir karşılaştırma işlevi kullanmaya ne dersiniz:

 //+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
typedef double (*TComparer)( MqlRates &a, MqlRates &b);

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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, TComparer Compare)
     {
       int Marker = Start;

       for ( int i = Start; i <= End; i++)
         if (Compare(Array[i], Array[End]) <= 0 )
           {
            SORT::Swap(Array, i, Marker);

            Marker++;
           }

       return (Marker - 1 );
     }

   template < typename T>
   static void        QuickSort(T &Array[], const int Start, const int End, TComparer Compare)
     {
       if (Start < End)
        {
         const int Pivot = Partition(Array, Start, End, Compare);

         SORT::QuickSort(Array, Start, Pivot - 1 , Compare);
         SORT::QuickSort(Array, Pivot + 1 , End, Compare);
        }

       return ;
     }

public :
   template < typename T>
   static void        Sort(T &Array[], TComparer Compare, int Count = WHOLE_ARRAY , const int Start = 0 )
     {
       if (Count == WHOLE_ARRAY )
         Count = :: ArraySize (Array);

      SORT::QuickSort(Array, Start, Start + Count - 1 , Compare);

       return ;
     }
  };

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double compare_open( MqlRates &a, MqlRates &b)          { return a.open - b.open;     }
double compare_high( MqlRates &a, MqlRates &b)          { return a.high - b.high;     }
double compare_low( MqlRates &a, MqlRates &b)           { return a.low  - b.low;      }
double compare_close( MqlRates &a, MqlRates &b)         { return a.close - b.close;   }
double compare_time( MqlRates &a, MqlRates &b)          { return ( double )(a.time - b.time); }
double compare_tick_volume( MqlRates &a, MqlRates &b)   { return ( double )(a.tick_volume - b.tick_volume); }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart ()
  {
   MqlRates Rates[];

   CopyRates ( _Symbol , PERIOD_CURRENT , 0 , 5 , Rates);
   ArrayPrint (Rates);

   SORT::Sort(Rates, compare_open);
   ArrayPrint (Rates);
  }
 
fxsaber # :

Haklısın, teşekkürler! Düz bir yerde abarttım. Varyantınızı sıralama için bırakacağım.


Başvuru.


ZZY Yazık, alt alan veya yöntemle çalışmıyor.

İşte kitaplığımdan optimize edilmiş QuickSort, gereksinimlerinize biraz uyarlanmış.

Büyük dizileri yığın taşması olmadan sıralayabilir (kontrolsüz özyineleme nedeniyle).

 //+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
typedef double (*TComparer)( MqlRates &a, MqlRates &b);

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class SORT
  {
private :
   //+------------------------------------------------------------------+
   //| Swaps two variables or two array elements.                       |
   //+------------------------------------------------------------------+
   template < typename T>
   static void        Swap(T &var1, T &var2)
     {
      T temp = var1;
      var1 = var2;
      var2 = temp;
     }
   //+------------------------------------------------------------------+
   //| Insertion Sort                                                   |
   //+------------------------------------------------------------------+
   /**
    * Sort the input array in-place in ascending order.
    * Insertion sort is the fastest sort algorithm for very small
    * arrays (<10-20 elements), or when the input is almost sorted.
    */
   template < typename T>
   static void        InsertionSort(T &arr[], int lo, int hi, TComparer Compare)
     {
       for ( int i = lo + 1 ; i <= hi; i++)
        {
         if (Compare(arr[i], arr[i - 1 ]) < 0 )
           {
            T key = arr[i];
             int j = i - 1 ;
             while (j >= lo && Compare(arr[j], key) > 0 )
              {
               arr[j + 1 ] = arr[j];
               j--;
              }
            arr[j + 1 ] = key;
           }
        }
     }
   //+------------------------------------------------------------------+
   //| Quick Sort (Optimized)                                           |
   //+------------------------------------------------------------------+
   /**
    * Sort the input array in-place in ascending order.
    * Generally, the fastest comparison-based sort algorithm for arrays.
    * (esp. if large size).
    * Average time complexity: O(n log n)
    * Worst-case time complexity: O(n log n)
    * Stable    : no
    *
    * Improvements:
    *
    * 1. Use insertion sort for small partitions, takes linear time O(n + I) with nearly sorted data.
    * 2. Choose pivot as the middle element, to avoid the worst case O(n^2) on already-sorted data.
    * 3. Hoare's parition scheme, which is more efficient than Lomuto's partition scheme
    *    because it does three times fewer swaps on average, and it creates efficient
    *    partitions even when all values are equal (duplicate sort keys).
    * 4. Sort small partitions using recursion and do tail recursion elimination for large partitions.
    *    This guarantees O(logn) space complexity and avoids stack overflow with huge arrays.
    */
   template < typename T>
   static void        QuickSort(T &arr[], int lo, int hi, TComparer Compare)
     {
       // Use a while loop for tail recursion elimination.
       while (lo < hi)
        {
         // Insertion sort is faster for small partitions.
         if (hi - lo < 16 )
           {
            InsertionSort(arr, lo, hi, Compare);
             return ;
           }

         // Pick pivot as the middle element.
         int mid = lo + (hi - lo) / 2 ;
         T pivot = arr[mid];

         // Hoare’s partition scheme.
         int i = lo;
         int j = hi;
         while (i <= j)
           {
             while (Compare(arr[i], pivot) < 0 )
               i++;
             while (Compare(arr[j], pivot) > 0 )
               j--;
             if (i <= j)
              {
               Swap(arr[i], arr[j]);
               i++;
               j--;
              }
           }
         // now, a[lo..j] <= a[i..hi]

         // Sort the small partition first using recursion and do tail recursion elimination for
         // the large partition.
         int l_size = j - lo;
         int r_size = hi - i;
         if (l_size < r_size)
           {
             if (l_size > 0 )
              {
               QuickSort(arr, lo, j, Compare);
              }
            lo = i;
           }
         else
           {
             if (r_size > 0 )
              {
               QuickSort(arr, i, hi, Compare);
              }
            hi = j;
           }
        }
     }

public :
   template < typename T>
   static void        Sort(T &Array[], TComparer Compare, int Count = WHOLE_ARRAY , const int Start = 0 )
     {
       if (Count == WHOLE_ARRAY )
         Count = :: ArraySize (Array);

      SORT::QuickSort(Array, Start, Start + Count - 1 , Compare);
     }
  };

//+------------------------------------------------------------------+
//| Compares two fields and returns a value indicating whether one   |
//| is equal to, less than, or greater than the other.               |
//+------------------------------------------------------------------+
double compare_open( MqlRates &a, MqlRates &b)          { return a.open - b.open;     }
double compare_high( MqlRates &a, MqlRates &b)          { return a.high - b.high;     }
double compare_low( MqlRates &a, MqlRates &b)           { return a.low  - b.low;      }
double compare_close( MqlRates &a, MqlRates &b)         { return a.close - b.close;   }
double compare_time( MqlRates &a, MqlRates &b)          { return ( double )(a.time - b.time); }
double compare_tick_volume( MqlRates &a, MqlRates &b)   { return ( double )(a.tick_volume - b.tick_volume); }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart ()
  {
   MqlRates Rates[];

   CopyRates ( _Symbol , PERIOD_CURRENT , 0 , 5 , Rates);
   ArrayPrint (Rates);

   SORT::Sort(Rates, compare_open);
   ArrayPrint (Rates);

   SORT::Sort(Rates, compare_tick_volume);
   ArrayPrint (Rates);
  }
 
Bodolino # :

Merhaba ve paylaşım için teşekkürler!

Bu işe yararsa mükemmel olurdu. Ancak, bir .mq5 komut dosyasına yapıştırıldığında ve ne yazık ki yürütüldüğünde kodunuz aşağıdaki hataları veriyor:

  • yerel sınıflarda şablon bildirimlerine izin verilmez ArraySortStruct.mq5 87 4
  • (kodunuzu biraz değiştirdikten sonra): şablon bildirimlerine yalnızca global, ad alanı veya sınıf kapsamında izin verilir ArraySortStruct.mq5 90 4 )

Lütfen bunu düzeltir misiniz? Senin için muhtemelen kolay, oysa ben nereden başlayacağımı bilmiyorum :-)

 
 

ArrayInsert kullanırken, Array_Destination[] öğelerinin eklendiği Array_Source[] öğelerinden daha küçük olduğunda bellekten tasarruf edebilirsiniz.

Bunu yapmak için, ArraySwap'i iki kez uygulamalısınız: ArrayInsert'ten önce ve sonra.


Örneğin, büyük MqlTick arşivleri vb. ile çalışırken bu önemlidir.

 

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi üzerine forum

mql5 dilinin özellikleri, incelikleri ve çalışma teknikleri

fxsaber, 2022.02.20 15:00

Haklısınız, teşekkür ederim! Ben düz bir yerde overmudryl. Sıralama için varyantınızı bırakacağım.

Uygulama.

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

Bölümleme yönteminde bir hata vardı. Düzeltilmiş versiyon.

// Сортировка массива структур и указателей на объекты по полю.
#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 Partition2 ( T &Array[], const int Start, const int End )         \
    {                                                                            \
      const T Pivot = Array[End];                                                \
      int i = (Start - 1);                                                       \
                                                                                 \
      for (int j = Start; j < End; j++)                                          \
        if (Array[j].##FIELD < Pivot.##FIELD)                                    \
          SORT::Swap(Array, ++i, j);                                             \
                                                                                 \
      SORT::Swap(Array, i + 1, End);                                             \
                                                                                 \
      return(i + 1);                                                             \
    }                                                                            \
                                                                                 \
    template <typename T>                                                        \
    static void QuickSort( T &Array[], const int Start, const int End )          \
    {                                                                            \
      if (Start < End)                                                           \
      {                                                                          \
        const int Pivot = SORT::Partition2(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)
 
fxsaber #:

Partition yönteminde bir hata vardı. Düzeltilmiş sürüm.

Sıralama için sayısal bir alanın alındığı özel bir durum için (en yaygın durum), öncekinden birkaç kat daha hızlı olan bir varyant yazdım. Ancak iki kat daha fazla bellek tüketiyor. Büyük diziler için geçerlidir.

// Сортировка массива структур и указателей на объекты по ЧИСЛОВОМУ полю.
#define  ArraySortStruct2_Define(FIELD)                               \
namespace SortOnField_##FIELD                                        \
{                                                                    \
  class SORT2                                                        \
  {                                                                  \
  private:                                                           \
    template <typename T, typename T2>                               \
    static void Sort( T &Array[], const T2& )                        \
    {                                                                \
      T2 SortIndex[][2];                                             \
                                                                     \  
      const int Size = ::ArrayResize(SortIndex, ::ArraySize(Array)); \
                                                                     \
      for (int i = Size - 1; i >= 0; i--)                            \
      {                                                              \
        SortIndex[i][0] = (T2)Array[i].##FIELD;                      \
        SortIndex[i][1] = (T2)i;                                     \
      }                                                              \
                                                                     \
      ::ArraySort(SortIndex);                                        \
                                                                     \
      T Sort_Array[];                                                \
                                                                     \
      for (int i = ::ArrayResize(Sort_Array, Size) - 1; i >= 0; i--) \
        Sort_Array[i] = Array[(int)SortIndex[i][1]];                 \
                                                                     \
      ::ArraySwap(Sort_Array, Array);                                \
                                                                     \
      return;                                                        \
    }                                                                \
                                                                     \
  public:                                                            \
    template <typename T>                                            \
    static void Sort( T &Array[] )                                   \
    {                                                                \
      if (::ArraySize(Array))                                        \
        SORT2::Sort(Array, Array[0].##FIELD);                        \
                                                                     \
      return;                                                        \
    }                                                                \
  };                                                                 \
}

#define  ArraySortStruct2(ARRAY, FIELD) SortOnField_##FIELD::SORT2::Sort(ARRAY)


Uygulama (yürütme süresinin ölçülmesi ile).

#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279
#define _BV2(A) _BV(A, 100) // Алертим все, что исполняется дольше 100 микросекунд.

struct STRUCT : public MqlTick
{
  double Num;
};

ArraySortStruct_Define(Num)
ArraySortStruct2_Define(Num)

void OnStart()
{
  STRUCT Array[];
  
  const int Size = ArrayResize(Array, 1 e5);
  
  for (int i = Size - 1; i >= 0; i--)
    Array[i].Num = Size - i;
    
//  _BV2(ArraySortStruct(Array, Num));
  _BV2(ArraySortStruct2(Array, Num));
}


Sonuç.

Alert: Bench_Stack = 0, 100 <= Time[Test9.mq5 129 in OnStart: SortOnField_Num::SORT::Sort(Array)] = 34574468 mcs.

Alert: Bench_Stack = 0, 100 <= Time[Test9.mq5 130 in OnStart: SortOnField_Num::SORT2::Sort(Array)] = 10586 mcs.