mql5语言的特点、微妙之处以及技巧 - 页 222 1...215216217218219220221222223224225226227228229...247 新评论 Roman 2022.02.21 06:50 #2211 Maxim Kuznetsov #:这不是什么新鲜事,从出生开始就是这样的。只有当数据大于__atomic__时,才应该用关键部分来包裹/保护访问(或者用mutex到终端std::线程)。 好吧,我不知道这种行为,还以为导入时有一个单独的过程。 我以为全局DLL指针将是新的,在每一个加载的MT5程序中。,我不得不流汗去理解逻辑,想知道为什么错误会在内存中弹出。 但当我通过 try (print) 方法找出原因时,那么整个与 DLL 合作的架构计划将以不同方式建立。 伙计,你对突变的看法是对的,我没有想到这一点。谢谢你的提示。 mktr8591 2022.02.21 11:49 #2212 fxsaber #: ZZY 很遗憾,你不能按子领域或方法来做。 是的,尽管如果该方法没有参数,你可以这样做。 // Сортировка массива структур и указателей на объекты по методу. #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) 申请。 #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); } fxsaber 2022.04.20 16:20 #2213 随着订单的部分执行,字段ORDER_TIME_SETUP_MSC 发生变化。 因此,DEAL_TIME_MSC 可以小于其订单的ORDER_TIME_SETUP_MSC。 amrali 2022.04.20 23:46 #2214 使用一个自定义的比较函数怎么样。 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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); } amrali 2022.04.21 17:00 #2215 fxsaber #:你是对的,谢谢你!我在一个平坦的地方做得过头了。我会留下你的变体进行分类。应用。ZZY 很遗憾,按子字段或方法,它不起作用。 这里是我的库中优化的QuickSort,根据你的要求稍作调整。 它可以对巨大的数组进行排序而不会出现堆栈溢出(由于不受控制的递归)。 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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); } Aricoco Arinze 2022.04.21 22:14 #2216 Bodolino #:嗨,谢谢你的分享如果能成功的话,这将是完美的。但是,当粘贴到一个.mq5脚本中并执行时,不幸的是,你的代码出现了以下错误。 模板声明在本地类中是不允许的 ArraySortStruct.mq5 87 4 (在稍微 修改了你的代码后): 模板声明只允许在全局、命名空间或类的范围内进行 ArraySortStruct.mq5 90 4 ) 能否请你解决这个问题?对你来说,这可能很容易,而我不知道从哪里开始 :-) Artyom Trishkin 2022.05.16 08:48 #2217 与此主题无关的评论已移至"MQL4 和 MQL5 初学者的任何问题,有关算法和代码的帮助和讨论"。 fxsaber 2022.05.19 16:12 #2218 使用 ArrayInsert 时,如果 Array_Destination[] 小于添加元素的 Array_Source[],则可以节省内存。 为此,应在 ArrayInsert 之前和之后两次应用 ArraySwap。 例如,在处理大型 MqlTick 存档等时就需要使用 ArraySwap。 fxsaber 2022.06.06 17:55 #2219 交易、自动交易系统和交易策略测试论坛 mql5 语言的特殊性、微妙之处和工作技巧 fxsaber, 2022.02.20 15:00 你是对的,谢谢!我在一个直的地方overmudryl。我会留下你的变体进行排序。 应用。 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); } 分区方法中存在错误。更正后的版本。 // Сортировка массива структур и указателей на объекты по полю. #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 2022.06.19 14:17 #2220 fxsaber #: 分区方法中存在错误。已更正版本。 针对数字字段被用于排序的特殊情况(最常见的情况),我编写了一个变体,它比之前的变体快了几个数量级。但它消耗的内存是前者的两倍。它适用于大型数组。 // Сортировка массива структур и указателей на объекты по ЧИСЛОВОМУ полю. #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) 应用(测量执行时间)。 #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)); } 结果 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. 1...215216217218219220221222223224225226227228229...247 新评论 您错过了交易机会: 免费交易应用程序 8,000+信号可供复制 探索金融市场的经济新闻 注册 登录 拉丁字符(不带空格) 密码将被发送至该邮箱 发生错误 使用 Google 登录 您同意网站政策和使用条款 如果您没有帐号,请注册 可以使用cookies登录MQL5.com网站。 请在您的浏览器中启用必要的设置,否则您将无法登录。 忘记您的登录名/密码? 使用 Google 登录
这不是什么新鲜事,从出生开始就是这样的。
只有当数据大于__atomic__时,才应该用关键部分来包裹/保护访问(或者用mutex到终端std::线程)。
好吧,我不知道这种行为,还以为导入时有一个单独的过程。
我以为全局DLL指针将是新的,在每一个加载的MT5程序中。
,我不得不流汗去理解逻辑,想知道为什么错误会在内存中弹出。
但当我通过 try (print) 方法找出原因时,那么整个与 DLL 合作的架构计划将以不同方式建立。
伙计,你对突变的看法是对的,我没有想到这一点。谢谢你的提示。
是的,尽管如果该方法没有参数,你可以这样做。
申请。
随着订单的部分执行,字段ORDER_TIME_SETUP_MSC 发生变化。
因此,DEAL_TIME_MSC 可以小于其订单的ORDER_TIME_SETUP_MSC。
使用一个自定义的比较函数怎么样。
你是对的,谢谢你!我在一个平坦的地方做得过头了。我会留下你的变体进行分类。
应用。
ZZY 很遗憾,按子字段或方法,它不起作用。
这里是我的库中优化的QuickSort,根据你的要求稍作调整。
它可以对巨大的数组进行排序而不会出现堆栈溢出(由于不受控制的递归)。
嗨,谢谢你的分享
如果能成功的话,这将是完美的。但是,当粘贴到一个.mq5脚本中并执行时,不幸的是,你的代码出现了以下错误。
能否请你解决这个问题?对你来说,这可能很容易,而我不知道从哪里开始 :-)
使用 ArrayInsert 时,如果 Array_Destination[] 小于添加元素的 Array_Source[],则可以节省内存。
为此,应在 ArrayInsert 之前和之后两次应用 ArraySwap。
例如,在处理大型 MqlTick 存档等时就需要使用 ArraySwap。
交易、自动交易系统和交易策略测试论坛
mql5 语言的特殊性、微妙之处和工作技巧
fxsaber, 2022.02.20 15:00
你是对的,谢谢!我在一个直的地方overmudryl。我会留下你的变体进行排序。
应用。
分区方法中存在错误。更正后的版本。
分区方法中存在错误。已更正版本。
针对数字字段被用于排序的特殊情况(最常见的情况),我编写了一个变体,它比之前的变体快了几个数量级。但它消耗的内存是前者的两倍。它适用于大型数组。
应用(测量执行时间)。
结果