preview
Эко-эволюционный алгоритм — Eco-inspired Evolutionary Algorithm (ECO)

Эко-эволюционный алгоритм — Eco-inspired Evolutionary Algorithm (ECO)

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

Содержание

  1. Введение
  2. Реализация алгоритма
  3. Результаты тестов
  4. Выводы


Введение

В данной статье познакомимся с алгоритмом оптимизации, также решением, подсмотренным у природы. Eco-inspired Evolutionary Algorithm  — это метаэвристический метод оптимизации, который использует экологические концепции (местообитание, взаимоотношения видов, экологическая сукцессия) для моделирования поиска решений. Он был предложен в начале 2010‑х годов как расширение идей эволюционных алгоритмов, но с акцентом на экологические процессы.

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

Однако до недавнего времени такие фундаментальные экологические концепции, как хабитаты (среды обитания), экологические взаимоотношения и экологическая сукцессия, оставались практически неисследованными в контексте оптимизации. Алгоритм Eco-inspired Evolutionary Algorithm, предложенный Rafael Stubs Parpinelli и Heitor Silvério Lopes в 2011 году, заполняет этот пробел, предлагая принципиально новый взгляд на построение кооперативных алгоритмов поиска.


Реализация алгоритма

В основе ECO лежит экологическая метафора, в которой множество популяций кандидатных решений сосуществуют, взаимодействуют и коэволюционируют друг с другом:

Экологический концепт
Вычислительная интерпретация
Хабитат
Кластер популяций, расположенных в одной области пространства поиска
ПопуляцияГруппа кандидатных решений, эволюционирующих по единой стратегии
Центроид
Точка концентрации особей популяции, определяющая её "регион обитания"
Intra-habitat отношенияСпаривание между особями популяций внутри одного хабитата
Inter-habitat отношенияМиграция лучших особей между хабитатами
Экологическая сукцессияИтеративный процесс формирования хабитатов и установления связей

Множественные популяции. В отличие от классических эволюционных алгоритмов с единственной популяцией, ECO оперирует несколькими независимыми популяциями, каждая из которых эволюционирует согласно собственной стратегии поиска. Это обеспечивает естественное разделение между интенсификацией (exploiation) и диверсификацией (exploration).

Динамическое формирование хабитатов. На каждой итерации алгоритм вычисляет центроиды популяций и группирует близкие популяции в хабитаты на основе порогового расстояния "ρ". Это позволяет системе самоорганизовываться и адаптироваться к ландшафту целевой функции.

Двухуровневое взаимодействие. "Intra-habitat" взаимодействия (спаривание) усиливают локальный поиск в перспективных регионах, в то время как "inter-habitat" взаимодействия (миграции) обеспечивают обмен генетическим материалом между удалёнными областями пространства поиска.

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

Структура алгоритма. Основной цикл ECO (экологическая сукцессия) состоит из следующих этапов:

1. Инициализация популяций в случайных регионах пространства поиска

2. ПОКА не выполнен критерий останова:

   2.1. Эволюционный период — каждая популяция независимо эволюционирует.

   2.2. Вычисление центроидов популяций.

   2.3. Формирование хабитатов на основе близости центроидов.

   2.4. Intra-habitat взаимодействия - спаривание между смежными популяциями.

   2.5. Inter-habitat взаимодействия - миграция лучших особей между хабитатами.

3. Возврат лучшего найденного решения.

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

Особь — одно кандидатное решение задачи. Например, если мы оптимизируем два параметра торговой стратегии (период скользящей средней и уровень стоп-лосса), то особь — это конкретная пара значений (20, 50).

Популяция — группа особей, живущих рядом и эволюционирующих вместе. Популяция характеризуется своим центром — средним положением всех особей.

Хабитат — объединение близких популяций. Если центры двух популяций находятся недалеко друг от друга, они образуют общий хабитат и начинают обмениваться особями.

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

Высота

  ▲

  │    ∧              ∧∧

  │   ╱ ╲    ∧∧      ╱  ╲

  │  ╱   ╲  ╱  ╲    ╱    ╲

  │ ╱     ╲╱    ╲  ╱      ╲

  │╱              ╲╱        ╲

  └──────────────────────────────► Позиция

      G1    G2      G3   G4  G5      

G1-G5 — стартовые позиции групп

  • Шаг 1: Локальный поиск. Каждая группа исследует свою окрестность, поднимаясь выше.
  • Шаг 2: Определение хабитатов. Группы G1 и G2 оказались близко — они образуют хабитат. Группы G4 и G5 тоже рядом — другой хабитат. Группа G3 пока одна.
  • Шаг 3: Обмен внутри хабитата. G1 и G2 делятся информацией о найденных маршрутах. Лучший альпинист из G1 показывает путь участнику из G2.
  • Шаг 4: Миграция между хабитатами. Лучший альпинист из Хабитата1 отправляется в Хабитат2, принося знания о перспективных направлениях.

Результат: через несколько итераций все группы концентрируются вокруг главной вершины.

Структура алгоритма. Алгоритм работает циклически, повторяя пять основных шагов:

Шаг 1: Эволюция популяций. Каждая особь пытается улучшить свою позицию двумя способами:

  • случайное исследование — смещение относительно случайного соседа,
  • притяжение к лидеру — движение к лучшей особи популяции.

Пример для особи с позицией (3, 4): сосед находится в (5, 2), а лидер находится в (7, 8). Случайное смещение: (3,4) - (5,2) = (-2, 2), умножаем на случайный коэффициент. Притяжение к лидеру: (7,8) - (3,4) = (4, 4), умножаем на малый коэффициент. Новая позиция = текущая + смещение + притяжение

Лучшая особь популяции не изменяется — это гарантирует сохранение достигнутого результата.

Шаг 2: Вычисление центроидов. Центроид — это "центр масс" популяции, среднее положение всех особей. Популяция из 4 особей:

     5 ┤    ●(2,5)

     4 ┤  ●(1,4)         

     3 ┤      ◉(2,3) ← центроид

     2 ┤        ●(3,2)

     1 ┤●(1,1)

       └─────────────

       0 1 2 3 4 5

Центроид = ((1+2+3+1)/4, (1+5+2+4)/4) = (1.75, 3.0) ≈ (2, 3). Центроид показывает, где "живёт" популяция в пространстве поиска.

Шаг 3: Формирование хабитатов. Популяции, чьи центроиды находятся близко друг к другу, объединяются в хабитат. "Близость" определяется порогом "ρ": 5 популяций с центроидами:

Расстояния: P0-P1 = 1.5 (близко); P0-P2 = 3.0 (далеко); P3-P4 = 4.0 (далеко). При пороге "ρ", дающем расстояние 2.0: Хабитат A: {P0, P1} - близкие популяции, Хабитат B: {P2} - одиночная, Хабитат C: {P3} - одиночная, Хабитат D: {P4} - одиночная.

Шаг 4: Спаривание внутри хабитатов. Популяции одного хабитата обмениваются генетическим материалом: Хабитат A содержит популяции P0 и P1.

1. Из P0 выбираем сильную особь (турнирный отбор). Берём 3 случайных особи, выбираем лучшую → Родитель 1: (4, 6).

2. Из P1 аналогично выбираем: → Родитель 2: (8, 2).

3. Создаём потомка (кроссовер): x: между 4 и 8 → случайно выбираем 5.5; y: между 2 и 6 → случайно выбираем 4.0 → Потомок: (5.5, 4.0). Это для равномерного кроссовера, но в нашей реализации будет использоваться uniform crossover (для каждой координаты случайно выбирается один из родителей), а не арифметическое среднее. Потомок (5.5, 4.0) возможен только если для "x" взяли среднее.

4. Потомок заменяет слабую особь в P1. Это усиливает поиск в перспективных регионах.

Шаг 5: Миграция между хабитатами. Лучшие особи путешествуют между хабитатами, распространяя хорошие решения:

Хабитат A                      Хабитат B

┌─────────────┐                ┌─────────────┐

│ P0: лучшая  │                │ P2          │

│     (3, 7)  │ ─────────────► │     ?       │

│     ★       │    миграция    │     ★       │

└─────────────┘                └─────────────┘

Лучшая особь из P0 копируется в P2, заменяя случайную (не лучшую) особь. Миграция предотвращает изоляцию хабитатов и ускоряет распространение найденных решений.

Динамика системы. В начале работы популяции разбросаны по всему пространству поиска - много изолированных хабитатов. По мере оптимизации популяции сходятся к лучшим регионам - хабитаты укрупняются:

Итерация 1: 6 хабитатов (исследование); Итерация 25: 3 хабитата (переход); Итерация 50: 1 хабитат (эксплуатация). Это иллюстративный пример, в реальности зависит от функции и параметра "ρ".

ECO

Рисунок 1. Иллюстрация работы алгоритма ECO

Иллюстрация показывает: левая часть — Search Space: 3 хабитата (H₀, H₁, H₂) как цветные области, 6 субпопуляций (Sp₀-Sp₅) с агентами (фиолетовые точки). Лучшие особи выделены красным цветом. Пунктирные линии — смежность между популяциями (dist ≤ ρ). Зелёные стрелки — спаривание внутри хабитата. Красные стрелки — миграции между хабитатами. Правая часть — Algorithm Flow: 6 шагов алгоритма с формулами.

Напишем реализацию алгоритма ECO.

Структура "S_ECO_Coord". Вспомогательная структура для хранения одной координаты центроида. Массив "centroids" хранит центроиды всех субпопуляций в плоском виде размером [numPops × coords], где каждый элемент — одна координата одного центроида.

//————————————————————————————————————————————————————————————————————
struct S_ECO_Coord
{
    double v;
};
//————————————————————————————————————————————————————————————————————

Класс "C_AO_ECOi", основной класс алгоритма, который наследуется от базового класса "C_AO". Этот класс реализует эволюционный алгоритм, вдохновленный экологическими взаимодействиями. Алгоритм разбивает популяцию на подпопуляции, которые имитируют отдельные экосистемы. Эти подпопуляции взаимодействуют друг с другом как на локальном, так и на глобальном уровне, что способствует поиску оптимального решения.

Метод "SetParams" обновляет внутренние параметры алгоритма ECOi на основе значений, хранящихся в массиве "params". Этот метод обычно вызывается после изменений параметров извне.

//————————————————————————————————————————————————————————————————————
class C_AO_ECOi : public C_AO
{
  public:
  ~C_AO_ECOi () { }

  C_AO_ECOi ()
  {
    ao_name = "ECOi";
    ao_desc = "Eco-inspired Evolutionary Algorithm";
    ao_link = "https://www.mql5.com/ru/articles/20608";

    popSize   = 100;   // Total population size
    numPops   = 50;    // Number of sub-populations (N-POP)
    evoStep   = 1;     // Evolutive period iterations (EVO-STEP)
    rho       = 0.3;   // Proximity threshold for habitat formation
    tournSize = 8;     // Tournament selection size (T-SIZE)

    ArrayResize (params, 5);
    params [0].name = "popSize";   params [0].val = popSize;
    params [1].name = "numPops";   params [1].val = numPops;
    params [2].name = "evoStep";   params [2].val = evoStep;
    params [3].name = "rho";       params [3].val = rho;
    params [4].name = "tournSize"; params [4].val = tournSize;
  }

  void SetParams ()
  {
    popSize   = (int)params [0].val;
    numPops   = (int)params [1].val;
    evoStep   = (int)params [2].val;
    rho       = params [3].val;
    tournSize = (int)params [4].val;
  }

  bool Init (const double &rangeMinP  [],
             const double &rangeMaxP  [],
             const double &rangeStepP [],
             const int     epochsP);

  void Moving   ();
  void Revision ();

  //------------------------------------------------------------------
  int    numPops;       // Number of sub-populations
  int    evoStep;       // Evolutive period
  double rho;           // Proximity threshold
  int    tournSize;     // Tournament size

  private: //—————————————————————————————————————————————————————————
  int         evoCounter;      // Counter for evolutive period
  int         subPopSize;      // Size of each sub-population

  S_ECO_Coord centroids [];    // [numPops * coords] - flattened centroid array
  int         habitat   [];    // Habitat index for each sub-population
  int         numHabitats;
  bool        adjacency [];    // Adjacency matrix [numPops * numPops] - flattened
  int         uniqueHab [];    // Array of unique habitat indices
  double      maxDist;         // Maximum possible distance (for normalization)

  void   CalculateCentroids    ();
  void   BuildAdjacencyMatrix  ();
  void   FormHabitats          ();
  void   IntraHabitatMating    ();
  void   InterHabitatMigration ();
  void   EvolutivePeriod       ();
  int    TournamentSelect      (int popIdx);
  void   Crossover             (int parent1, int parent2, int childIdx);
  double EuclideanDistanceNorm (int pop1, int pop2);
  int    GetBestInPopulation   (int popIdx);
  int    GetRandomInPopulation (int popIdx, int excludeIdx);
  void   BoundaryControl       (int idx);
  int    GetPopStart           (int popIdx);
  int    GetPopEnd             (int popIdx);
};
//————————————————————————————————————————————————————————————————————

Метод "Init" — инициализация алгоритма перед запуском оптимизации. Метод вызывает "StandardInit" базового класса для инициализации общих структур. Сбрасывается счётчик эволюционного периода, корректируется "numPops", если оно превышает "popSize" или меньше 1. Вычисляется subPopSize = popSize / numPops. Выделяется память под массивы: centroids, habitat, adjacency, uniqueHab. Вычисляется "maxDist" — длина диагонали пространства поиска для нормализации расстояний. Инициализируются хабитаты: каждая субпопуляция изначально образует свой хабитат.

//————————————————————————————————————————————————————————————————————
bool C_AO_ECOi::Init (const double &rangeMinP  [],
                      const double &rangeMaxP  [],
                      const double &rangeStepP [],
                      const int     epochsP)
{
  if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;

  //------------------------------------------------------------------
  evoCounter = 0;

  // Ensure numPops doesn't exceed popSize
  if (numPops > popSize) numPops = popSize;
  if (numPops < 1) numPops = 1;

  subPopSize = popSize / numPops;
  if (subPopSize < 1) subPopSize = 1;

  // Allocate arrays
  ArrayResize (centroids, numPops * coords);
  ArrayResize (habitat,   numPops);
  ArrayResize (adjacency, numPops * numPops);
  ArrayResize (uniqueHab, numPops);

  // Calculate maximum distance for normalization
  maxDist = 0.0;
  for (int c = 0; c < coords; c++)
  {
    double width = rangeMax [c] - rangeMin [c];
    maxDist += width * width;
  }
  maxDist = MathSqrt (maxDist);
  if (maxDist < 1e-10) maxDist = 1.0;

  // Initialize habitats - each population is its own habitat
  for (int p = 0; p < numPops; p++)
  {
    habitat [p] = p;
  }
  numHabitats = numPops;

  return true;
}
//————————————————————————————————————————————————————————————————————

Метод "Moving". Назначение: основной метод, выполняющий один шаг алгоритма. Вызывается на каждой итерации и управляет процессом поиска. Первая итерация (отсутствие ревизии). Метод инициализирует всю популяцию случайными значениями, распределенными по нормальному закону вокруг случайных центров в пределах заданных диапазонов.

Последующие итерации: инкрементирует счетчик эволюционных итераций (evoCounter). Вызывает метод "EvolutivePeriod" для проведения локального поиска внутри каждой субпопуляции. После завершения эволюционного периода (достижение evoStep): вызывается "CalculateCentroids" для определения центров каждой субпопуляции, "BuildAdjacencyMatrix" — для построения матрицы смежности на основе расстояний между центроидами, "FormHabitats" — для формирования экологических местообитаний на основе матрицы смежности, "IntraHabitatMating" — для проведения обмена генетической информацией (скрещивания) между соседними популяциями в пределах одного местообитания, и "InterHabitatMigration" — для выполнения "великих миграций" (переноса лучших особей между разными местообитаниями).

Сбрасывается счетчик эволюционных итераций (evoCounter) в ноль.

//————————————————————————————————————————————————————————————————————
void C_AO_ECOi::Moving ()
{
  //------------------------------------------------------------------
  // First iteration: random initialization of all populations
  if (!revision)
  {
    for (int i = 0; i < popSize; i++)
    {
      for (int c = 0; c < coords; c++)
      {
        // Initialize with normal distribution around random center (Box-Muller)
        double center = u.RNDfromCI (rangeMin [c], rangeMax [c]);
        a [i].c [c] = u.GaussDistribution (center, rangeMin [c], rangeMax [c], 2.0);
        a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }

    revision = true;
    return;
  }

  //------------------------------------------------------------------
  evoCounter++;

  //==================================================================
  // Evolutive Period: Simple evolution for each sub-population
  // Using ABC-inspired local search (employed bee phase)
  //==================================================================
  EvolutivePeriod ();

  //==================================================================
  // After evoStep iterations, perform ecological interactions
  //==================================================================
  if (evoCounter >= evoStep)
  {
    // Step 5: Calculate centroids for each population (Eq. 1)
    CalculateCentroids ();

    // Step 6: Build adjacency matrix and form habitats
    BuildAdjacencyMatrix ();
    FormHabitats ();

    // Step 7-8: Intra-habitat interactions (mating)
    IntraHabitatMating ();

    // Step 9-10: Inter-habitat interactions (great migrations)
    InterHabitatMigration ();

    evoCounter = 0;
  }
}
//————————————————————————————————————————————————————————————————————

Метод "EvolutivePeriod". Назначение: эволюционный период — локальный поиск внутри каждой субпопуляции. Реализует ABC-подобную стратегию (фаза employed bee). Метод перебирает каждую особь в общей популяции и случайным образом выбирает одну из координат для изменения, определяет, к какой субпопуляции принадлежит данная особь, выбирает другую случайную особь из той же субпопуляции. Генерирует новую позицию для текущей особи, используя формулу, схожую с ABC: x_new = x_i + phi * (x_i - x_k), где "phi" - случайный коэффициент. Применяет новую позицию к особи и выполняет контроль границ (BoundaryControl).

Примечание: жадная селекция (сравнение с предыдущим значением) не выполняется — фитнес пересчитывается внешним кодом после "Moving".

//————————————————————————————————————————————————————————————————————
void C_AO_ECOi::EvolutivePeriod ()
{
  // Simple evolution: Each individual explores neighborhood
  // Inspired by ABC employed bee phase
  for (int i = 0; i < popSize; i++)
  {
    // Select a random dimension to modify
    int dim = u.RNDminusOne (coords);

    // Determine which sub-population this individual belongs to
    int popIdx = i / subPopSize;
    if (popIdx >= numPops) popIdx = numPops - 1;

    // Select a random different individual from same sub-population
    int otherIdx = GetRandomInPopulation (popIdx, i);

    // Generate new position using ABC-style equation:
    // x_new = x_i + phi * (x_i - x_k)
    double phi    = u.RNDfromCI (-1.0, 1.0);
    double newVal = a [i].c [dim] + phi * (a [i].c [dim] - a [otherIdx].c [dim]);

    // Apply new value
    a [i].c [dim] = newVal;
    BoundaryControl (i);
  }
}
//————————————————————————————————————————————————————————————————————

Метод "CalculateCentroids". Назначение: вычисление центроидов (геометрических центров) для каждой субпопуляции. Формула (Equation 1 из статьи): C = Σxi / Pop. Логика работы для каждой субпопуляции: инициализируются координаты центроида нулями, суммируются координаты всех особей в данной субпопуляции, затем делится полученная сумма на количество особей в субпопуляции, чтобы получить среднее значение (центроид).

Результат: заполненный массив "centroids".

//————————————————————————————————————————————————————————————————————
void C_AO_ECOi::CalculateCentroids ()
{
  // Calculate centroid for each sub-population
  // C = sum(xi) / Pop  (Equation 1 from paper)

  for (int p = 0; p < numPops; p++)
  {
    int startIdx = GetPopStart (p);
    int endIdx   = GetPopEnd (p);
    int count    = endIdx - startIdx;
    if (count < 1) count = 1;

    // Initialize centroid to zero
    for (int c = 0; c < coords; c++)
    {
      centroids [p * coords + c].v = 0.0;
    }

    // Sum all positions
    for (int i = startIdx; i < endIdx; i++)
    {
      for (int c = 0; c < coords; c++)
      {
        centroids [p * coords + c].v += a [i].c [c];
      }
    }

    // Divide by population count
    for (int c = 0; c < coords; c++)
    {
      centroids [p * coords + c].v /= count;
    }
  }
}
//————————————————————————————————————————————————————————————————————

Метод "BuildAdjacencyMatrix". Осуществляется построение матрицы смежности субпопуляций на основе расстояния между их центроидами. Критерий смежности: две субпопуляции смежны, если нормализованное евклидово расстояние между их центроидами ≤ ρ (rho).

Логика работы метода для каждой пары субпопуляций: вычисляется нормализованное евклидово расстояние между их центроидами, используя метод "EuclideanDistanceNorm", если расстояние меньше или равно заданному порогу "rho", устанавливается соответствующий элемент матрицы смежности в "true" (что означает, что они соседние), иначе в "false". Результат: заполненная матрица "adjacency".

//————————————————————————————————————————————————————————————————————
void C_AO_ECOi::BuildAdjacencyMatrix ()
{
  // Build adjacency matrix based on normalized Euclidean distance
  // Two populations are adjacent if distance <= rho

  for (int i = 0; i < numPops; i++)
  {
    for (int j = 0; j < numPops; j++)
    {
      if (i == j)
      {
        adjacency [i * numPops + j] = false;
      }
      else
      {
        double dist = EuclideanDistanceNorm (i, j);
        adjacency [i * numPops + j] = (dist <= rho);
      }
    }
  }
}
//————————————————————————————————————————————————————————————————————

Метод "EuclideanDistanceNorm" — вычисление нормализованного евклидова расстояния между центроидами двух субпопуляций. Параметры: pop1, pop2 — индексы субпопуляций. Метод возвращает расстояние в диапазоне [0, 1], где 1 — максимально возможное расстояние (диагональ пространства).

Формула: dist = sqrt(Σ(c1[i] - c2[i])²) / maxDist. Делится полученное расстояние на максимальное возможное расстояние (maxDist) для нормализации.

//————————————————————————————————————————————————————————————————————
double C_AO_ECOi::EuclideanDistanceNorm (int pop1, int pop2)
{
  // Calculate normalized Euclidean distance between two population centroids
  double dist = 0.0;

  for (int c = 0; c < coords; c++)
  {
    double diff = centroids [pop1 * coords + c].v - centroids [pop2 * coords + c].v;
    dist += diff * diff;
  }

  dist = MathSqrt (dist);

  // Normalize by maximum possible distance
  return dist / maxDist;
}
//————————————————————————————————————————————————————————————————————

Метод "FormHabitats". Формирование хабитатов — групп смежных субпопуляций. Алгоритм: Union-Find (объединение множеств) на основе матрицы смежности.

Изначально каждая субпопуляция считается отдельным местообитанием. Используя матрицу смежности, субпопуляции, которые являются соседними (находятся друг к другу в пределах rho), объединяются в одно местообитание. Это делается путем последовательного слияния местообитаний. После формирования всех местообитаний, собирается список уникальных индексов местообитаний (uniqueHab) и подсчитывается их общее количество (numHabitats).

Результат: habitat — индекс хабитата для каждой субпопуляции, uniqueHab — список уникальных индексов хабитатов и numHabitats   — количество хабитатов.

//————————————————————————————————————————————————————————————————————
void C_AO_ECOi::FormHabitats ()
{
  // Form habitats using union-find approach on adjacency matrix
  // Initially each population is its own habitat

  for (int p = 0; p < numPops; p++)
  {
    habitat [p] = p;
  }

  // Merge adjacent populations into same habitat
  for (int i = 0; i < numPops; i++)
  {
    for (int j = i + 1; j < numPops; j++)
    {
      if (adjacency [i * numPops + j])
      {
        // Merge habitats: all populations in j's habitat join i's habitat
        int oldHab = habitat [j];
        int newHab = habitat [i];

        if (oldHab != newHab)
        {
          for (int p = 0; p < numPops; p++)
          {
            if (habitat [p] == oldHab)
            {
              habitat [p] = newHab;
            }
          }
        }
      }
    }
  }

  // Collect unique habitat indices
  numHabitats = 0;
  for (int p = 0; p < numPops; p++)
  {
    int h = habitat [p];
    bool found = false;

    for (int k = 0; k < numHabitats; k++)
    {
      if (uniqueHab [k] == h)
      {
        found = true;
        break;
      }
    }

    if (!found)
    {
      uniqueHab [numHabitats] = h;
      numHabitats++;
    }
  }
}
//————————————————————————————————————————————————————————————————————

Метод "IntraHabitatMating". Внутрихабитатное спаривание — обмен генетическим материалом между смежными субпопуляциями одного хабитата. Экологическая аналогия: репродуктивные связи между популяциями в пределах одного местообитания. Перебираются все пары субпопуляций. Если две субпопуляции находятся в одном местообитании и являются соседними (согласно матрице смежности), тогда с использованием турнирного отбора (TournamentSelect) выбираются два родителя из этих двух субпопуляций. Выбирается случайная особь в одной из субпопуляций (исключая лучшую особь), которая будет заменена потомком. Выполняется скрещивание (Crossover) двух родителей для создания потомка. Потомок заменяет выбранную особь в целевой субпопуляции.

//————————————————————————————————————————————————————————————————————
void C_AO_ECOi::IntraHabitatMating ()
{
  // Mating between adjacent populations within the same habitat
  // For each pair of adjacent populations: tournament select parents, crossover, replace random individual

  for (int p = 0; p < numPops; p++)
  {
    for (int q = p + 1; q < numPops; q++)
    {
      // Check if in same habitat and adjacent
      if (habitat [p] == habitat [q] && adjacency [p * numPops + q])
      {
        // Tournament selection from population p
        int parent1 = TournamentSelect (p);

        // Tournament selection from population q
        int parent2 = TournamentSelect (q);

        // Select a random individual (not the best) from population q to replace
        int bestQ    = GetBestInPopulation (q);
        int childIdx = GetRandomInPopulation (q, bestQ);

        // Perform crossover - child replaces selected individual
        Crossover (parent1, parent2, childIdx);
      }
    }
  }
}
//————————————————————————————————————————————————————————————————————

Метод "InterHabitatMigration". Назначение: межхабитатная миграция — перенос лучших решений между хабитатами. Экологическая аналогия: "Великие миграции" — лучшие особи мигрируют в другие местообитания. Для каждого местообитания выбирается случайная субпопуляция из данного местообитания, находится лучшая особь в этой субпопуляции (GetBestInPopulation), выбирается случайное другое местообитание (отличное от исходного), далее выбирается случайная субпопуляция в целевом местообитании. Выбирается случайная особь в целевой субпопуляции (исключая лучшую) для замены. Лучшая особь из исходной субпопуляции копируется на место выбранной, для замены особи в целевой субпопуляции.

Примечание: фитнес мигрировавшего агента будет пересчитан внешним кодом.

//————————————————————————————————————————————————————————————————————
void C_AO_ECOi::InterHabitatMigration ()
{
  // Great migrations: best individual from one habitat migrates to another
  // For each habitat, select random population, migrate best to another habitat

  if (numHabitats < 2) return;

  // For each habitat, perform migration
  for (int hIdx = 0; hIdx < numHabitats; hIdx++)
  {
    int srcHab = uniqueHab [hIdx];

    // Find populations in this habitat
    int popsInHab [];
    ArrayResize (popsInHab, 0);

    for (int p = 0; p < numPops; p++)
    {
      if (habitat [p] == srcHab)
      {
        int size = ArraySize (popsInHab);
        ArrayResize (popsInHab, size + 1);
        popsInHab [size] = p;
      }
    }

    if (ArraySize (popsInHab) == 0) continue;

    // Select random population from this habitat
    int srcPopIdx = popsInHab [u.RNDminusOne (ArraySize (popsInHab))];

    // Get best individual from this population
    int bestIdx = GetBestInPopulation (srcPopIdx);

    // Select random destination habitat (different from source)
    int destHabIdx = u.RNDminusOne (numHabitats);
    int attempts = 0;
    while (uniqueHab [destHabIdx] == srcHab && attempts < numHabitats)
    {
      destHabIdx = (destHabIdx + 1) % numHabitats;
      attempts++;
    }

    if (uniqueHab [destHabIdx] == srcHab) continue; // No other habitat available

    int destHab = uniqueHab [destHabIdx];

    // Find populations in destination habitat
    int popsInDestHab [];
    ArrayResize (popsInDestHab, 0);

    for (int p = 0; p < numPops; p++)
    {
      if (habitat [p] == destHab)
      {
        int size = ArraySize (popsInDestHab);
        ArrayResize (popsInDestHab, size + 1);
        popsInDestHab [size] = p;
      }
    }

    if (ArraySize (popsInDestHab) == 0) continue;

    // Select random population in destination habitat
    int destPopIdx = popsInDestHab [u.RNDminusOne (ArraySize (popsInDestHab))];

    // Select random individual (not the best) in destination population to replace
    int bestDest  = GetBestInPopulation (destPopIdx);
    int targetIdx = GetRandomInPopulation (destPopIdx, bestDest);

    // Copy best individual to target position (migration)
    for (int c = 0; c < coords; c++)
    {
      a [targetIdx].c [c] = a [bestIdx].c [c];
    }
    // Note: fitness will be recalculated externally after Moving()
  }
}
//————————————————————————————————————————————————————————————————————

Метод "TournamentSelect". Турнирная селекция — выбор агента с лучшим фитнесом среди случайной выборки.
Параметр: "popIdx" — индекс субпопуляции. Метод выполняет турнирный отбор внутри одной субпопуляции. Случайным образом выбирает "tournSize" особей из указанной субпопуляции. Возвращается индекс особи с наилучшей приспособленностью (наибольшим значением "f") среди выбранных.

//————————————————————————————————————————————————————————————————————
int C_AO_ECOi::TournamentSelect (int popIdx)
{
  // Tournament selection within a sub-population
  int startIdx = GetPopStart (popIdx);
  int endIdx   = GetPopEnd   (popIdx);
  int popCount = endIdx - startIdx;

  if (popCount <= 0) return startIdx;

  int    bestIdx = startIdx + u.RNDminusOne (popCount);
  double bestFit = a [bestIdx].f;

  for (int t = 1; t < tournSize && t < popCount; t++)
  {
    int idx = startIdx + u.RNDminusOne (popCount);
    if (a [idx].f > bestFit)
    {
      bestFit = a [idx].f;
      bestIdx = idx;
    }
  }

  return bestIdx;
}
//————————————————————————————————————————————————————————————————————

Метод "Crossover". Назначение: равномерный (uniform) кроссовер двух родителей. Метод реализует равномерное скрещивание между двумя родителями для создания потомка. Для каждой координаты потомка с вероятностью 0.5 выбирается соответствующая координата от первого родителя. В противном случае выбирается координата от второго родителя. После создания потомка выполняется контроль границ (BoundaryControl).

//————————————————————————————————————————————————————————————————————
void C_AO_ECOi::Crossover (int parent1, int parent2, int childIdx)
{
  // Uniform crossover between two parents
  for (int c = 0; c < coords; c++)
  {
    if (u.RNDbool ())
    {
      a [childIdx].c [c] = a [parent1].c [c];
    }
    else
    {
      a [childIdx].c [c] = a [parent2].c [c];
    }
  }

  BoundaryControl (childIdx);
}
//————————————————————————————————————————————————————————————————————

Метод "GetBestInPopulation". Описание: находит и возвращает индекс лучшей особи в указанной субпопуляции. Перебирает всех особей в заданной субпопуляции и находит ту, у которой значение приспособленности (f) наибольшее.

//————————————————————————————————————————————————————————————————————
int C_AO_ECOi::GetBestInPopulation (int popIdx)
{
  int startIdx = GetPopStart (popIdx);
  int endIdx   = GetPopEnd (popIdx);

  int    bestIdx = startIdx;
  double bestFit = a [startIdx].f;

  for (int i = startIdx + 1; i < endIdx; i++)
  {
    if (a [i].f > bestFit)
    {
      bestFit = a [i].f;
      bestIdx = i;
    }
  }

  return bestIdx;
}
//————————————————————————————————————————————————————————————————————

Метод "GetRandomInPopulation". Назначение: выбор случайного агента из субпопуляции, исключая указанный индекс. Параметры: popIdx —индекс субпопуляции, excludeIdx — индекс агента, который нужно исключить. Метод возвращает индекс случайной особи из указанной субпопуляции, с возможностью исключить определенную особь.

Выбирает случайную особь из субпопуляции, если выбранная особь совпадает с исключаемой (excludeIdx), происходит повторный выбор (с ограничением попыток), чтобы избежать возвращения исключенной особи.

//————————————————————————————————————————————————————————————————————
int C_AO_ECOi::GetRandomInPopulation (int popIdx, int excludeIdx)
{
  int startIdx = GetPopStart (popIdx);
  int endIdx   = GetPopEnd (popIdx);
  int popCount = endIdx - startIdx;

  if (popCount <= 1) return startIdx;

  int idx = startIdx + u.RNDminusOne (popCount);
  int attempts = 0;

  while (idx == excludeIdx && attempts < 10)
  {
    idx = startIdx + u.RNDminusOne (popCount);
    attempts++;
  }

  return idx;
}
//————————————————————————————————————————————————————————————————————

Метод "GetPopStart". Вычисление границ субпопуляции в общем массиве агентов. Возвращается индекс первого агента субпопуляции.

//————————————————————————————————————————————————————————————————————
int C_AO_ECOi::GetPopStart (int popIdx)
{
  int start = popIdx * subPopSize;
  if (start >= popSize) start = popSize - 1;
  return start;
}
//————————————————————————————————————————————————————————————————————

Метод "GetPopEnd". Возвращается индекс после последнего агента субпопуляции. Для последней субпопуляции end = popSize (получает "остаток" агентов).

//————————————————————————————————————————————————————————————————————
int C_AO_ECOi::GetPopEnd (int popIdx)
{
  int end = (popIdx + 1) * subPopSize;
  if (end > popSize) end = popSize;
  if (popIdx == numPops - 1) end = popSize; // Last population gets remaining
  return end;
}
//————————————————————————————————————————————————————————————————————

Метод "BoundaryControl". Назначение: контроль границ — возврат координат агента в допустимый диапазон. Для каждой координаты особи, если координата выходит за пределы допустимого диапазона (min, max), применяется механизм отражающих границ (отражение от границы), если отражение не помогло (координата все еще вне диапазона после нескольких попыток), устанавливается случайное значение в пределах допустимого диапазона.

Результат дополнительно обрабатывается методом "SeInDiSp", который корректирует значение с учетом шага (rangeStep).

//————————————————————————————————————————————————————————————————————
void C_AO_ECOi::BoundaryControl (int idx)
{
  for (int c = 0; c < coords; c++)
  {
    double val = a [idx].c [c];
    double min = rangeMin [c];
    double max = rangeMax [c];

    // Reflection boundary handling
    int iter = 0;
    while ((val < min || val > max) && iter < 10)
    {
      if (val < min) val = min + (min - val);
      if (val > max) val = max - (val - max);
      iter++;
    }

    // If reflection fails, use random position
    if (val < min || val > max)
    {
      val = u.RNDfromCI (min, max);
    }

    a [idx].c [c] = u.SeInDiSp (val, min, max, rangeStep [c]);
  }
}
//————————————————————————————————————————————————————————————————————

Метод "Revision" находит глобально лучшую особь среди всей популяции и обновляет лучшую найденную ранее (если текущая лучше). Перебирает всех особей в общей популяции. Сравнивает приспособленность текущей лучшей особи (fB) с приспособленностью найденной на данной итерации.

Если найдена новая лучшая особь, ее приспособленность и координаты сохраняются.

//————————————————————————————————————————————————————————————————————
void C_AO_ECOi::Revision ()
{
  // Find and update global best
  int    bestIdx = 0;
  double bestFit = a [0].f;

  for (int i = 1; i < popSize; i++)
  {
    if (a [i].f > bestFit)
    {
      bestFit = a [i].f;
      bestIdx = i;
    }
  }

  if (bestFit > fB)
  {
    fB = bestFit;
    ArrayCopy (cB, a [bestIdx].c, 0, 0, coords);
  }
}
//————————————————————————————————————————————————————————————————————


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

Алгоритм ECOi (Eco-inspired Evolutionary Algorithm) показал результат 48% на тестовом наборе функций. Это значение находится на границе попадания в таблицу лучших алгоритмов оптимизации — совсем немного не хватило для включения в рейтинг.

Алгоритм использует разнообразные механизмы: ABC-подобный локальный поиск, формирование хабитатов, внутрихабитатное спаривание с турнирной селекцией и кроссовером, межхабитатные миграции. Такое разнообразие обеспечивает баланс между эксплуатацией и исследованием.

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

Адаптивная структура популяции. Разбиение на субпопуляции с динамическим формированием хабитатов создаёт естественную нишевую структуру, потенциально полезную для мультимодальных задач.

ECOi|Eco-inspired Evolutionary Algorithm|100.0|50.0|1.0|0.3|8.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.8454991049506774
25 Hilly's; Func runs: 10000; result: 0.5348563688609891
500 Hilly's; Func runs: 10000; result: 0.29261342860799167
=============================
5 Forest's; Func runs: 10000; result: 0.8820344476464197
25 Forest's; Func runs: 10000; result: 0.46479689499361054
500 Forest's; Func runs: 10000; result: 0.19211609956835546
=============================
5 Megacity's; Func runs: 10000; result: 0.6553846153846152
25 Megacity's; Func runs: 10000; result: 0.348
500 Megacity's; Func runs: 10000; result: 0.12630769230769343
=============================
All score: 4.34161 (48.24%)

Визуализация работы алгоритма ECO на наших тестовых функциях и, как пример, на стандартных тестовых функциях, которые можно выбрать из предложенного списка функций в программе.

Hilly

ECOi на тестовой функции Hilly

Forest

ECOi на тестовой функции Forest

Megacity

ECOi на тестовой функции Megacity

Shaffer

ECOi на тестовой функции Shaffer 

GoldsteinPrice

ECOi на тестовой функции GoldsteinPrice

Алгоритма ECO представлен ознакомительно в рейтинговой таблице лучших популяционных методов оптимизации.

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)
dingo_optimization_algorithm_M0,479680,453670,463691,397040,941450,879090,914542,735080,786150,860610,848052,494816,62773,63
across neighbourhood search0,949480,847760,438572,235811,000000,923340,399882,323230,709230,634770,230911,574916,13468,15
code lock algorithm (joo)0,953450,871070,375902,200420,989420,917090,316422,222940,796920,693850,193031,683806,10767,86
animal migration ptimization M0,903580,843170,462842,209590,990010,924360,465982,380340,567690,591320,237731,396755,98766,52
(P+O) evolution strategies0,922560,881010,400212,203790,977500,874900,319452,171850,673850,629850,186341,490035,86665,17
comet tail algorithm (joo)0,953460,863190,277702,094350,997940,857400,339492,194840,887690,564310,105121,557125,84664,96
time evolution travel algorithm (joo)0,913620,823490,319902,057010,970960,895320,293242,159520,734620,685690,160211,580525,79764,41
stochastic diffusion search M0,930660,854450,394762,179880,999830,892440,196192,088460,723330,611000,106701,441035,70963,44
billiards optimization algorithm M0,957570,825990,252352,035901,000000,900360,305022,205380,735380,525230,095631,356255,59862,19
archery algorithm M0,917440,708760,421602,047800,925270,758020,353282,036570,673850,552000,237381,463235,54861,64
evolution of social groups (joo)0,999060,796540,350562,146161,000000,828630,131021,959650,823330,553000,047251,423585,52961,44
simulated isotropic annealing (joo)0,957840,842640,414652,215130,982390,795860,205071,983320,686670,493000,090531,270205,46960,76
extremal_optimization_M0,761660,772420,317471,851550,999990,767510,235272,002770,747690,539690,142491,429875,28458,71
biogeography based optimization0,949120,694560,350311,993990,938200,673650,256821,868670,746150,482770,173691,402615,26558,50
artificial cooperative search0,755470,747440,304071,806981,000000,888610,224132,112740,690770,481850,133221,305835,22658,06
dialectical algorithm0,861830,700330,337241,899400,981630,727720,287181,996530,703080,452920,163671,319675,21657,95
black hole algorithm M0,752360,766750,345831,864930,935930,801520,271772,009230,650770,516460,154721,321955,19657,73
anarchy society optimization0,848720,746460,314651,909830,961480,791500,238031,991010,570770,540620,166141,277525,17857,54
royal flush optimization (joo)0,833610,737420,346291,917330,894240,738240,240981,873460,631540,502920,164211,298675,08956,55
atomic orbital search M0,802320,704490,310211,817020,856600,694510,219961,771070,746150,528620,143581,418355,00655,63
turtle shell evolution algorithm (joo)0,967980,644800,296721,909490,994490,619810,227081,841390,690770,426460,135981,253225,00455,60
backtracking_search_algorithm0,973090,545340,290981,809410,999990,585430,217471,802890,847690,369530,129781,347004,95955,10
differential evolution0,950440,616740,303081,870260,953170,788960,166521,908650,786670,360330,029531,176534,95555,06
successful restaurateur algorithm (joo)0,968830,634550,292171,895550,946370,555060,191241,692670,749230,440310,125261,314804,90354,48
bonobo_optimizer0,775650,638050,329081,742780,880880,763440,255731,900050,610770,498460,142461,251694,89554,38
chemical reaction optimisation0,946290,661120,298531,905930,879060,584220,211461,674730,758460,426460,126861,311784,89254,36
blood inheritance optimization (joo)0,815680,653360,308771,777810,899370,653190,217601,770160,678460,476310,139021,293784,84253,80
dream_optimization_algorithm0,855560,700850,372801,929210,734210,489050,241471,464730,772310,473540,185611,431464,82553,62
bird swarm algorithm0,893060,649000,262501,804550,924200,711210,249391,884790,693850,326150,100121,120124,80953,44
dolphin_echolocation_algorithm0,759950,675720,341711,777380,895820,642230,239411,777460,615380,440310,151151,206844,76252,91
harmony search0,865090,687820,325271,878180,999990,680020,095901,775920,620000,422670,054581,097254,75152,79
saplings sowing and growing0,778390,649250,395431,823080,859730,624670,174291,658690,646670,441330,105981,193984,67651,95
bacterial chemotaxis optimization M0,759530,622680,314831,697040,893780,613390,225421,732590,653850,420920,144351,219124,64951,65
african buffalo optimization0,833370,622470,299641,755480,921700,586180,197231,705110,610000,431540,132251,173784,63451,49
(PO) evolution strategies0,790250,626470,429351,846060,876160,609430,195911,681510,590000,379330,113221,082554,61051,22
fractal-based Algorithm0,790000,651340,289651,730990,871580,568230,188771,628580,610770,460620,123981,195374,55550,61
tabu search M0,877950,614310,291041,783300,928850,518440,190541,637830,610770,382150,121571,114494,53650,40
brain storm optimization0,937360,576160,296881,810410,931310,558660,235371,725340,552310,290770,119140,962224,49849,98
wale optimization algorithm M0,845210,562980,262631,670810,931000,522780,163651,617430,663080,411380,113571,188034,47649,74
artificial electric field algorithm0,877000,617530,252351,746880,927290,726980,180641,834900,666150,116310,095080,877544,45949,55
artificial ecosystem-based optimization algorithm0,913800,467130,264701,645630,902230,437050,214001,553270,661540,308000,285631,255174,45449,49
camel algorithm M0,786840,560420,351331,698590,827720,560410,243361,631490,648460,330920,134181,113564,44449,37
ant colony optimization M0,881900,661270,303771,846930,858730,586800,150511,596040,596670,373330,024720,994724,43849,31
covariance_matrix_adaptation_evolution_strategy0,762580,720890,000001,483470,820560,796160,000001,616720,758460,490770,000001,249234,34948,33
duelist_algorithm0,927820,537780,277921,743520,869570,475360,181931,526860,621530,335690,117151,074374,34548,28
eco-inspired_evolutionary_algorithm 0,845490,534850,292611,672950,882030,464790,192111,538930,655380,348000,126301,129684,34248,24
random walk0,487540,321590,257811,066940,375540,219440,158770,753750,279690,149170,098470,527342,34826,09


Выводы

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

Слабый локальный поиск. ABC-подобная формула x_new = x + φ·(x - x_other) модифицирует только одно измерение за итерацию. Для функций с сильными межпараметрическими зависимостями это может быть недостаточно эффективно.

Потеря хороших решений. При кроссовере и миграции потомок заменяет случайного агента (не худшего), что может приводить к потере неплохих решений. Отсутствие жадной селекции в эволюционном периоде также может замедлять сходимость.

Чувствительность к параметрам. Порог близости "ρ" критически влияет на формирование хабитатов. При неоптимальном значении либо все популяции объединяются в один хабитат (теряется разнообразие), либо остаются изолированными (теряется обмен информацией).

Редкие экологические взаимодействия. Спаривание и миграции происходят только каждые evoStep итераций. Если этот период слишком длинный, полезная информация распространяется медленно; если слишком короткий — популяции не успевают локально сойтись.

Алгоритм ECO демонстрирует интересный подход к оптимизации, вдохновлённый экологическими концепциями. Результат 48% — вполне приемлемый, особенно учитывая оригинальность идеи. Однако сложность архитектуры с множеством операторов не трансформировалась в пропорционально высокую эффективность. Возможно, некоторое упрощение алгоритма (меньше операторов, но более агрессивных) или усиление локального поиска могли бы улучшить результаты. Также стоит отметить, что экологическая метафора лучше подходит для задач с явной мультимодальной структурой, где концепция хабитатов может проявить свои преимущества в полной мере.

tab

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

chart

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

Плюсы и минусы алгоритма ECO:

Плюсы:

  1. Хорошая сходимость на функциях высокой и средней размерности (не самые худшие результаты в таблице).

Минусы:

  1. На задачах малой размерности низкая сходимость.
  2. Много внешних параметров.
  3. Много различных операторов модификации решений, что усложняет отладку и настройку алгоритма.

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


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

#ИмяТипОписание
1#C_AO.mqh
Включаемый файл
Родительский класс популяционных алгоритмов
оптимизации
2#C_AO_enum.mqh
Включаемый файл
Перечисление популяционных алгоритмов оптимизации
3TestFunctions.mqh
Включаемый файл
Библиотека тестовых функций
4
TestStandFunctions.mqh
Включаемый файл
Библиотека функций тестового стенда
5
Utilities.mqh
Включаемый файл
Библиотека вспомогательных функций
6
CalculationTestResults.mqh
Включаемый файл
Скрипт для расчета результатов в сравнительную таблицу
7
Testing AOs.mq5
СкриптЕдиный испытательный стенд для всех популяционных алгоритмов оптимизации
8
Simple use of population optimization algorithms.mq5
Скрипт
Простой пример использования популяционных алгоритмов оптимизации без визуализации
9
Test_AO_ECOi.mq5
СкриптИспытательный стенд для EGOi
Прикрепленные файлы |
ECOi.zip (399.28 KB)
Нейросети в трейдинге: Возмущённые модели пространства состояний для анализа рыночной динамики (Окончание) Нейросети в трейдинге: Возмущённые модели пространства состояний для анализа рыночной динамики (Окончание)
В статье представлена адаптация фреймворка P-SSE для задач анализа финансовых рынков. Реализованные решения обеспечивают последовательную обработку локальных событий, аккумулируя их в согласованное представление рыночной динамики. Подход позволяет прогнозировать изменения рынка на заданный горизонт планирования, сохраняя высокую чувствительность к микроимпульсам и минимизируя вычислительные затраты.
Возможности Мастера MQL5, которые вам нужно знать (Часть 58): Обучение с подкреплением (DDPG) совместно с паттернами скользящей средней и стохастика Возможности Мастера MQL5, которые вам нужно знать (Часть 58): Обучение с подкреплением (DDPG) совместно с паттернами скользящей средней и стохастика
Скользящая средняя и стохастический осциллятор — очень распространенные индикаторы, совместные паттерны которых мы исследовали в предыдущей статье с помощью сети обучения с учителем, чтобы понять, какие из них работают. В этой статье мы сделаем следующий шаг, рассмотрев влияние обучения с подкреплением, используемого с обученной нейронной сетью, на производительность. Наши испытания проводились в течение очень ограниченного промежутка времени. Тем не менее, мы продолжим использовать возможности, предоставляемые Мастером MQL5.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Нейросети в трейдинге: Возмущённые модели пространства состояний для анализа рыночной динамики (модуль E-TROF) Нейросети в трейдинге: Возмущённые модели пространства состояний для анализа рыночной динамики (модуль E-TROF)
В статье показан механизм превращения потока тиков или баров в устойчивое контекстное представление рынка, пригодное для онлайн-торговли без лишних вычислений. Инкрементальная обработка, стековое накопление состояния и расширенное пространство признаков позволяют выявлять направленные движения и локальные корреляции там, где классические методы видят лишь шум.