preview
Популяционные алгоритмы оптимизации: строим защиту от читеров

Популяционные алгоритмы оптимизации: строим защиту от читеров

MetaTrader 5Трейдинг |
61 0
Andrey Dik
Andrey Dik

Содержание

  1. Введение
  2. Результаты тестов
  3. Составной тест
  4. Выводы


Введение

В предыдущей статье мы обнаружили, что отдельные алгоритмы способны получать завышенные оценки не за счёт качества поиска, а за счёт случайного совпадения своей внутренней механики с геометрией тестовых функций. Мы выявили природу явления, сформулировали критерии диагностики и скорректировали тестовые функции Forest и Megacity. Это устранило возможность выигрыша вследствие перемещения поисковых агентов по «диагонали» в двумерной плоскости. Статья завершилась планом: прогнать все алгоритмы на обновлённом стенде и пересчитать рейтинг.

Данная статья — выполнение этого плана. Все 45 алгоритмов из рейтинговой таблицы были протестированы заново на скорректированных тестовых функциях. Помимо пересчёта, разработан составной тест на «читерство». Вместо одной функции с повторяющимися координатами агент одновременно оптимизирует пять различных функций с разными ландшафтами. Алгоритм с искусственным направленным смещением не способен одновременно «угадать» оптимум на пяти разных поверхностях, тогда как честный поисковый механизм покажет очень близкие результаты как на обновлённых тестовых функциях, так и на новой мульти-функции. Его задача — быстро и однозначно определить, обладает ли алгоритм реальной поисковой способностью, до запуска полного тестового стенда. Это своего рода входной фильтр, отсеивающий «пустышки» на раннем этапе. Речь идёт не о пересмотре методологии, а об устранении нескольких исключений, которые эксплуатировали конкретное расположение экстремумов.

По итогам прочтения трейдер получит обновлённую рейтинговую таблицу, очищенную от алгоритмов с ложно завышенными результатами, и готовый скрипт для самостоятельной проверки любого нового алгоритма перед тем, как доверить ему оптимизацию своей стратегии.


Результаты тестов

Приведём результаты тестирования первых 10 алгоритмов из нашей старой рейтинговой таблицы на новом стенде. 

ANS (72.73%) — уверенно занимает первое место, показав максимально возможный результат 1.0 на Forest и почти идеальный на Hilly при 5 функциях. Стабильно высокие результаты по всем трём функциям.

ANS|Across Neighbourhood Search|50.0|100.0|8.0|1.0|0.6|
=============================
5 Hilly's; Func runs: 10000; result: 0.9999999999875436
25 Hilly's; Func runs: 10000; result: 0.8822811736388573
500 Hilly's; Func runs: 10000; result: 0.40137720364864543
=============================
5 Forest's; Func runs: 10000; result: 1.0
25 Forest's; Func runs: 10000; result: 0.9528121725014275
500 Forest's; Func runs: 10000; result: 0.2809183267906096
=============================
5 Megacity's; Func runs: 10000; result: 0.9466666666666669
25 Megacity's; Func runs: 10000; result: 0.8573333333333336
500 Megacity's; Func runs: 10000; result: 0.2238933333333332
=============================
All score: 6.54528 (72.73%)

CLA (71.17%) —  третий результат в новом рейтинге. Высокие показатели на первых тестах всех функций (0.951, 0.993, 0.936), уверенное масштабирование на средних размерностях.

CLA|Code Lock Algorithm|100.0|8.0|0.8|0.03|
=============================
5 Hilly's; Func runs: 10000; result: 0.9513916030211934
25 Hilly's; Func runs: 10000; result: 0.8619898090237819
500 Hilly's; Func runs: 10000; result: 0.37878768991969275
=============================
5 Forest's; Func runs: 10000; result: 0.9934937994742749
25 Forest's; Func runs: 10000; result: 0.9350030299784114
500 Forest's; Func runs: 10000; result: 0.264969743691552
=============================
5 Megacity's; Func runs: 10000; result: 0.9359999999999999
25 Megacity's; Func runs: 10000; result: 0.8426666666666668
500 Megacity's; Func runs: 10000; result: 0.24059999999999984
=============================
All score: 6.40490 (71.17%)

AMOm (71.95%) — вторая позиция нового рейтинга с очень ровным профилем: ни на одной функции нет ни аномального взлёта, ни провала. Особенно хорош на высоких размерностях — 0.468 на Hilly-500 и 0.364 на Forest-500, одни из лучших показателей в таблице.

AMOm|Animal Migration Optimization M|50.0|8.0|10.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.9162371105304754
25 Hilly's; Func runs: 10000; result: 0.8360339347175263
500 Hilly's; Func runs: 10000; result: 0.46789660023174695
=============================
5 Forest's; Func runs: 10000; result: 0.9848161468170084
25 Forest's; Func runs: 10000; result: 0.9200997377060082
500 Forest's; Func runs: 10000; result: 0.3639111656785071
=============================
5 Megacity's; Func runs: 10000; result: 0.9173333333333332
25 Megacity's; Func runs: 10000; result: 0.8170666666666667
500 Megacity's; Func runs: 10000; result: 0.2517733333333329
=============================
All score: 6.47517 (71.95%)

(P+O)ES (69.63%) — лучший результат на Hilly-25 среди всей десятки (0.895). Сбалансированный алгоритм без слабых мест, хорошо справляется с задачами разного характера. 

(P_O)ES|Evolution Strategies|100.0|150.0|0.02|8.0|10.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.8657144873317885
25 Hilly's; Func runs: 10000; result: 0.8953901738038004
500 Hilly's; Func runs: 10000; result: 0.39739528286050285
=============================
5 Forest's; Func runs: 10000; result: 0.9776075492446766
25 Forest's; Func runs: 10000; result: 0.8981952542170181
500 Forest's; Func runs: 10000; result: 0.2687849185074435
=============================
5 Megacity's; Func runs: 10000; result: 0.9213333333333333
25 Megacity's; Func runs: 10000; result: 0.8024000000000001
500 Megacity's; Func runs: 10000; result: 0.23952000000000004
=============================
All score: 6.26634 (69.63%)

CTA (65.14%) — делит 9–10 место с ESG в новом рейтинге. Лучший в десятке результат на Megacity-5 (0.955), но самое резкое падение с ростом размерности: от 0.955 до 0.110 на Megacity. Алгоритм силён на компактных задачах, но хуже масштабируется. 

CTA|Comet Tail Algorithm|80.0|40.0|4.0|-1.0|0.2|1.0|0.5|0.1|15.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.9243464383277585
25 Hilly's; Func runs: 10000; result: 0.8678611260832623
500 Hilly's; Func runs: 10000; result: 0.2783803821000941
=============================
5 Forest's; Func runs: 10000; result: 0.9903857592716669
25 Forest's; Func runs: 10000; result: 0.8457126196030522
500 Forest's; Func runs: 10000; result: 0.19448478585260007
=============================
5 Megacity's; Func runs: 10000; result: 0.9546666666666669
25 Megacity's; Func runs: 10000; result: 0.6968000000000002
500 Megacity's; Func runs: 10000; result: 0.11008000000000102
=============================
All score: 5.86272 (65.14%)

TETA (65.21%) — почти идеальный результат на Forest-5 (0.997) и сильный на Megacity-25 (0.822), но слабее показатели на высоких размерностях: Forest-500 (0.144) и Megacity-500 (0.104) — самые низкие в десятке. 

TETA|Time Evolution Travel Algorithm (joo)|50.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.9145203656820382
25 Hilly's; Func runs: 10000; result: 0.8636891042289963
500 Hilly's; Func runs: 10000; result: 0.2557893068727686
=============================
5 Forest's; Func runs: 10000; result: 0.9965389719633986
25 Forest's; Func runs: 10000; result: 0.9129125157050326
500 Forest's; Func runs: 10000; result: 0.14394284935691087
=============================
5 Megacity's; Func runs: 10000; result: 0.8546666666666669
25 Megacity's; Func runs: 10000; result: 0.8221333333333336
500 Megacity's; Func runs: 10000; result: 0.10442666666666756
=============================
All score: 5.86862 (65.21%)

SDSm (68.63%) — сильные результаты на первых тестах всех функций (выше 0.92), но заметное снижение на высоких размерностях, особенно на Forest-500 (0.221) и Megacity-500 (0.214). 

SDSm|Stochastic Diffusion Search M|100.0|100.0|0.05|
=============================
5 Hilly's; Func runs: 10000; result: 0.9519471636297065
25 Hilly's; Func runs: 10000; result: 0.8494376697764915
500 Hilly's; Func runs: 10000; result: 0.3624897619727907
=============================
5 Forest's; Func runs: 10000; result: 0.9806113591666786
25 Forest's; Func runs: 10000; result: 0.8845675590592755
500 Forest's; Func runs: 10000; result: 0.2211247219431563
=============================
5 Megacity's; Func runs: 10000; result: 0.9226666666666669
25 Megacity's; Func runs: 10000; result: 0.7901333333333336
500 Megacity's; Func runs: 10000; result: 0.21379999999999993
=============================
All score: 6.17678 (68.63%)

ECBO (62.97%) — почти идеальный результат на Forest-5 (0.995) и сильный на Hilly-5 (0.940), но падение на высоких размерностях: Forest-500 всего 0.131. 

ECBO|Enhanced Colliding Bodies Optimization|50.0|20.0|0.7|
=============================
5 Hilly's; Func runs: 10000; result: 0.9402415265522688
25 Hilly's; Func runs: 10000; result: 0.7236308766253738
500 Hilly's; Func runs: 10000; result: 0.3235591845134633
=============================
5 Forest's; Func runs: 10000; result: 0.9947663805080049
25 Forest's; Func runs: 10000; result: 0.8029133468157632
500 Forest's; Func runs: 10000; result: 0.13055914998929397
=============================
5 Megacity's; Func runs: 10000; result: 0.8760000000000001
25 Megacity's; Func runs: 10000; result: 0.7016000000000002
500 Megacity's; Func runs: 10000; result: 0.17433333333333365
=============================
All score: 5.66760 (62.97%)

BOAm (60.41%) — единственный алгоритм в десятке, у которого Hilly-5 ниже 0.8 (0.762), зато самый стабильный по средним размерностям: разрыв между Hilly-25 (0.724) и Forest-25 (0.820) минимальный. Хороший результат на Forest-500 (0.289) — второй в десятке после AMOm, но провал на Megacity-500 (0.098) — самый низкий в таблице. 

BOAm|Billiards Optimization Algorithm M|50.0|10.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.7617749675007237
25 Hilly's; Func runs: 10000; result: 0.7242063623901942
500 Hilly's; Func runs: 10000; result: 0.2527483917912686
=============================
5 Forest's; Func runs: 10000; result: 0.9089006604555031
25 Forest's; Func runs: 10000; result: 0.819600230097181
500 Forest's; Func runs: 10000; result: 0.2885341267767846
=============================
5 Megacity's; Func runs: 10000; result: 0.8373333333333333
25 Megacity's; Func runs: 10000; result: 0.7461333333333333
500 Megacity's; Func runs: 10000; result: 0.09762666666666744
=============================
All score: 5.43686 (60.41%)

AAm (66.16%) — выделяется лучшим в десятке результатом на Hilly-500 (0.426) и Megacity-500 (0.287). Алгоритм лучше других масштабируется на высокие размерности, но уступает лидерам на малых. 

AAm|Archery Algorithm M|50.0|0.3|
=============================
5 Hilly's; Func runs: 10000; result: 0.8468452965108316
25 Hilly's; Func runs: 10000; result: 0.7332044456299903
500 Hilly's; Func runs: 10000; result: 0.42589593336440623
=============================
5 Forest's; Func runs: 10000; result: 0.9670855014018752
25 Forest's; Func runs: 10000; result: 0.7783747648133637
500 Forest's; Func runs: 10000; result: 0.27788504722761453
=============================
5 Megacity's; Func runs: 10000; result: 0.8613333333333332
25 Megacity's; Func runs: 10000; result: 0.7770666666666668
500 Megacity's; Func runs: 10000; result: 0.28711999999999954
=============================
All score: 5.95481 (66.16%)

Результаты прогона алгоритмов на обновлённом стенде получены и готовы к внесению в рейтинговую таблицу. Однако перед этим есть смысл сделать ещё один шаг, о котором речь пойдёт далее.

В ходе наших исследований было обнаружено, что некоторые алгоритмы оптимизации могут показывать завышенные результаты на отдельных тестовых функциях не за счёт качества поиска, а за счёт случайного совпадения внутренней механики алгоритма с геометрией ландшафта функции. Например, если алгоритм генерирует траектории преимущественно вдоль диагонали пространства поиска, а глобальный максимум расположен на этой диагонали, то оптимум будет находиться легче. Это не отражает реальную поисковую способность алгоритма.

HHO продемонстрировал подозрительно высокий результат на функции Forest — свыше 93% при том, что на Hilly той же размерности показывал лишь около 58%. Такой разрыв выходил за рамки обычного разброса и потребовал детального расследования. Анализ внутренней механики алгоритма выявил, что скалярные множители в формулах HHO порождают преимущественно диагональные траектории поиска, а глобальный максимум Forest располагался как раз вблизи диагонали пространства. Алгоритм не столько искал оптимум, сколько систематически «наезжал» на него за счёт совпадения направления движения с геометрией ландшафта. Мы назвали это явление «читерством».

Стандартный тестовый стенд запускает каждую из трёх тестовых функций (Hilly, Forest, Megacity) независимо, с тремя уровнями размерности: 10, 50 и 1000 координат одной и той же функции. При этом все пары координат агента оптимизируют одну и ту же поверхность. Алгоритм с систематическим смещением в определённом направлении может эксплуатировать эту однородность.

Для предварительного выявления такого поведения был разработан составной тест. Принцип прост: вместо 10 координат одной функции (5 пар) мы используем 5 разных функций — Hilly, Forest, Megacity, Peaks и Skin. Каждой функции назначается одна пара координат. Каждая пара живёт в собственном ландшафте и индивидуальном допустимом диапазоне: Hilly оптимизируется в [-3, 3], Forest в [-42.5, -37] × [-45, -39.8], Megacity в [-10, -2] × [-10.5, 10] и так далее. Итоговый fitness агента вычисляется как среднее значение Core() по всем пяти функциям.

Ключевое свойство теста: алгоритм не может «обмануть» его тем же способом, что и одиночную функцию. Любой читерский приём, к примеру, применимый для Forest, бесполезен для Hilly или Megacity с их совершенно другой геометрией и другими диапазонами координат. Чтобы получить высокий результат на составном тесте, алгоритм должен действительно уметь искать оптимум в каждом из пяти различных ландшафтов независимо.

Интерпретация результатов проста. Если алгоритм «честный», его результат на составном тесте будет примерно соответствовать среднему результату первого теста (5 функций) стандартного стенда по тем же функциям, с небольшим отклонением. Если же алгоритм завышает результат на какой-либо одной функции за счёт геометрического совпадения, на составном тесте это преимущество исчезнет, и разница между стандартным и составным тестом будет значительной. Чем больше это расхождение — тем сильнее алгоритм эксплуатирует особенности конкретной функции вместо реального поиска.


Составной тест

Скрипт Test_AO_AntiCheat построен максимально просто и не требует визуализации — только вывод результатов в журнал.

При запуске алгоритм оптимизации выбирается из выпадающего списка через параметр AOexactly_P, что позволяет быстро переключаться между любыми алгоритмами без перекомпиляции. Два оставшихся параметра задают количество вычислений функции (NumbTestFuncRuns_P) и число повторных прогонов (NumberRepetTest_P).

В начале работы скрипт создаёт пять объектов тестовых функций: Hilly, Forest, Megacity, Peaks и Skin. Далее формируются массивы rangeMin и rangeMax длиной 10 элементов (5 пар координат). Каждая пара получает границы поиска от своей функции: элементы 0-1 заполняются доменом Hilly, элементы 2-3 — доменом Forest, и так далее. Массив rangeStep заполняется нулями, поскольку дискретизация аргументов не используется.

Число эпох вычисляется стандартным способом — общее количество вычислений делится на размер популяции. Далее запускается основной цикл повторных прогонов. В каждом прогоне алгоритм инициализируется заново, и внутренний цикл по эпохам выполняет стандартную последовательность: вызов Moving(), расчёт fitness, вызов Revision().

Расчёт fitness — единственное отличие от стандартного скрипта. Вместо вызова f.CalcFunc(ao.a[set].c), который передаёт все координаты одной функции, здесь для каждого агента выполняется цикл по пяти функциям. Каждая функция получает свою пару координат через прямой вызов Core(x, y), результаты суммируются и делятся на пять. Поскольку все функции возвращают нормализованные значения в диапазоне [0, 1], итоговый fitness тоже лежит в [0, 1].

После каждого прогона в журнал выводится достигнутый результат ao.fB. По завершении всех прогонов выводится среднее значение и его процентное выражение. Этот процент — индикатор. Достаточно сравнить его со средним значением первого теста стандартного стенда, чтобы оценить «честность» алгоритма.

//+------------------------------------------------------------------+
void OnStart()
 {
  C_AO *AO = SelectAO(AOexactly_P);

  if(AO == NULL)
   {
    Print("AO is not selected...");
    return;
   }

  Print(AO.GetName(), "|", AO.GetDesc(), "|", AO.GetParams());

//--- создаём 5 функций
#define NFUNCS 5
  C_Function *funcs [NFUNCS];
  funcs [0] = new C_Hilly();
  funcs [1] = new C_Forest();
  funcs [2] = new C_Megacity();
  funcs [3] = new C_Peaks();
  funcs [4] = new C_Skin();

//--- 10 координат: пара 0-1 = Hilly, 2-3 = Forest, 4-5 = Megacity,
//                   6-7 = Peaks, 8-9 = Skin
  int params = NFUNCS * 2;

  double rangeMin  [];
  double rangeMax  [];
  double rangeStep [];
  ArrayResize(rangeMin,  params);
  ArrayResize(rangeMax,  params);
  ArrayResize(rangeStep, params);

  for(int i = 0; i < NFUNCS; i++)
   {
    rangeMin  [i * 2]     = funcs [i].GetMinRangeX();
    rangeMax  [i * 2]     = funcs [i].GetMaxRangeX();
    rangeStep [i * 2]     = 0.0;

    rangeMin  [i * 2 + 1] = funcs [i].GetMinRangeY();
    rangeMax  [i * 2 + 1] = funcs [i].GetMaxRangeY();
    rangeStep [i * 2 + 1] = 0.0;
   }

//--- запуск тестов
  int    epochCount = NumbTestFuncRuns_P / (int)AO.params [0].val;
  double aveResult  = 0.0;

  Print("=============================");
  Print("Composite test: Hilly + Forest + Megacity + Peaks + Skin");
  Print("Coordinates: ", params, "; Epochs: ", epochCount,
        "; Repeats: ", NumberRepetTest_P);
  Print("=============================");

  for(int test = 0; test < NumberRepetTest_P; test++)
   {
    if(!AO.Init(rangeMin, rangeMax, rangeStep, epochCount))
      break;

    for(int epochCNT = 1; epochCNT <= epochCount && !IsStopped(); epochCNT++)
     {
      AO.Moving();

      //--- расчёт fitness для каждого агента
      for(int set = 0; set < ArraySize(AO.a); set++)
       {
        double sum = 0.0;
        for(int i = 0; i < NFUNCS; i++)
         {
          sum += funcs [i].Core(AO.a [set].c [i * 2],
                                AO.a [set].c [i * 2 + 1]);
         }
        AO.a [set].f = sum / NFUNCS;
       }

      AO.Revision();
     }

    Print("Run ", test + 1, "/", NumberRepetTest_P, ": ", AO.fB);
    aveResult += AO.fB;
   }

  aveResult /= (double)NumberRepetTest_P;

  Print("=============================");
  Print("Average result: ", DoubleToString(aveResult, 10),
        " (", DoubleToString(aveResult * 100.0, 2), "%)");
  Print("=============================");

//--- освобождение
  for(int i = 0; i < NFUNCS; i++)
    delete funcs [i];
  delete AO;
 }
//+------------------------------------------------------------------+

Теперь можем перейти к распечатке результатов. Результаты очень показательные и хорошо демонстрируют работу теста.

DOAm (53.68%) и HHO (53.18%) показали практически одинаковый результат на составном тесте. Однако на стандартном стенде их общие оценки заметно различались: DOAm — 73.63%, HHO — 68.32%. Особенно бросается в глаза поведение на Forest: оба алгоритма показывали на этой функции аномально высокие результаты (DOAm — 94.1%, HHO — 92.9% на первом тесте с 5 функциями), значительно превышающие их результаты на Hilly. Составной тест это преимущество «отрезал» — когда Forest стоит рядом с четырьмя другими функциями с совершенно разными доменами и ландшафтами, эксплуатировать геометрию одной конкретной функции уже невозможно. Падение с ~73% и ~68% до ~53% — это существенное расхождение, указывающее на то, что часть результата на стандартном стенде была «незаслуженной».

DOAm|Dingo Optimization Algorithm M|50.0|0.5|0.7|
=============================
Composite test: Hilly + Forest + Megacity + Peaks + Skin
Coordinates: 10; Epochs: 200; Repeats: 10
=============================
Run 1/10: 0.4239956151778058
Run 2/10: 0.6031577198849927
Run 3/10: 0.472651762215779
Run 4/10: 0.44242763860374995
Run 5/10: 0.393561526388916
Run 6/10: 0.58159034825664
Run 7/10: 0.58159034825664
Run 8/10: 0.6044791403615191
Run 9/10: 0.6682691450306482
Run 10/10: 0.5960407868510031
=============================
Average result: 0.5367764031 (53.68%)
=============================

HHO|Harris Hawks Optimization|50.0|1.5|
=============================
Composite test: Hilly + Forest + Megacity + Peaks + Skin
Coordinates: 10; Epochs: 200; Repeats: 10
=============================
Run 1/10: 0.5647280120475809
Run 2/10: 0.5866885383601005
Run 3/10: 0.510840192697806
Run 4/10: 0.510840192697806
Run 5/10: 0.5801540782975321
Run 6/10: 0.5801540782975321
Run 7/10: 0.6101617039102479
Run 8/10: 0.4505520166668432
Run 9/10: 0.4505520166668432
Run 10/10: 0.4732281103689847
=============================
Average result: 0.5317898940 (53.18%)
=============================

ANS (98.38%) показал впечатляющий результат: практически идеальное решение на пяти разных функциях одновременно. Несколько прогонов дали 0.9999 — фактически точное нахождение глобальных максимумов всех пяти функций. Это говорит о том, что высокие результаты ANS на стандартном стенде полностью обусловлены качеством поискового механизма, а не эксплуатацией особенностей конкретных ландшафтов. Алгоритм одинаково хорошо работает независимо от геометрии и домена функции.

ANS|Across Neighbourhood Search|50.0|100.0|8.0|1.0|0.6|
=============================
Composite test: Hilly + Forest + Megacity + Peaks + Skin
Coordinates: 10; Epochs: 200; Repeats: 10
=============================
Run 1/10: 0.9866666666663436
Run 2/10: 0.9866666666666667
Run 3/10: 0.9999999999999998
Run 4/10: 0.9994983755015288
Run 5/10: 0.9069704495992525
Run 6/10: 0.9861650421661512
Run 7/10: 0.98612941584339
Run 8/10: 0.9999999999999993
Run 9/10: 0.9866666666666623
Run 10/10: 0.999498375502054
=============================
Average result: 0.9838261659 (98.38%)
=============================

CLA (96.70%) подтвердил аналогичную картину — стабильно высокие результаты на всех прогонах, практически все выше 98% (с двумя выбросами около 90%, что нормально для стохастического процесса). Это тоже «честный» алгоритм.

CLA|Code Lock Algorithm (joo)|100.0|8.0|0.8|0.03|
=============================
Composite test: Hilly + Forest + Megacity + Peaks + Skin
Coordinates: 10; Epochs: 100; Repeats: 10
=============================
Run 1/10: 0.9814189578704682
Run 2/10: 0.9839805249712157
Run 3/10: 0.9847263113568381
Run 4/10: 0.9849091877632024
Run 5/10: 0.9064307824513899
Run 6/10: 0.9848008598052127
Run 7/10: 0.8930626122526194
Run 8/10: 0.9856223196479059
Run 9/10: 0.9795896538911133
Run 10/10: 0.9854045893497755
=============================
Average result: 0.9669945799 (96.70%)

Итог: тест чётко разделил алгоритмы на две группы. ANS и CLA показали, что их поисковый механизм работает универсально. DOAm и HHO потеряли около 20 процентных пунктов — это и есть та доля их стандартного результата, которая приходилась на «везение» с геометрией отдельных функций, а не на реальную поисковую способность.

Поэтому DOAm и HHO не будут присутствовать в нашей рейтинговой таблице, поскольку включение таких алгоритмов в рейтинг исказило бы общую картину и ввело бы в заблуждение относительно их реальной эффективности.

После обновления тестовых функций (максимума Megacity и корректировки Forest) рейтинговая таблица была полностью пересчитана. Сравнение старых и новых результатов показало, что большинство алгоритмов сохранили свои позиции с незначительными отклонениями. Несколько алгоритмов улучшили результат на 4–6 пунктов: SSG (+5.8), AMOm (+5.4), SDSm (+5.2), (PO)ES (+5.0), SIA (+4.7). У некоторых наблюдалось небольшое снижение: BOAm (−1.8), BSA backtracking (−1.9), CSO (−1.6). Ряд алгоритмов — CTA, ECBO, DOA, FBA — изменились менее чем на 1 процентный пункт. В целом расхождения не выходили за рамки ожидаемого: изменение геометрии тестовых функций естественным образом перераспределяет результаты, одним алгоритмам новый ландшафт подходит чуть лучше, другим — чуть хуже.

Однако один алгоритм вызвал вопросы — HS (Harmony Search). Его общий результат вырос с 52.79% до 60.60%, что составляет 7.8 процентных пунктов — заметно больше, чем у остальных. Причём весь прирост пришёлся на одну функцию: результат первого теста Megacity вырос с 0.620 до 0.917, а суммарный балл по Megacity — с 1.097 до 1.698. На Hilly и Forest результаты HS практически не изменились. Столь резкий скачок на одной конкретной функции потребовал проверки: действительно ли HS стал лучше искать, или же его механика случайно совпала с новой геометрией Megacity?

Для ответа на этот вопрос мы прогнали HS через составной тест. HS чист. 92.45% — это примерно уровень ANS (98.38%) и CLA (96.70%) на том же составном тесте.

HS|Harmony Search|50.0|0.9|0.1|0.1|
=============================
Composite test: Hilly + Forest + Megacity + Peaks + Skin
Coordinates: 10; Epochs: 200; Repeats: 10
=============================
Run 1/10: 0.8521718129502356
Run 2/10: 0.8521718129502356
Run 3/10: 0.9800589497283483
Run 4/10: 0.9800589497283483
Run 5/10: 0.9949839619589923
Run 6/10: 0.9949839619589923
Run 7/10: 0.9949839619589923
Run 8/10: 0.8064827441874302
Run 9/10: 0.8064827441874302
Run 10/10: 0.9828288881157536
=============================
Average result: 0.9245207788 (92.45%)
=============================

Для сравнения, алгоритмы, уличённые в «читерстве» (DOAm и HHO), на том же тесте набрали лишь 53.68% и 53.18%. Разница очевидна: HS действительно умеет искать оптимум на разных ландшафтах одновременно. 

Теперь наша рейтинговая таблица завершена и выглядит следующим образом:

cc AO Description Hilly Hilly
Final
Forest Forest
Final
Megacity (discrete) Megacity
Final
Final
Result
% of
MAX
10 p (5 F)50 p (25 F)1000 p (500 F)10 p (5 F)50 p (25 F)1000 p (500 F)10 p (5 F)50 p (25 F)1000 p (500 F)
1ANSacross neighbourhood search1,000000,882280,401382,283661,000000,952810,280922,233730,946670,857330,223892,027896,54572,72
2AMOmanimal migration optimization M0,916240,836030,467902,220170,984820,920100,363912,268830,917330,817070,251771,986176,47571,94
3CLAcode lock algorithm (joo)0,951390,861990,378792,192170,993490,935000,264972,193460,936000,842670,240602,019276,40571,17
4(P+O)ES(P+O) evolution strategies0,865710,895390,397402,158500,977610,898200,268782,144590,921330,802400,239521,963256,26669,62
5SDSmstochastic diffusion search M0,951950,849440,362492,163880,980610,884570,221122,086300,922670,790130,213801,926606,17768,63
6AAmarchery algorithm M0,846850,733200,425902,005950,967090,778370,277892,023350,861330,777070,287121,925525,95566,17
7SIAsimulated isotropic annealing (joo)0,935430,865040,384832,185300,940690,806090,238351,985130,864000,661600,195361,720965,89165,46
8TETAtime evolution travel algorithm (joo)0,914520,863690,255792,034000,996540,912910,143942,053390,854670,822130,104431,781235,86965,21
9ESGevolution of social groups (joo)0,981110,798570,311672,091350,989540,822700,150321,962560,921330,734400,153151,808885,86365,14
10CTAcomet tail algorithm (joo)0,924350,867860,278382,070590,990390,845710,194482,030580,954670,696800,110081,761555,86365,14
11ECBOenhanced colliding bodies optimization0,940240,723630,323561,987430,994770,802910,130561,928240,876000,701600,174331,751935,66862,98
12DAdialectical algorithm0,931170,754000,262051,947220,989250,813750,086621,889620,926670,681070,113151,720895,55861,76
13BBObiogeography based optimization0,958760,706090,357522,022370,929810,706600,169701,806110,874670,630130,208131,712935,54161,57
14BHAmblack hole algorithm M0,795580,762070,346821,904470,998360,757980,138261,894600,850670,644270,170201,665145,46460,71
15HSharmony search0,914200,690490,299241,903930,976270,733730,141931,851930,917330,627200,153641,698175,45460,60
16RFOroyal flush optimization (joo)0,809890,744810,345461,900160,952510,779260,151851,883620,804000,664270,190711,658985,44360,48
17BOAmbilliards optimization algorithm M0,761770,724210,252751,738730,908900,819600,288532,017030,837330,746130,097631,681095,43760,41
18ASOanarchy society optimization0,730700,737130,311951,779780,997320,877000,176192,050510,720000,687730,189881,597615,42860,31
19EOmextremal optimization_M0,765270,752050,319081,836400,999990,764260,124371,888620,841330,641330,152471,635135,36059,56
20ACSartificial cooperative search0,755450,771620,316531,843601,000000,804880,107051,911930,769330,608000,141571,518905,27458,60
21SSGsaplings sowing and growing0,754360,632060,359351,745770,919070,696940,197551,813560,818670,605330,213471,637475,19757,74
22AOSmatomic orbital search M0,761840,684350,313441,759630,900150,800440,115011,815600,828000,632800,156961,617765,19357,70
23TSEAturtle shell evolution algorithm (joo)0,958090,648520,295711,902320,995220,581040,105421,681680,921330,521600,145671,588605,17357,48
24DEdifferential evolution0,963980,623460,260891,848330,984820,770180,114591,869590,930670,362130,110001,402805,12156,90
25BIOblood inheritance optimization (joo)0,725800,665220,312281,703300,999950,681250,115401,796600,854670,593330,153641,601645,10256,69
26(PO)ES(PO) evolution strategies0,739720,581900,388961,710580,911990,599750,212621,724360,824000,562400,234321,620725,05656,18
27BObonobo optimizer0,755550,643660,326571,725780,943320,704420,139991,787730,734670,614400,167281,516355,03055,89
28SRAsuccessful restaurateur algorithm (joo)0,890100,633590,291151,814840,966340,552850,089141,608330,893330,528000,139111,560444,98455,38
29CROchemical reaction optimisation0,912810,656810,298661,868280,905130,560200,109391,574720,828000,501330,141491,470824,91454,60
30BCOmbacterial chemotaxis optimization M0,825890,617330,315841,759060,952960,637180,119841,709980,765330,516530,158001,439864,90954,54
31DOAdream optimization algorithm0,785220,781210,360361,926790,615840,421170,122541,159550,866670,725870,211271,803814,89054,33
32ABOafrican buffalo optimization0,922950,625280,298851,847080,929920,574680,093721,598320,733330,513330,143241,389904,83553,72
33BSAbird swarm algorithm0,944320,679410,264011,887740,916490,656190,120541,693220,809330,335470,106521,251324,83253,69
34TSmtabu search M0,878060,610400,289931,778390,981160,521650,085441,588250,826670,495470,135521,457664,82453,60
35BSAbacktracking search algorithm0,871280,531900,286751,689930,924080,516020,091531,531630,960000,472530,137601,570134,79253,24
36WOAmwhale optimization algorithm M0,938930,594770,266951,800650,980360,538730,071121,590210,786670,476000,118921,381594,77253,02
37CSOcompetitive swarm optimizer0,851510,607860,298961,758330,840850,584910,119741,545500,800000,485600,141841,427444,73152,57
38FBAfractal-based algorithm0,694190,642670,289551,626410,998120,549050,087051,634220,761330,512530,136891,410754,67151,90
39ECOieco-inspired evolutionary algorithm0,788170,544020,293601,625790,889960,465920,097471,453350,785330,451730,142951,380014,45949,54
40BSObrain storm optimization0,922070,576250,297321,795640,807640,425080,094481,327200,772000,365330,130651,267984,39148,79
41CAmcamel algorithm M0,715340,569170,359851,644360,840940,471740,108501,421180,704000,419470,195631,319104,38548,72
42ACOmant colony optimization_M0,718850,484100,309901,512850,757920,486390,118711,363020,836000,486670,161481,484154,36048,44
43BSObrain storm optimization 0,913310,558130,297051,768490,853290,440380,094471,388140,722670,328800,133251,184724,34148,23
44AEFAartificial electric field algorithm0,887980,657690,252761,798430,955500,636020,039461,630980,608000,160000,098450,866454,29647,73
45SOAsimple optimization algorithm0,916640,470400,270951,657990,882640,315460,060441,258540,829330,317330,115791,262454,17946,43
RWrandom walk0,499700,323330,257911,080940,307540,114700,044000,466240,361330,170130,102440,633902,18124,23


Выводы

В данной статье мы завершили работу, начатую в предыдущей: от диагностики проблемы перешли к её полному устранению. Основные результаты:

  • Все 45 алгоритмов были протестированы на обновлённых тестовых функциях с пересчётом рейтинговой таблицы. Подавляющее большинство алгоритмов показали результаты, близкие к прежним — отклонения составили от долей процента до 5–6 пунктов, что укладывается в естественный разброс при изменении ландшафта. Это подтвердило надёжность тестового стенда как инструмента: его методология работает корректно, а выявленная проблема касалась лишь нескольких алгоритмов-исключений.
  • Алгоритмы HHO и DOAm были идентифицированы как «читеры» и исключены из рейтинговой таблицы. Составной тест показал для них результат около 53% — уровень, несопоставимый с их прежними оценками на стандартном стенде (68% и 73%). Для сравнения, алгоритмы из верхней части таблицы — ANS, CLA, HS — на том же составном тесте показали 96–99%, подтвердив универсальность своего поискового механизма.
  • Разработан скрипт составного теста на устойчивость к геометрическому смещению. Пять различных функций (Hilly, Forest, Megacity, Peaks, Skin) с разными доменами и ландшафтами объединены в одну задачу с 10 координатами. Один запуск этого скрипта занимает несколько секунд и даёт однозначный ответ: если результат значительно ниже, чем среднее первого теста стандартного стенда — алгоритм эксплуатирует геометрию, а не ищет. Рекомендуется использовать этот скрипт как входной фильтр перед полным прогоном на тестовом стенде.

Для практикующего трейдера всё это имеет прямое значение. Алгоритмы оптимизации используются в торговле повсеместно — для подбора параметров торговых стратегий, настройки индикаторов, оптимизации портфеля. Если алгоритм завышает результаты на тестовых задачах из‑за случайного совпадения с их геометрией, то на реальных задачах он даст далёкие от оптимума параметры и создаст ложное ощущение качества оптимизации. Наш инструментарий для выявления «читерства» помогает отсеять такие алгоритмы ещё на этапе выбора и использовать только те, которые действительно обладают качественным поисковым механизмом.

Практическая рекомендация для трейдера: перед тем как использовать новый алгоритм оптимизации для подбора параметров торговой стратегии, прогоните его через составной тест. Если результат составного теста существенно расходится с результатами стандартного стенда — не доверяйте этому алгоритму, такой алгоритм не справится с реальной задачей так же, как пасует перед составным тестом. Все описанные инструменты — скрипт составного теста, обновлённые тестовые функции и 3D-панель визуализации — прилагаются к статье и готовы к использованию.

tab

Рисунок 1. Цветовая градация алгоритмов по соответствующим тестам

tab

Рисунок 2. Гистограмма результатов (0–100; больше — лучше, 100 — теоретический максимум). В архиве — скрипт для расчёта рейтинговой таблицы.


К статье прикреплён архив с актуальными версиями кодов алгоритмов. Автор не несёт ответственности за абсолютную точность в описании канонических алгоритмов, во многие из них были внесены изменения для улучшения поисковых возможностей. Выводы и суждения, представленные в статьях, основываются на результатах проведённых экспериментов.


Программы, используемые в статье

#ИмяТипОписание
1#C_AO.mqh
Включаемый файл
Родительский класс популяционных алгоритмов оптимизации
2#C_AO_enum.mqh
Включаемый файл
Перечисление популяционных алгоритмов оптимизации
3TestFunctions.mqh
Включаемый файл
Библиотека тестовых функций
4
TestStandFunctions.mqh
Включаемый файл
Библиотека функций тестового стенда
5TestStand3D.mqhВключаемый файл3D-панель визуализации для тестового стенда 
6Utilities.mqh
Включаемый файл
Библиотека вспомогательных функций
7Test_AO_All.mq5СкриптЕдиный испытательный стенд для всех популяционных алгоритмов оптимизации
8Verify_Extremes.mq5Скрипт
Поиск RAW-экстремумов + 2D-тепловая карта функции
9Test_AO_AntiCheat.mq5Скрипт Тест на читерство алгоритмов оптимизации
Прикрепленные файлы |
UpdatedRating.zip (425.71 KB)
Моделирование рынка: Первые шаги на SQL в MQL5 (I) Моделирование рынка: Первые шаги на SQL в MQL5 (I)
В сегодняшней статье мы начнём изучать использование SQL в коде MQL5. Мы также рассмотрим, как можно создать базу данных. Или, точнее, как создать файл базы данных в SQLite, используя ресурсы или процедуры, включенные в язык MQL5. Мы также увидим, как создать таблицу, а затем как установить связь между таблицами с помощью первичного и внешнего ключей. Всё это, опять же, с использованием MQL5. Мы увидим, как легко создать код, который в будущем можно будет перенести в другие реализации SQL, используя класс, помогающий скрыть созданную реализацию. И, что самое важное, мы увидим, что в разные моменты мы можем столкнуться с риском того, что при использовании SQL что-то пойдет не так. Это происходит так, потому что в коде MQL5 SQL-код всегда будет помещаться внутри строки.
Разработка инструментария для анализа Price Action (Часть 33): Инструмент на основе теории свечного диапазона Разработка инструментария для анализа Price Action (Часть 33): Инструмент на основе теории свечного диапазона
Улучшите свое понимание рынка с помощью набора инструментов Candle-Range Theory для MetaTrader 5 – полностью нативного решения на MQL5 на основе теории свечного диапазона, которое превращает необработанные ценовые бары в информацию о волатильности в реальном времени. Легковесная библиотека CRangePattern сопоставляет истинный диапазон каждой свечи с адаптивным ATR и классифицирует ее в момент закрытия; затем CRT Indicator отображает эти классификации на графике в виде четких цветовых прямоугольников и стрелок, которые сразу показывают зоны сжатия, резкие пробои и полное поглощение диапазона.
Статистический арбитраж на основе коинтегрированных акций (Часть 7): Система оценки 2 Статистический арбитраж на основе коинтегрированных акций (Часть 7): Система оценки 2
В данной статье описываются два дополнительных критерия оценки, используемых при отборе корзин акций для торговли в стратегиях возврата к среднему, а точнее — в статистическом арбитраже на основе коинтеграции. Данная статья дополняет предыдущую публикацию, в которой были представлены показатели ликвидности и силы векторов коинтеграции, а также стратегические критерии — временной интервал и период ретроспективы, — за счет включения показателей стабильности векторов коинтеграции и времени возврата к среднему значению (полупериод). В статье приведены результаты бэктеста с применением новых фильтров с комментариями, а также предоставлены файлы, необходимые для его воспроизведения.
Как создать и оптимизировать торговую систему на основе циклов (Detrended Price Oscillator — DPO) Как создать и оптимизировать торговую систему на основе циклов (Detrended Price Oscillator — DPO)
В этой статье объясняется, как спроектировать и оптимизировать торговую систему с использованием индикатора «Бестрендовый ценовой осциллятор» (Detrended Price Oscillator, DPO) на MQL5. В ней описывается основная логика индикатора, демонстрирующая, как он определяет краткосрочные циклы, отфильтровывая долгосрочные тенденции. С помощью серии пошаговых примеров и простых стратегий читатели узнают, как его кодировать, определять сигналы входа и выхода, а также проводить тестирование на истории. Наконец, в статье представлены практические методы оптимизации для повышения эффективности и адаптации системы к изменчивым рыночным условиям.