//+------------------------------------------------------------------+
//| Внутренняя процедура: разделение Хоара |
//| Рекурсия только в меньшую половину => глубина стека O(log N) |
//+------------------------------------------------------------------+
void QuickSortRange(string &array[], int lo, int hi)
{
while(lo < hi)
{
int i = lo;
int j = hi;
string pivot = array[(lo + hi) / 2]; // опорный элемент — середина
while(i <= j)
{
while(array[i] < pivot) i++; // пропускаем "меньшие" слева
while(array[j] > pivot) j--; // пропускаем "большие" справа
if(i <= j)
{
string tmp = array[i];
array[i] = array[j];
array[j] = tmp;
i++;
j--;
}
}
// меньшую часть обрабатываем рекурсивно, большую — в цикле
if(j - lo < hi - i)
{
QuickSortRange(array, lo, j);
lo = i;
}
else
{
QuickSortRange(array, i, hi);
hi = j;
}
}
}
//+------------------------------------------------------------------+
//| Быстрая сортировка строкового массива по возрастанию |
//+------------------------------------------------------------------+
void Array_sort(string &array[])
{
int size = ArraySize(array);
if(size > 1)
QuickSortRange(array, 0, size - 1);
}
2. Тестовый скрипт (готовый файл)
Сохраните как MQL5\Scripts\ArraySortTest.mq5 . Тесты сравнивают результат с эталоннойсортировкой вставками (независимая реализация) на случайных данных — встроенный ArraySort строки не поддерживает, поэтому эталон пишем сами.
//+------------------------------------------------------------------+
//| ArraySortTest.mq5 |
//+------------------------------------------------------------------+
#property script_show_confirm
//--- сюда входит код Array_sort / QuickSortRange из блока выше ---
//--- счётчики ------------------------------------------------------
int g_total = 0;
int g_failed = 0;
//--- проверка упорядоченности --------------------------------------
bool IsSortedAsc(const string &arr[])
{
for(int k = 1; k < ArraySize(arr); k++)
if(arr[k - 1] > arr[k])
return(false);
return(true);
}
//--- печать результата одного теста ---------------------------------
void Report(const string test_name, const string &arr[])
{
g_total++;
bool ok = IsSortedAsc(arr);
if(!ok) g_failed++;
string dump = "";
int shown = MathMin(ArraySize(arr), 8);
for(int k = 0; k < shown; k++)
dump += (k > 0 ? " | " : "") + arr[k];
if(ArraySize(arr) > shown)
dump += " | ...";
PrintFormat("[%s] %-24s (%d эл.) %s", ok ? "OK " : "FAIL",
test_name, ArraySize(arr), dump);
}
//--- эталон: сортировка вставками ----------------------------------
void ReferenceSort(string &arr[])
{
int n = ArraySize(arr);
for(int i = 1; i < n; i++)
{
string key = arr[i];
int j = i - 1;
while(j >= 0 && arr[j] > key)
{
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
bool SameContents(const string &a[], const string &b[])
{
if(ArraySize(a) != ArraySize(b)) return(false);
for(int k = 0; k < ArraySize(a); k++)
if(a[k] != b[k]) return(false);
return(true);
}
//--- генератор случайных строк -------------------------------------
string RandomString()
{
string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int len = 1 + MathRand() % 12;
string s = "";
for(int k = 0; k < len; k++)
s += StringSubstr(alphabet, MathRand() % 62, 1);
return(s);
}
//+------------------------------------------------------------------+
//| Запуск всех тестов |
//+------------------------------------------------------------------+
void OnStart()
{
Print("=== Array_sort: тест быстрой сортировки строк ===");
string t_empty[]; // 1) пустой
Array_sort(t_empty); Report("Пустой массив", t_empty);
string t_one[] = {"alpha"}; // 2) один
Array_sort(t_one); Report("Один элемент", t_one);
string t_two[] = {"zebra", "apple"}; // 3) два
Array_sort(t_two); Report("Два элемента", t_two);
string t_srt[] = {"a","b","c","d","e"}; // 4) уже отсорт.
Array_sort(t_srt); Report("Уже отсортированный", t_srt);
string t_rev[] = {"e","d","c","b","a"}; // 5) обратный
Array_sort(t_rev); Report("Обратный порядок", t_rev);
string t_dup[] = {"bb","aa","cc","aa","bb","cc"}; // 6) дубликаты
Array_sort(t_dup); Report("Дубликаты", t_dup);
string t_cse[] = {"banana","Apple","apple","Zebra","_x","10","2"};
Array_sort(t_cse); Report("Регистр/цифры", t_cse); // 7) 'A'<'a'
//--- 8) случайные данные vs эталон -----------------------------
MathSrand(42);
for(int round = 0; round < 2; round++)
{
int n = (round == 0) ? 100 : 1000;
string rnd[], ref[];
ArrayResize(rnd, n); ArrayResize(ref, n);
for(int k = 0; k < n; k++)
{
string s = RandomString();
rnd[k] = s; ref[k] = s;
}
ulong t0 = GetMicrosecondCount();
Array_sort(rnd);
ulong ms = (GetMicrosecondCount() - t0) / 1000.0;
ReferenceSort(ref);
bool match = SameContents(rnd, ref);
bool ok = IsSortedAsc(rnd) && match;
g_total++; if(!ok) g_failed++;
PrintFormat("[%s] Случайных строк: %d, время: %.1f мс, совпадение с эталоном: %s",
ok ? "OK " : "FAIL", n, ms, match ? "да" : "НЕТ!");
}
//--- 9) массовые дубликаты (проверка вырожденного случая) ------
string t_eq[];
ArrayResize(t_eq, 3000);
for(int k = 0; k < 3000; k++) t_eq[k] = "same";
Array_sort(t_eq); Report("3000 одинаковых", t_eq);
Print("------------------------------------------------");
PrintFormat("ИТОГ: %d/%d тестов пройдено, ошибок: %d",
g_total - g_failed, g_total, g_failed);
}
3. Запуск и проверка результатов
Честно скажу: в этой сессии у меня нет доступа к компилятору MetaEditor или терминалу (из инструментов доступны только рыночные данные), поэтому физически выполнить скрипт я не могу. Вот как это сделать вам, плюс результат моей проверки алгоритма вручную.
Запуск: F7 в MetaEditor (компиляция, должно быть 0 errors ) → перетащить скрипт на любой график → открыть вкладку «Эксперты». Либо из командной строки:
=== Array_sort: тест быстрой сортировки строк === [OK ] Пустой массив (0 эл.) [OK ] Один элемент (1 эл.) alpha [OK ] Два элемента (2 эл.) apple | zebra [OK ] Уже отсортированный (5 эл.) a | b | c | d | e [OK ] Обратный порядок (5 эл.) a | b | c | d | e [OK ] Дубликаты (6 эл.) aa | aa | bb | bb | cc | cc [OK ] Регистр/цифры (7 эл.) 10 | 2 | Apple | Zebra | _x | apple | banana [OK ] Случайных строк: 100, время: 0.4 мс, совпадение с эталоном: да [OK ] Случайных строк: 1000, время: 4.8 мс, совпадение с эталоном: да [OK ] 3000 одинаковых (3000 эл.) same | same | ... ------------------------------------------------ ИТОГ: 10/10 тестов пройдено, ошибок: 0
проход 1: swap(e,a) → {a,d,c,b,e} , далее границы сужаются до (0..3)
проход 2: pivot="d", swap(d,b) → {a,b,c,d,e}
проход 3: pivot="b" → тривиальные части → итог a b c d e ✓
Примечания
Сложность: в среднем O(N·logN), память — только стек O(logN) благодаря рекурсии в меньшую половину. Массив из одинаковых элементов тоже разбивается пополам — деградации нет.
Сравнение — лексикографическое по кодам Unicode и регистрозависимое: 'A'(65) < '_'(95) < 'a'(97) . Для регистронезависимой версии замените array[i] < pivot на StringCompare(array[i], pivot, false) < 0 .
Если нужно по убыванию — поменяйте знаки < и > местами во внутренних циклах.
PS: Потребовалось дополнительное исследование с моделью. Произошли некоторые уточнения. Если будет интерес, добавлю.
Языковая модель работает в LM Studio и подключается к mcp терминала и редактора кода:
После некоторого времени mcp перестают работать и возвращают ошибки:
Так со всеми имеющимися инструментами.
Для воспроизведения нужна длительная непрерывная работа языковой модели.
Сетевая активность в моменте:
В логах терминала и редактора в этот момент ничего не появляется.
LM Studio:
Проверка работоспособности основных инструментов:
Не было такой проблемы. Я работал и с штатным ассистентом и с агентом Hermes. Никогда не было отказа в исполнении. Ну, по сути, бесплатное — не значит бесконечное. Наверняка есть лимиты дневные, недельные. Поэтому это, естественно, будет ограничивать время использования. Я не встречал ни на форуме, ни в описаниях, есть ли какие-то лимиты, ограничения по использованию MCP.
Vladimir Perervenko #: Не было такой проблемы. Я работал и с штатным ассистентом и с агентом Hermes. Никогда не было отказа в исполнении. Ну, по сути, бесплатное — не значит бесконечное. Наверняка есть лимиты дневные, недельные. Поэтому это, естественно, будет ограничивать время использования. Я не встречал ни на форуме, ни в описаниях, есть ли какие-то лимиты, ограничения по использованию MCP.
Я просто тестировал агента, вопрос в написании кода для сортировки строк не стоит :)).
Мне надо было, чтобы ассистент мог написать код и проверить его исполнение.
Точнее сказать жутчайший костыль, который приделывают к системам, где нет с обоих сторон нормального api и нет прямого http streaming протокола.
Я разрабатываю локальные MCP-серверы, используя стандартный ввод/вывод (stdio). Я не понимаю, зачем мне для этого использовать HTTP, ведь это вынудит меня использовать HTTP-сервер.
Конечно, я понимаю вашу точку зрения, у нас разные потребности.
Для авторизации и пользования сайтом MQL5.com необходимо разрешить использование файлов Сookie.
Пожалуйста, включите в вашем браузере данную настройку, иначе вы не сможете авторизоваться.
Вы вошли в аккаунт. Двухфакторная аутентификация отключена. Настройте её заново и отсканируйте новый QR-код или продолжите с отключённой двухфакторной аутентификацией.
Языковая модель работает в LM Studio и подключается к mcp терминала и редактора кода:
{ "mcpServers": { "metaeditor": { "url": "http://127.0.0.1:22345/mcp", "headers": { "Authorization": "Bearer bla-bla-bla" } }, "terminal": { "url": "http://127.0.0.1:22346/mcp", "headers": { "Authorization": "Bearer bla-bla-bla" } }, "marketdata": { "url": "https://www.metatrader.com/mcp", "headers": { "Authorization": "Bearer bla-bla-bla" } } } }После некоторого времени mcp перестают работать и возвращают ошибки:
Так со всеми имеющимися инструментами.
Для воспроизведения нужна длительная непрерывная работа языковой модели.
Сетевая активность в моменте:
В логах терминала и редактора в этот момент ничего не появляется.
LM Studio:
Проверка работоспособности основных инструментов:
1. Сама функция
//+------------------------------------------------------------------+ //| Внутренняя процедура: разделение Хоара | //| Рекурсия только в меньшую половину => глубина стека O(log N) | //+------------------------------------------------------------------+ void QuickSortRange(string &array[], int lo, int hi) { while(lo < hi) { int i = lo; int j = hi; string pivot = array[(lo + hi) / 2]; // опорный элемент — середина while(i <= j) { while(array[i] < pivot) i++; // пропускаем "меньшие" слева while(array[j] > pivot) j--; // пропускаем "большие" справа if(i <= j) { string tmp = array[i]; array[i] = array[j]; array[j] = tmp; i++; j--; } } // меньшую часть обрабатываем рекурсивно, большую — в цикле if(j - lo < hi - i) { QuickSortRange(array, lo, j); lo = i; } else { QuickSortRange(array, i, hi); hi = j; } } } //+------------------------------------------------------------------+ //| Быстрая сортировка строкового массива по возрастанию | //+------------------------------------------------------------------+ void Array_sort(string &array[]) { int size = ArraySize(array); if(size > 1) QuickSortRange(array, 0, size - 1); }2. Тестовый скрипт (готовый файл)
Сохраните как MQL5\Scripts\ArraySortTest.mq5 . Тесты сравнивают результат с эталонной сортировкой вставками (независимая реализация) на случайных данных — встроенный ArraySort строки не поддерживает, поэтому эталон пишем сами.
//+------------------------------------------------------------------+ //| ArraySortTest.mq5 | //+------------------------------------------------------------------+ #property script_show_confirm //--- сюда входит код Array_sort / QuickSortRange из блока выше --- //--- счётчики ------------------------------------------------------ int g_total = 0; int g_failed = 0; //--- проверка упорядоченности -------------------------------------- bool IsSortedAsc(const string &arr[]) { for(int k = 1; k < ArraySize(arr); k++) if(arr[k - 1] > arr[k]) return(false); return(true); } //--- печать результата одного теста --------------------------------- void Report(const string test_name, const string &arr[]) { g_total++; bool ok = IsSortedAsc(arr); if(!ok) g_failed++; string dump = ""; int shown = MathMin(ArraySize(arr), 8); for(int k = 0; k < shown; k++) dump += (k > 0 ? " | " : "") + arr[k]; if(ArraySize(arr) > shown) dump += " | ..."; PrintFormat("[%s] %-24s (%d эл.) %s", ok ? "OK " : "FAIL", test_name, ArraySize(arr), dump); } //--- эталон: сортировка вставками ---------------------------------- void ReferenceSort(string &arr[]) { int n = ArraySize(arr); for(int i = 1; i < n; i++) { string key = arr[i]; int j = i - 1; while(j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = key; } } bool SameContents(const string &a[], const string &b[]) { if(ArraySize(a) != ArraySize(b)) return(false); for(int k = 0; k < ArraySize(a); k++) if(a[k] != b[k]) return(false); return(true); } //--- генератор случайных строк ------------------------------------- string RandomString() { string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; int len = 1 + MathRand() % 12; string s = ""; for(int k = 0; k < len; k++) s += StringSubstr(alphabet, MathRand() % 62, 1); return(s); } //+------------------------------------------------------------------+ //| Запуск всех тестов | //+------------------------------------------------------------------+ void OnStart() { Print("=== Array_sort: тест быстрой сортировки строк ==="); string t_empty[]; // 1) пустой Array_sort(t_empty); Report("Пустой массив", t_empty); string t_one[] = {"alpha"}; // 2) один Array_sort(t_one); Report("Один элемент", t_one); string t_two[] = {"zebra", "apple"}; // 3) два Array_sort(t_two); Report("Два элемента", t_two); string t_srt[] = {"a","b","c","d","e"}; // 4) уже отсорт. Array_sort(t_srt); Report("Уже отсортированный", t_srt); string t_rev[] = {"e","d","c","b","a"}; // 5) обратный Array_sort(t_rev); Report("Обратный порядок", t_rev); string t_dup[] = {"bb","aa","cc","aa","bb","cc"}; // 6) дубликаты Array_sort(t_dup); Report("Дубликаты", t_dup); string t_cse[] = {"banana","Apple","apple","Zebra","_x","10","2"}; Array_sort(t_cse); Report("Регистр/цифры", t_cse); // 7) 'A'<'a' //--- 8) случайные данные vs эталон ----------------------------- MathSrand(42); for(int round = 0; round < 2; round++) { int n = (round == 0) ? 100 : 1000; string rnd[], ref[]; ArrayResize(rnd, n); ArrayResize(ref, n); for(int k = 0; k < n; k++) { string s = RandomString(); rnd[k] = s; ref[k] = s; } ulong t0 = GetMicrosecondCount(); Array_sort(rnd); ulong ms = (GetMicrosecondCount() - t0) / 1000.0; ReferenceSort(ref); bool match = SameContents(rnd, ref); bool ok = IsSortedAsc(rnd) && match; g_total++; if(!ok) g_failed++; PrintFormat("[%s] Случайных строк: %d, время: %.1f мс, совпадение с эталоном: %s", ok ? "OK " : "FAIL", n, ms, match ? "да" : "НЕТ!"); } //--- 9) массовые дубликаты (проверка вырожденного случая) ------ string t_eq[]; ArrayResize(t_eq, 3000); for(int k = 0; k < 3000; k++) t_eq[k] = "same"; Array_sort(t_eq); Report("3000 одинаковых", t_eq); Print("------------------------------------------------"); PrintFormat("ИТОГ: %d/%d тестов пройдено, ошибок: %d", g_total - g_failed, g_total, g_failed); }3. Запуск и проверка результатов
Честно скажу: в этой сессии у меня нет доступа к компилятору MetaEditor или терминалу (из инструментов доступны только рыночные данные), поэтому физически выполнить скрипт я не могу. Вот как это сделать вам, плюс результат моей проверки алгоритма вручную.
Запуск: F7 в MetaEditor (компиляция, должно быть 0 errors ) → перетащить скрипт на любой график → открыть вкладку «Эксперты». Либо из командной строки:
metaeditor64.exe /compile:"...\MQL5\Scripts\ArraySortTest.mq5" /log
Ожидаемый вывод журнала (времена примерные):
=== Array_sort: тест быстрой сортировки строк === [OK ] Пустой массив (0 эл.) [OK ] Один элемент (1 эл.) alpha [OK ] Два элемента (2 эл.) apple | zebra [OK ] Уже отсортированный (5 эл.) a | b | c | d | e [OK ] Обратный порядок (5 эл.) a | b | c | d | e [OK ] Дубликаты (6 эл.) aa | aa | bb | bb | cc | cc [OK ] Регистр/цифры (7 эл.) 10 | 2 | Apple | Zebra | _x | apple | banana [OK ] Случайных строк: 100, время: 0.4 мс, совпадение с эталоном: да [OK ] Случайных строк: 1000, время: 4.8 мс, совпадение с эталоном: да [OK ] 3000 одинаковых (3000 эл.) same | same | ... ------------------------------------------------ ИТОГ: 10/10 тестов пройдено, ошибок: 0
Ручная верификация (трассировка худшего случая {"e","d","c","b","a"} , pivot="c"):
Примечания
PS: Потребовалось дополнительное исследование с моделью. Произошли некоторые уточнения. Если будет интерес, добавлю.
Языковая модель работает в LM Studio и подключается к mcp терминала и редактора кода:
После некоторого времени mcp перестают работать и возвращают ошибки:
Так со всеми имеющимися инструментами.
Для воспроизведения нужна длительная непрерывная работа языковой модели.
Сетевая активность в моменте:
В логах терминала и редактора в этот момент ничего не появляется.
LM Studio:
Проверка работоспособности основных инструментов:
Быстрая сортировка строк для MQL5
Не было такой проблемы. Я работал и с штатным ассистентом и с агентом Hermes. Никогда не было отказа в исполнении. Ну, по сути, бесплатное — не значит бесконечное. Наверняка есть лимиты дневные, недельные. Поэтому это, естественно, будет ограничивать время использования. Я не встречал ни на форуме, ни в описаниях, есть ли какие-то лимиты, ограничения по использованию MCP.
Я просто тестировал агента, вопрос в написании кода для сортировки строк не стоит :)).
Мне надо было, чтобы ассистент мог написать код и проверить его исполнение.
Существует ли или будет ли возможность использовать локальный MCP-сервер с помощью STDIO?
Нет, это бессмысленный и устаревший метод.
Точнее сказать жутчайший костыль, который приделывают к системам, где нет с обоих сторон нормального api и нет прямого http streaming протокола.
После некоторого времени mcp перестают работать и возвращают ошибки:
Это сообщение самого LM Studio. Он по какой-то причине не может послать запросы.
Вы не показали логи терминала и редактора.
Нет, это бессмысленный и устаревший метод.
Точнее сказать жутчайший костыль, который приделывают к системам, где нет с обоих сторон нормального api и нет прямого http streaming протокола.
Я разрабатываю локальные MCP-серверы, используя стандартный ввод/вывод (stdio). Я не понимаю, зачем мне для этого использовать HTTP, ведь это вынудит меня использовать HTTP-сервер.
Конечно, я понимаю вашу точку зрения, у нас разные потребности.
О чём всё это?
Это сообщение самого LM Studio. Он по какой-то причине не может послать запросы.
Вы не показали логи терминала и редактора.
Тут уже другая задача. Всё в прикрепленном файле.
Похоже, что после определённого времени появляется ошибка.