Прежде чем решиться на создание этой темы, я провёл поиск по форуму и кое-что нашёл. Но у меня почему-то это не работает ...
Есть необходимость хранить информацию об открытых позициях, а именно цену открытия и тикет. Система учёта позиция хэджинговая, поэтому позиций по одному и тому же инструменту может быть несколько. Для хранения нужной информации я создал структуру с двумя полями, и массив для хранения этих структур. В какой-то момент возникла необходимость отсортировать массив структур по ценам открытия позиций.
Я нашёл вот здесь код для сортировки массива структур от @fxsaber:
Сохранил этот код в файле SortStruct.mqh. Затем отсюда взял вот такой пример для проверки:
Этот пример прекрасно работает, его вывод полностью совпадает с тем, что приведён самим @fxsaber по вышеупомянутой ссылке.
Вдохновлённый этим примером, я набросал свой скрипт, где объявил структуру, переменную и массив. Массив заполнил тестовыми данными, вывел на печать, отсортировал по полю price_open и снова вывел (всё почти также, как в предыдущем примере):
При компиляции этот скрипт не выдаёт ни одной ошибки. Но сортировка массива не производится. Вот результат выполнения этого примера:
Пожалуйста, помогите понять, что я делаю не так?
Почему в моём случае сортировка не производится и как сделать так, чтобы она производилась?
Как вообще сортируют массивы структур по произвольному полю в 2025 году?
Когда-то я это пробовал. Из нескольких вариантов получил желаемый результат. но потом отказался.
Используйте лучше массив объектов
#include <Arrays\ArrayObj.mqh> CArrayObj listObj; //--- Список объектов if(!listObj.Add(obj)) { delete obj;//--- Если добавление завершилось ошибкой — удалим этот объект printf("Что-то пошло не так %s %d",__FUNCTION__,__LINE__); continue; }
Примерно так добавили.
Сортируются так
listObj.Sort(0);
Но придётся писать свою виртуальную функцию сортировки
Можно сортировать по одному полю, по двум или как пожелаете. Главное всё описать в функции
virtual int Compare(const CObject *node, const int mode = 0) const;
Примерно так
/********************************************************************/ template <typename T1> int class::compare(T1 data1, T1 data2) const { if(data1 == data2) return 0; if(data1 > data2) return 1; return -1; };/*****************************************************************/ /********************************************************************/ int class::Compare(const CObject *node, const int mode = 0) const { const class *obj = node; //--- при mode==0 сравниваем символ if(mode == 0) return compare(this.getSymbol(), obj.getSymbol()); //--- при mode==1 сравниваем тикет if(mode == 1) return compare(this.m_ticket, obj.getTicket()); return -1; };/*****************************************************************/
Используйте лучше массив объектов
Я смотрел в сторону этого класса, но меня смутил вот этот момент (цитата из документации):
Разве моя простенькая структура является наследником класса CObject? Я только начинаю вникать в ООП и пока не понимаю этого.
Примерно так добавили.
Попробовал, не получается:
#include <Arrays\ArrayObj.mqh> struct open_position { ulong ticket; double price_open; }; void OnStart() { CArrayObj array; open_position pos; pos.ticket = 1; pos.price_open = 0.05; array.Add(pos); }
Попытка компиляции:
'pos' - parameter conversion not allowed
Цветом выделено место, на которое ругается компилятор.
@Alexey Viktorov, по вашему коду мне не очень понятно, какого типа переменная obj. Судя по имени это объект? Мне надо разобраться, как заменить структуру классом, унаследованным от CObject ?Попробовал, не получается:
Попытка компиляции:
Цветом выделено место, на которое ругается компилятор.
@Alexey Viktorov, по вашему коду мне не очень понятно, какого типа переменная obj. Судя по имени это объект? Мне надо разобраться, как заменить структуру объектом?Я тоже далёк от полного понимания ООП, но с помощью Тришкина освоил вот это и доволен собой как бегемот на болоте.
Да. Это должен быть класс, а не структура.
В общем последовательность такая:
Объявлена переменная класса tmpObj
Потом в этот объект добавляется, в моём случае символ
tmpObj.setSymbol(symbol); // это здесь. listObj.Sort(0); // Сортируем список не важно пустой или нет if(listObj.Search(&tmpObj) == -1) // Если такой объект не найден { CSpring *obj = new CSpring(symbol); // создали указатель и добавили объект в список if(!listObj.Add(obj)) delete obj;//--- Если добавление завершилось ошибкой — удалим этот объект }
Затем в этом списке можно искать любой объект как по одному параметру, например по символу, так и по двум, символу и ТФ например. Всё зависит от функции Compare() как вы напишете для себя.
Если я где-то неправильно называю указатель объектом, то меня кто-то поправит.
В итоге стоящую передо мной задачу удалось решить так:
#include <Arrays\ArrayObj.mqh> //+------------------------------------------------------------------+ //| Класс для хранения информации об открытой позиции | //+------------------------------------------------------------------+ class COpenPosition : public CObject { private: ulong m_ticket; // Тикет позиции double m_price; // Цена открытия позиции public: // Конструктор по умолчанию COpenPosition(void): m_ticket(0), m_price(0.0) {} // Конструктор с параметрами COpenPosition(const ulong ticket, const double price): m_ticket(ticket), m_price(price) {} // Деструктор ~COpenPosition(void) {} // Методы доступа к полям класса (геттеры) ulong Ticket(void) const { return m_ticket; } double Price(void) const { return m_price; } // Методы установки значений полей (сеттеры) void Ticket(const ulong ticket) { m_ticket = ticket; } void Price(const double price) { m_price = price; } // Переопределение метода Compare для сортировки по цене virtual int Compare(const CObject *node, const int mode=0) const { const COpenPosition *other = node; if(other == NULL) return 0; // Сравнение по цене if(m_price < other.Price()) return -1; if(m_price > other.Price()) return 1; return 0; } }; //+------------------------------------------------------------------+ //| Пример использования CArrayObj с сортировкой позиций по цене | //+------------------------------------------------------------------+ void OnStart() { // Создание массива объектов CArrayObj positions; // Включение флага освобождения элементов при удалении массива positions.FreeMode(true); // Создание позиций с разными ценами positions.Add(new COpenPosition(123456, 1.12345)); positions.Add(new COpenPosition(789012, 1.67890)); positions.Add(new COpenPosition(345678, 1.03456)); positions.Add(new COpenPosition(901234, 1.23456)); // Вывод информации до сортировки Print("--- Позиции до сортировки ---"); for(int i = 0; i < positions.Total(); i++) { COpenPosition *pos = positions.At(i); if(pos != NULL) Print("Позиция ", i, " - Тикет: ", pos.Ticket(), ", Цена: ", pos.Price()); } // Сортировка массива по возрастанию цены positions.Sort(0); // Вывод информации после сортировки Print("--- Позиции после сортировки по возрастанию цены ---"); for(int i = 0; i < positions.Total(); i++) { COpenPosition *pos = positions.At(i); if(pos != NULL) Print("Позиция ", i, " - Тикет: ", pos.Ticket(), ", Цена: ", pos.Price()); } }
@Alexey Viktorov, благодарю за помощь!
В итоге стоящую передо мной задачу удалось решить так:
@Alexey Viktorov, благодарю за помощь!
Огромная благодарность Артёму Тришкину за помощь. Это он меня научил этому. Я мучал его вопросами целую неделю. А может и больше…😊
Но у меня почему-то это не работает ...
1. ArraySwap возвращает false, код ошибки: ERR_INVALID_ARRAY 4006 Массив неподходящего типа, неподходящего размера или испорченный объект динамического массива
2. Изменяем код:
// объявляем переменную и массив open_position pos; //open_position array[6]; open_position array[]; ArrayResize(array, 6);
3. Результат:
Сортировка по цене: [ticket] [price_open] [0] 4 0.01000 [1] 6 0.02000 [2] 2 0.03000 [3] 1 0.05000 [4] 5 0.06000 [5] 3 0.08000
2. Изменяем код:
Бинго! Теперь и мой первоначальный пример работает!!!
Я на самом деле взял статический массив просто для примера. Мне казалось, так будет проще. А оказалось, что именно здесь собака порылась!
@trader6_1 и вам огромное спасибо за помощь!
Можно и статический и динамический.
#include <QuickSort.mqh> struct open_position { ulong ticket; double price_open; }; typedef bool (*FuncLess)( const open_position&, const open_position& ); bool Less( const open_position& struct1, const open_position& struct2 ) { return struct1.price_open < struct2.price_open; } void OnStart() { // объявляем переменную и массив open_position pos; open_position array[6]; // заполняем массив тестовыми данными pos.ticket = 1; pos.price_open = 0.05; array[0] = pos; pos.ticket = 2; pos.price_open = 0.03; array[1] = pos; pos.ticket = 3; pos.price_open = 0.08; array[2] = pos; pos.ticket = 4; pos.price_open = 0.01; array[3] = pos; pos.ticket = 5; pos.price_open = 0.06; array[4] = pos; pos.ticket = 6; pos.price_open = 0.02; array[5] = pos; // выводим на печать Print( "Массив как есть:" ); ArrayPrint( array ); QuickSort< open_position, FuncLess >( array, Less ); Print( "\nСортировка по цене:" ); ArrayPrint( array ); }
Библиотека QuickSort

- www.mql5.com

- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Прежде чем решиться на создание этой темы, я провёл поиск по форуму и кое-что нашёл. Но у меня почему-то это не работает ...
Есть необходимость хранить информацию об открытых позициях, а именно цену открытия и тикет. Система учёта позиция хэджинговая, поэтому позиций по одному и тому же инструменту может быть несколько. Для хранения нужной информации я создал структуру с двумя полями, и массив для хранения этих структур. В какой-то момент возникла необходимость отсортировать массив структур по ценам открытия позиций.
Я нашёл вот здесь код для сортировки массива структур от @fxsaber:
Сохранил этот код в файле SortStruct.mqh. Затем отсюда взял вот такой пример для проверки:
Этот пример прекрасно работает, его вывод полностью совпадает с тем, что приведён самим @fxsaber по вышеупомянутой ссылке.
Вдохновлённый этим примером, я набросал свой скрипт, где объявил структуру, переменную и массив. Массив заполнил тестовыми данными, вывел на печать, отсортировал по полю price_open и снова вывел (всё почти также, как в предыдущем примере):
При компиляции этот скрипт не выдаёт ни одной ошибки. Но сортировка массива не производится. Вот результат выполнения этого примера:
Пожалуйста, помогите понять, что я делаю не так?
Почему в моём случае сортировка не производится и как сделать так, чтобы она производилась?
Как вообще сортируют массивы структур по произвольному полю в 2025 году?