English Русский 中文 Deutsch 日本語 Português
preview
Optimización con el juego del caos — Game Optimization (CGO)

Optimización con el juego del caos — Game Optimization (CGO)

MetaTrader 5Probador |
330 0
Andrey Dik
Andrey Dik

Contenido

  1. Introducción
  2. Implementación del algoritmo
  3. Resultados de las pruebas


Introducción

Los algoritmos de optimización desempeñan un papel estratégico en la resolución de problemas complejos no solo en diversos campos de la ciencia moderna, sino también en el trading. Con el rápido desarrollo de la tecnología, estas tareas se hacen aún más complejas y la búsqueda de la mejor solución consume cada vez más energía, por lo que también aumentan los requisitos de los algoritmos de optimización, y su rendimiento con una alta rentabilidad. Uno de los métodos más recientes y prometedores es el algoritmo Chaos Game Optimisation (CGO), desarrollado por Siamak Talatahari y Mehdi Azizi en 2020. Este algoritmo se basa en los principios de la teoría del caos y usa secuencias caóticas para generar y mejorar las soluciones.

La idea básica del algoritmo consiste en utilizar secuencias caóticas para encontrar óptimos globales en espacios multidimensionales complejos. Las secuencias caóticas poseen ciertas propiedades que, teóricamente, les permiten evitar las trampas locales y encontrar soluciones de alta calidad. En este artículo, analizaremos los principios esenciales y las etapas del algoritmo de Chaos Game Optimization, lo implementaremos en código y realizaremos pruebas estándar en funciones de prueba para sacar conclusiones sobre su funcionamiento.


Implementación del algoritmo

Imaginemos un grupo de investigadores, cada uno de los cuales trata de encontrar un extremo en un laberinto multidimensional. Al principio del viaje, nuestros buscadores se dispersan aleatoriamente por el laberinto y encuentran su primer refugio dentro de los límites estrictamente definidos del espacio. Ese supone su punto de referencia. Cada buscador no actúa solo: observa a sus compañeros y, en cada momento, selecciona un grupo de compañeros al azar y calcula el centro de su ubicación, como si encontrara un punto de equilibrio entre sus posiciones.

Se trata de la sabiduría colectiva promediada por la experiencia del grupo. Y entonces comienza la verdadera magia del caos. El buscador puede seleccionar uno de los cuatro caminos para dar el siguiente paso. Cada trayectoria supone una fórmula de movimiento específica en la que se entrelazan tres puntos clave: su posición actual, el mejor lugar encontrado por todo el grupo y el centro del subgrupo elegido. Estos puntos se mezclan, y la fuerza de su influencia en el movimiento posterior viene definida por el coeficiente α, el conductor del caos.

El propio coeficiente α adopta diferentes formas, y cada buscador, siguiendo las reglas, se puede impulsar desde su posición, apuntando a la media áurea entre el mejor resultado y el centro del grupo, o comenzar desde el mejor punto, explorando el espacio que lo rodea, y también puede impulsarse desde el centro del grupo, o dar un salto completamente aleatorio hacia lo desconocido.

Al final de cada acción, se comparan los resultados. Si uno de los buscadores encuentra un lugar mejor que el récord anterior, se convertirá en un nuevo faro para todo el grupo en su búsqueda continua.

Ahí reside la verdadera belleza del algoritmo: en su capacidad para convertir el caos en orden, el azar en movimiento intencionado, la incertidumbre en progreso, y cada paso, cada movimiento está sujeto a la búsqueda de soluciones entre lo conocido y lo desconocido, entre la estabilidad y el riesgo, entre el orden y el caos.

cgo-illustration

Figura 1. Acciones típicas de un agente de búsqueda en el algoritmo CGO

En la figura 1, el punto rojo es el agente actual para el que calculamos la nueva posición. Los puntos azules suponen un grupo de agentes seleccionados aleatoriamente en la población en un número elegido al azar. El círculo de puntos violetas es la posición central del grupo. El punto dorado es la mejor solución encontrada. Los puntos verdes son posibles nuevas posiciones del agente según distintas fórmulas:
  • Fórmula 1: actual + α(β×mejor - γ×media)
  • Fórmula 2: mejor + α(β×media - γ×actual)
  • Fórmula 3: media + α(β×mejor - γ×actual)
  • Random: posición aleatoria

    Las líneas de puntos muestran los vectores de influencia de la mejor solución y la posición media del grupo dentro del movimiento del agente actual. El rectángulo gris punteado indica los límites de la zona de búsqueda.

    Vamos a escribir ahora el pseudocódigo del algoritmo.

  1. INICIALIZACIÓN DEL ALGORITMO:
    • Establecemos el tamaño de la población (por defecto es de 50 agentes)
    • Definimos los límites de búsqueda para cada coordenada:
      • valores mínimos (rangeMin)
      • valores máximos (rangeMax)
      • cambio de paso (rangeStep)
    • Para cada agente de la población:
      • generamos coordenadas iniciales aleatorias dentro de los límites dados
      • redondeamos las coordenadas para ajustarlas al paso
      • calculamos el valor de la función objetivo
    • Determinamos la mejor solución inicial entre todos los agentes
  2. CICLO PRINCIPAL DE OPTIMIZACIÓN:
    • Para cada agente de la población: 
    a) Elegimos un subconjunto aleatorio de agentes:
    • tamaño del subgrupo = número aleatorio entre 1 y el tamaño de la población
    • seleccionamos aleatoriamente a los agentes en un subgrupo
    b) Calculamos la posición media del subgrupo seleccionado:
    • para cada coordenada: coordenada_media = suma_grupo_coordenadas / tamaño_grupo
    c) Generamos los coeficientes para fórmulas de movimiento:
    • α (alfa) = elegir al azar uno de los métodos:
      • método 1: número aleatorio de 0 a 1
      • método 2: 2 × aleatorio(0,1) - 1 [obtenemos un número de -1 a 1]
      • método 3: Ir × aleatorio(0,1) + 1
      • método 4: Ir × aleatorio(0,1) + (1-Ir) donde Ir = aleatorio 0 ó 1
    • β (beta) = aleatoriamente 1 o 2
    • γ (gamma) = aleatoriamente 1 o 2
    d) Elegimos una de las cuatro fórmulas de movimiento al azar:
    • Fórmula 1: nueva_posición = actual + α(β×mejor - γ×media)
    • Fórmula 2: nueva_posición = mejor + α(β×media - γ×actual)
    • Fórmula 3: nueva_posición = media + α(β×mejor - γ×actual)
    • Fórmula 4: nueva_posición = posición aleatoria dentro de los límites de búsqueda
    e) Aplicamos la fórmula seleccionada:
    • para cada coordenada:
      • calculamos el nuevo valor mediante la fórmula
      • comprobamos si la búsqueda está fuera de los límites
      • si está fuera de los límites, corregimos a los límites más cercanos
      • redondeamos el valor considerando el paso de cambio
    f) Calculamos el valor de la función objetivo en la nueva posición.
  3. ACTUALIZACIÓN DE LA MEJOR SOLUCIÓN:
    • Para cada agente:
      • si el valor de la función objetivo del agente es mejor que el mejor actual:
        • actualizamos el mejor valor
        • guardamos las coordenadas de la nueva mejor solución
  4. REPETICIÓN:
    • Repetimos los pasos 2-3 hasta que se cumpla la condición de parada:
      • se ha alcanzado el número máximo de iteraciones
      • o se ha encontrado una solución de la calidad necesaria
      • u otro criterio de parada
  5. Pasemos ahora a la aplicación del algoritmo en sí. La clase "C_AO_CGO" implementa el algoritmo CGO y deriva de la clase "C_AO"; hereda propiedades y métodos de la clase básica. 

    Métodos:

    • SetParams () — establece el valor de "popSize" basándose en los datos del array de parámetros "params". Esto resulta importante para afinar el algoritmo antes de utilizarlo.
    • Init () — método de inicialización, admite valores de rango mínimo y máximo, paso de cambio y número de épocas. Su objetivo consiste en preparar el algoritmo para su ejecución estableciendo los límites de búsqueda y otros parámetros.
    • Moving () — describe los pasos necesarios para desplazar a los individuos durante el proceso de optimización. Su aplicación proporciona una lógica para las soluciones alternativas y su mejora.
    • Revision () — se encarga de revisar tanto las soluciones actuales de la población como la mejor solución global.

    Métodos privados:

    • GetAlpha () — para obtener el parámetro alpha, que se utiliza para controlar la estrategia, la "intensidad" y la "diversidad" de la búsqueda.
    • GenerateNewSolution () — para generar una nueva solución basada en el índice (seedIndex) y el valor medio del grupo (meanGroup). 
    class C_AO_CGO : public C_AO
    {
      public: //--------------------------------------------------------------------
      ~C_AO_CGO () { }
      C_AO_CGO ()
      {
        ao_name = "CGO";
        ao_desc = "Chaos Game Optimization";
        ao_link = "https://www.mql5.com/es/articles/17047";
    
        popSize = 25;
    
        ArrayResize (params, 1);
        params [0].name = "popSize"; params [0].val = popSize;
      }
    
      void SetParams ()
      {
        popSize = (int)params [0].val;
      }
    
      bool Init (const double &rangeMinP  [],  // minimum values
                 const double &rangeMaxP  [],  // maximum values
                 const double &rangeStepP [],  // step change
                 const int     epochsP = 0);   // number of epochs
    
      void Moving ();
      void Revision ();
    
      private: //-------------------------------------------------------------------
      double GetAlpha ();
      void   GenerateNewSolution (int seedIndex, double &meanGroup []);
    };
    //——————————————————————————————————————————————————————————————————————————————
    

    El método "Init" de la clase "C_AO_CGO" se encarga de inicializar los parámetros del algoritmo de optimización antes de su inicio. Toma los siguientes argumentos: los arrays que contienen los valores mínimo y máximo para cada variable de búsqueda, el cambio de paso para cada variable y el número de épocas (iteraciones) del algoritmo.

    //——————————————————————————————————————————————————————————————————————————————
    bool C_AO_CGO::Init (const double &rangeMinP  [], // minimum values
                         const double &rangeMaxP  [], // maximum values
                         const double &rangeStepP [], // step change
                         const int     epochsP = 0)   // number of epochs
    {
      if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;
    
      return true;
    }
    //——————————————————————————————————————————————————————————————————————————————
    

    El método Moving ejecuta la lógica básica de desplazamiento de los individuos de la población de soluciones en el algoritmo CGO. El objetivo principal de este método consiste en actualizar las soluciones de la población basándose en reglas, lo que incluye generar nuevas soluciones y promediar los resultados. Veamos con detalle sus partes principales.

    Primera parte, inicialización en la primera llamada (si la variable "revision" es "false"):

    • Se ejecuta un ciclo externo sobre todos los elementos de la población (popSize) y para cada elemento (individuo i):
      • Se inicia un ciclo interno sobre las coordenadas (coords):
      • Se genera un valor aleatorio para cada coordenada usando el método u.RNDfromCI (), que retorna un valor aleatorio dentro del rango especificado.
      • A continuación, este valor se ajusta mediante u.SeInDiSp (), que garantiza que el valor se mantenga dentro del intervalo, y redondea al paso más próximo.
      • Establece la bandera "revision" en "true" para la siguiente llamada al método y sale del método.
      Segunda parte, actualización de la población (si la variable "revision" tiene el valor "true"):
      • Para cada individuo de la población:
        • Se genera un tamaño de grupo aleatorio "randGroupSize" de "1" a "popSize".
        • Se crea un array "meanGroup" para almacenar el valor medio de las coordenadas, cuyo tamaño corresponde al número de coordenadas establecidas en "coords".
        • El array "randIndices" se rellena con índices aleatorios (individuos) que se utilizarán para formar el grupo.
        • En cada iteración, se añaden índices aleatorios a "randIndices", con los índices seleccionados al azar.
        • A continuación, para cada grupo, se suman los valores de las coordenadas de cada individuo a partir de índices seleccionados al azar y el resultado se guarda en "meanGroup".
        • Después de la suma, el valor de "meanGroup" se divide por el número de individuos del grupo para obtener el valor medio.
        • Luego se genera una nueva solución para el individuo "i" basada en la media del grupo utilizando el método "GenerateNewSolution ()".
      //——————————————————————————————————————————————————————————————————————————————
      void C_AO_CGO::Moving ()
      {
        //----------------------------------------------------------------------------
        if (!revision)
        {
          for (int i = 0; i < popSize; i++)
          {
            for (int c = 0; c < coords; c++)
            {
              a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
              a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
            }
          }
      
          revision = true;
          return;
        }
      
        //----------------------------------------------------------------------------
        for (int i = 0; i < popSize; i++)
        {
          int randGroupSize = u.RNDminusOne (popSize) + 1;
          double meanGroup [];
          ArrayResize (meanGroup, coords);
          ArrayInitialize (meanGroup, 0);
      
          int randIndices [];
          ArrayResize (randIndices, randGroupSize);
      
          for (int j = 0; j < randGroupSize; j++) randIndices [j] = u.RNDminusOne (popSize);
      
          for (int j = 0; j < randGroupSize; j++)
          {
            for (int c = 0; c < coords; c++)
            {
              meanGroup [c] += a [randIndices [j]].c [c];
            }
          }
          for (int c = 0; c < coords; c++) meanGroup [c] /= randGroupSize;
      
          GenerateNewSolution (i, meanGroup);
        }
      }
      //——————————————————————————————————————————————————————————————————————————————
      

      Acto seguido, el método de revisión actualiza las mejores soluciones de la población. Itera por todos los individuos de la población y comprueba si el valor "f" de su función de aptitud es mayor que el mejor valor actual "fB". En caso afirmativo, actualiza "fB" con el nuevo valor "f" y copia las coordenadas c del individuo actual en el array "cB". Así, el método Revision encuentra y actualiza la mejor solución conocida en la población basándose en los valores de la función de aptitud.

      //——————————————————————————————————————————————————————————————————————————————
      void C_AO_CGO::Revision ()
      {
        for (int i = 0; i < popSize; i++)
        {
          if (a [i].f > fB)
          {
            fB = a [i].f;
            ArrayCopy (cB, a [i].c, 0, 0, WHOLE_ARRAY);
          }
        }
      }
      //——————————————————————————————————————————————————————————————————————————————
      

      El método "GetAlpha" genera y retorna un valor "alpha" aleatorio según unas condiciones de selección aleatorias.

      • Ir   — valor aleatorio igual a "0" o "1".
      • Hay cuatro casos posibles (disponibles en "case"), cada uno de los cuales genera un valor "alpha" utilizando la fórmula correspondiente:
        • Caso 0: Genera un valor de 0 a 1.
        • Caso 1: Genera un valor entre -1 y 1.
        • Caso 2: Genera un valor de 1 a 2 multiplicándolo por "Ir" (0 ó 1).
        • Caso 3: Genera un valor que depende de "Ir" y tiene un rango de 0 a 1, o 1, dependiendo del valor "Ir".
      Nótese que las expresiones usadas para generar el número "alpha" podrían haberse utilizado de forma más sencilla, pero se utiliza la forma original, que se corresponde con las fórmulas de los autores del algoritmo.
        //——————————————————————————————————————————————————————————————————————————————
        double C_AO_CGO::GetAlpha ()
        {
          int Ir = u.RNDminusOne (2);
        
          switch (u.RNDminusOne (4))
          {
            case 0: return u.RNDfromCI (0, 1);
            case 1: return 2 * u.RNDfromCI (0, 1) - 1;
            case 2: return Ir * u.RNDfromCI (0, 1) + 1;
            case 3: return Ir * u.RNDfromCI (0, 1) + (1 - Ir);
          }
          return 0;
        }
        //——————————————————————————————————————————————————————————————————————————————
        

        El método "GenerateNewSolution" se encarga de generar una nueva solución para un agente concreto de la población en función de varios parámetros aleatorios.

        Inicialización de parámetros:
        • alpha — valor obtenido llamando al método "GetAlpha ()", utilizado para influir en la nueva posición.
        • beta y gamma son valores aleatorios (1 ó 2).
        Selección de fórmulas:
        • formula — selecciona aleatoriamente una de las cuatro ecuaciones posibles mediante las que se calculará la nueva posición.
        Ciclo por coordenadas: para cada coordenada (de 0 a coords):
        • newPos — variable para almacenar la nueva posición utilizando la fórmula seleccionada.
        • Dependiendo del valor de "formula":
          • Caso 0: la nueva posición se calcula como la posición actual del agente añadiendo la combinación de coordenadas de "cB" (mejor solución poblacional) y "meanGroup".
          • Caso 1: la nueva posición se calcula usando la coordenada de "cB" y el valor medio "meanGroup".
          • Caso 2: la nueva posición se determina partiendo del valor medio y la coordenada del agente actual.
          • Caso 3: la nueva posición se establece aleatoriamente dentro del rango especificado (rangoMin [c] y rangoMax [c]).
        Corrección de la nueva posición:
        • a [seedIndex].c [c] — la coordenada del agente correspondiente se actualiza mediante el método "u.SeInDiSp ()", que considera los valores mínimos, los valores máximos y los pasos para garantizar que el nuevo valor se encuentra dentro de los límites aceptables.
        //——————————————————————————————————————————————————————————————————————————————
        void C_AO_CGO::GenerateNewSolution (int seedIndex, double &meanGroup [])
        {
          double alpha = GetAlpha ();
          int    beta  = u.RNDminusOne (2) + 1;
          int    gamma = u.RNDminusOne (2) + 1;
        
          int formula = u.RNDminusOne (4);
        
          for (int c = 0; c < coords; c++)
          {
            double newPos = 0;
        
            switch (formula)
            {
              case 0:
                newPos = a [seedIndex].c [c] + alpha * (beta * cB [c] - gamma * meanGroup [c]);
                break;
        
              case 1:
                newPos = cB [c] + alpha * (beta * meanGroup [c] - gamma * a [seedIndex].c [c]);
                break;
        
              case 2:
                newPos = meanGroup [c] + alpha * (beta * cB [c] - gamma * a [seedIndex].c [c]);
                break;
        
              case 3:
                newPos = u.RNDfromCI (rangeMin [c], rangeMax [c]);
                break;
            }
        
            a [seedIndex].c [c] = u.SeInDiSp (newPos, rangeMin [c], rangeMax [c], rangeStep [c]);
          }
        }
        //——————————————————————————————————————————————————————————————————————————————
        

        Tras las pruebas, intentamos mejorar la convergencia del algoritmo y decidimos hacer un añadido respecto a la versión básica del algoritmo CGO. La principal diferencia se halla al principio del procesamiento de cada coordenada, antes de aplicar las fórmulas básicas de movimiento:

        double rnd = u.RNDprobab();                             // Get a random number from 0.0 to 1.0
        rnd *= rnd;                                             // Squate it
        int ind = (int)u.Scale(rnd, 0.0, 1.0, 0, popSize - 1);  // Scale to index
        a[seedIndex].c [c] = a[ind].c [c];                      // Copy the coordinate from another agent with the received index
        

        La coordenada se copia de un agente seleccionado aleatoriamente, y la selección del agente no es uniforme sino con una distribución de probabilidad cuadrática (rnd *= rnd). Esto crea un "desplazamiento" hacia la selección de agentes con índices más pequeños (las mejores soluciones tienen una mayor probabilidad de ser seleccionadas). Luego elevamos al cuadrado el número aleatorio, creando así una distribución desigual, escalamos al rango del índice de población y, a continuación, copiamos, antes de aplicar las fórmulas básicas de movimiento. Lamentablemente, nuestro empeño a la hora de acelerar la convergencia en áreas prometedoras no ha tenido el efecto esperado.

        Probablemente como consecuencia de la convergencia prematura, debido al efecto de amplificación, la diversidad en la población disminuye rápidamente, lo que en este algoritmo provoca un atasco aún mayor; es posible que la propia lógica del algoritmo impida que esto ocurra. A continuación le mostramos la sección de código donde se introdujimos los cambios; además hicimos algunos otros intentos de mejora, sin embargo, no hubo ningún progreso notable y decidimos quedarnos con la versión original del algoritmo.

        //——————————————————————————————————————————————————————————————————————————————
        void C_AO_CGO::GenerateNewSolution (int seedIndex, double &meanGroup [])
        {
          double alpha = GetAlpha ();
          int    beta  = u.RNDminusOne (2) + 1;
          int    gamma = u.RNDminusOne (2) + 1;
        
          int formula = u.RNDminusOne (4);
        
          for (int c = 0; c < coords; c++)
          {
            double rnd = u.RNDprobab ();
            rnd *= rnd;
            int ind = (int)u.Scale (rnd, 0.0, 1.0, 0, popSize - 1);
            a [seedIndex].c [c] = a [ind].c [c];
        
            double newPos = 0;
        
            switch (formula)
            {
              case 0:
                newPos = a [seedIndex].c [c] + alpha * (beta * cB [c] - gamma * meanGroup [c]);
                break;
        
              case 1:
                newPos = cB [c] + alpha * (beta * meanGroup [c] - gamma * a [seedIndex].c [c]);
                break;
        
              case 2:
                newPos = meanGroup [c] + alpha * (beta * cB [c] - gamma * a [seedIndex].c [c]);
                break;
        
              case 3:
                newPos = u.RNDfromCI (rangeMin [c], rangeMax [c]);
                break;
            }
        
            a [seedIndex].c [c] = u.SeInDiSp (newPos, rangeMin [c], rangeMax [c], rangeStep [c]);
          }
        }
        //——————————————————————————————————————————————————————————————————————————————
        


        Resultados de las pruebas

        Como podemos ver a continuación por los resultados de las pruebas, el número total de porcentajes anotados por el algoritmo resulta bastante modesto, sin embargo, si miramos más de cerca, podemos notar una característica interesante de este algoritmo, que vamos a describir a continuación.

        CGO|Chaos Game Optimization|50.0|
        =============================
        5 Hilly's; Func runs: 10000; result: 0.5725597668122144
        25 Hilly's; Func runs: 10000; result: 0.3715760642098293
        500 Hilly's; Func runs: 10000; result: 0.32017971142744234
        =============================
        5 Forest's; Func runs: 10000; result: 0.6117551660766816
        25 Forest's; Func runs: 10000; result: 0.619308424855028
        500 Forest's; Func runs: 10000; result: 0.6216109945434442
        =============================
        5 Megacity's; Func runs: 10000; result: 0.3753846153846153
        25 Megacity's; Func runs: 10000; result: 0.2192307692307692
        500 Megacity's; Func runs: 10000; result: 0.19028461538461647
        =============================
        All score: 3.90189 (43.35%)

        La visualización del funcionamiento del algoritmo con las funciones de prueba muestra claramente la formación de estructuras en la agrupación de agentes, y estas estructuras son diferentes en las distintas tareas. Pero lo que resulta común en la naturaleza del algoritmo es la enorme variación de los resultados de la optimización.

        Hilly

        CGO en la función de prueba Hilly

        Forest

        CGO en la función de prueba Forest

        Megacity

        CGO en la función de prueba Forest

        Al final de la prueba, el algoritmo CGO ocupa el puesto 38 en la tabla de clasificación de algoritmos de optimización basados en poblaciones.

        # AO Description Hilly Hilly final Forest Forest final Megacity (discrete) Megacity final Final result % de 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 search0.949480.847760.438572.235811.000000.923340.399882.323230.709230.634770.230911.574916.13468.15
        2CLAcode lock algorithm (joo)0.953450.871070.375902.200420.989420.917090.316422.222940.796920.693850.193031.683806.10767.86
        3AMOmanimal migration optimization M0.903580.843170.462842.209590.990010.924360.465982.380340.567690.591320.237731.396755.98766.52
        4(P+O)ES(P+O) evolution strategies0.922560.881010.400212.203790.977500.874900.319452.171850.673850.629850.186341.490035.86665.17
        5CTAcomet tail algorithm (joo)0.953460.863190.277702.094350.997940.857400.339492.194840.887690.564310.105121.557125.84664.96
        6TETAtime evolution travel algorithm (joo)0.913620.823490.319902.057010.970960.895320.293242.159520.734620.685690.160211.580525.79764.41
        7SDSmstochastic diffusion search M0.930660.854450.394762.179880.999830.892440.196192.088460.723330.611000.106701.441035.70963.44
        8AAmarchery algorithm M0.917440.708760.421602.047800.925270.758020.353282.036570.673850.552000.237381.463235.54861.64
        9ESGevolution of social groups (joo)0.999060.796540.350562.146161.000000.828630.131021.959650.823330.553000.047251.423585.52961.44
        10SIAsimulated isotropic annealing (joo)0.957840.842640.414652.215130.982390.795860.205071.983320.686670.493000.090531.270205.46960.76
        11ACSartificial cooperative search0.755470.747440.304071.806981.000000.888610.224132.112740.690770.481850.133221.305835.22658.06
        12DAdialectical algorithm0.861830.700330.337241.899400.981630.727720.287181.996530.703080.452920.163671.319675.21657.95
        13BHAmblack hole algorithm M0.752360.766750.345831.864930.935930.801520.271772.009230.650770.516460.154721.321955.19657.73
        14ASOanarchy society optimization0.848720.746460.314651.909830.961480.791500.238031.991010.570770.540620.166141.277525.17857.54
        15RFOroyal flush optimization (joo)0.833610.737420.346291.917330.894240.738240.240981.873460.631540.502920.164211.298675.08956.55
        16AOSmbúsqueda de orbitales atómicos M0.802320.704490.310211.817020.856600.694510.219961.771070.746150.528620.143581.418355.00655.63
        17TSEAturtle shell evolution algorithm (joo)0.967980.644800.296721.909490.994490.619810.227081.841390.690770.426460.135981.253225.00455.60
        18DEdifferential evolution0.950440.616740.303081.870260.953170.788960.166521.908650.786670.360330.029531.176534.95555.06
        19CROchemical reaction optimization0.946290.661120.298531.905930.879060.584220.211461.674730.758460.426460.126861.311784.89254.36
        20BIOblood inheritance optimization (joo)0.815680.653360.308771.777810.899370.653190.217601.770160.678460.476310.139021.293784.84253.80
        21BSAbird swarm algorithm0.893060.649000.262501.804550.924200.711210.249391.884790.693850.326150.100121.120124.80953.44
        22HSharmony search0.865090.687820.325271.878180.999990.680020.095901.775920.620000.422670.054581.097254.75152.79
        23SSGsaplings sowing and growing0.778390.649250.395431.823080.859730.624670.174291.658690.646670.441330.105981.193984.67651.95
        24BCOmbacterial chemotaxis optimization M0.759530.622680.314831.697040.893780.613390.225421.732590.653850.420920.144351.219124.64951.65
        25ABOafrican buffalo optimization0.833370.622470.299641.755480.921700.586180.197231.705110.610000.431540.132251.173784.63451.49
        26(PO)ES(PO) evolution strategies0.790250.626470.429351.846060.876160.609430.195911.681510.590000.379330.113221.082554.61051.22
        27TSmtabu search M0.877950.614310.291041.783300.928850.518440.190541.637830.610770.382150.121571.114494.53650.40
        28BSObrain storm optimization0.937360.576160.296881.810410.931310.558660.235371.725340.552310.290770.119140.962224.49849.98
        29WOAmwale optimization algorithm M0.845210.562980.262631.670810.931000.522780.163651.617430.663080.411380.113571.188034.47649.74
        30AEFAartificial electric field algorithm0.877000.617530.252351.746880.927290.726980.180641.834900.666150.116310.095080.877544.45949.55
        31AEOartificial ecosystem-based optimization algorithm0.913800.467130.264701.645630.902230.437050.214001.553270.661540.308000.285631.255174.45449.49
        32ACOmant colony optimization M0.881900.661270.303771.846930.858730.586800.150511.596040.596670.373330.024720.994724.43849.31
        33BFO-GAbacterial foraging optimization - ga0.891500.551110.315291.757900.969820.396120.063051.428990.726670.275000.035251.036924.22446.93
        34SOAsimple optimization algorithm0.915200.469760.270891.655850.896750.374010.169841.440600.695380.280310.108521.084224.18146.45
        35ABHartificial bee hive algorithm0.841310.542270.263041.646630.878580.477790.171811.528180.509230.338770.103970.951974.12745.85
        36ACMOatmospheric cloud model optimization0.903210.485460.304031.692700.802680.378570.191781.373030.623080.244000.107950.975034.04144.90
        37ADAMmadaptive moment estimation M0.886350.447660.266131.600140.844970.384930.168891.398800.661540.270460.105941.037944.03744.85
        38CGOchaos game optimization0.572560.371580.320181.264320.611760.619310.621611.852670.375380.219230.190280.784903.90243.35
        39ATAmartificial tribe algorithm M0.717710.553040.252351.523100.824910.559040.204731.588670.440000.186150.094110.720263.83242.58
        40ASHAartificial showering algorithm0.896860.404330.256171.557370.803600.355260.191601.350460.476920.181230.097740.755893.66440.71
        41ASBOadaptive social behavior optimization0.763310.492530.326191.582020.795460.400350.260971.456770.264620.171690.182000.618313.65740.63
        42MECmind evolutionary computation0.695330.533760.326611.555690.724640.330360.071981.126980.525000.220000.041980.786983.47038.55
        43CSAcircle search algorithm0.665600.453170.291261.410030.687970.413970.205251.307190.375380.236310.106460.718153.43538.17
        44IWOinvasive weed optimization0.726790.522560.331231.580580.707560.339550.074841.121960.423330.230670.046170.700173.40337.81
        45Micro-AISmicro artificial immune system0.795470.519220.308611.623300.729560.368790.093981.192330.376670.158670.028020.563353.37937.54

        R.W.random walk0.487540.321590.257811.066940.375540.219440.158770.753750.279690.149170.098470.527342.34826.09


        Conclusiones

        Tras analizar los resultados del algoritmo CGO, hemos llegado a conclusiones importantes. El algoritmo de Chaos Game Optimization muestra un comportamiento extremadamente interesante. En conjunto, su rendimiento puede calificarse de inferior a la media, como demuestra una puntuación global del 43,35%. Sin embargo, lo más destacable es su comportamiento al escalar la tarea, pues el CGO muestra una alta eficiencia exactamente en tareas multivariantes, en las pruebas con una dimensionalidad de 1000 variables. Se trata de una propiedad atípica para la mayoría de los algoritmos metaheurísticos, que suelen sufrir la "maldición de la dimensionalidad" y pierden eficacia con el aumento del número de variables. En cambio, el CGO a veces incluso supera sus resultados en tareas de 10 y 50 dimensiones al trabajar con tareas de 1000 dimensiones. Esto resulta especialmente evidente en la función de prueba Forest, que tiene un extremo global en un punto "agudo".

        Creo que este fenómeno se debe a la propia naturaleza del algoritmo. La base caótica del CGO y la variedad de fórmulas de movimiento proporcionan un mecanismo eficaz para explorar espacios de alta dimensionalidad. Las cuatro estrategias diferentes de actualización de la posición, la selección aleatoria entre ellas y un coeficiente α impredecible, permiten al algoritmo resolver problemas en paisajes multidimensionales complejos. El algoritmo funciona especialmente bien con características de tipo Forest, con resultados de 0,61-0,62, muy por encima de su rendimiento medio.

        Analizando el dispositivo del algoritmo, podemos ver que su fuerza en la alta dimensionalidad se relaciona con el procesamiento de las coordenadas. En lugar de trabajar con el vector soluciones completo, el CGO actualiza cada coordenada de forma independiente, lo que le ofrece una ventaja al aumentar la dimensionalidad. Además, el uso de grupos aleatorios y sus posiciones medias garantiza un intercambio eficaz de información entre los agentes, incluso en espacios de alta dimensionalidad.

        Hemos intentado rotado la superficie de la función Forest en diferentes ángulos para asegurarnos de que los interesantes resultados obtenidos no suponen una coincidencia aleatoria derivada de las peculiaridades de la lógica del algoritmo y la función de prueba correspondiente. Esto era necesario para eliminar la posibilidad de alcanzar accidentalmente el extremo global. Los experimentos con rotación de funciones solo han confirmado que esos resultados no son aleatorios. Dada esta peculiaridad del trabajo del CGO con funciones con extremos agudos, recomiendo múltiples ejecuciones de optimización si se utiliza este algoritmo. Esta recomendación resulta especialmente relevante para este algoritmo en particular.

        En general, a pesar de su rendimiento global medio, la capacidad única del CGO para mantener e incluso mejorar la eficiencia a medida que aumenta la dimensionalidad del problema lo convierte en un algoritmo extremadamente interesante para su posterior estudio y aplicación a problemas de optimización complejos.

        Tab

        Figura 2. Clasificación por colores de los algoritmos según las pruebas respectivas

        Chart

        Figura 3. Histograma de los resultados de las pruebas de algoritmos (en una escala de 0 a 100, cuanto más mejor, donde 100 es el máximo resultado teórico posible, el script para calcular la tabla de puntuación está en el archivo)

        Ventajas e inconvenientes del algoritmo CGO:

        Ventajas:

        1. Sin parámetros externos
        2. Buena convergencia en funciones de dimensionalidad alta y media

        Desventajas:

        1. Se atasca en extremos locales en problemas de pequeña dimensionalidad.

        Adjuntamos al artículo un archivo con las versiones actuales de los códigos de los algoritmos. El autor de este artículo no se responsabiliza de la exactitud absoluta de la descripción de los algoritmos canónicos, muchos de ellos han sido modificados para mejorar las capacidades de búsqueda. Las conclusiones y juicios presentados en los artículos se basan en los resultados de los experimentos realizados.


        Programas usados en el artículo

        #NombreTipoDescripción
        1#C_AO.mqh
        Archivo de inclusión
        Clase padre de algoritmos de población
        optimizaciones
        2#C_AO_enum.mqh
        Archivo de inclusión
        Enumeración de los algoritmos de optimización basados en la población
        3TestFunctions.mqh
        Archivo de inclusión
        Biblioteca de funciones de prueba
        4
        TestStandFunctions.mqh
        Archivo de inclusión
        Biblioteca de funciones del banco de pruebas
        5
        Utilities.mqh
        Archivo de inclusión
        Biblioteca de funciones auxiliares
        6
        CalculationTestResults.mqh
        Archivo de inclusión
        Script para calcular los resultados en una tabla comparativa
        7
        Testing AOs.mq5
        ScriptBanco de pruebas único para todos los algoritmos de optimización basados en la población
        8
        Simple use of population optimization algorithms.mq5
        Script
        Ejemplo sencillo de utilización de algoritmos de optimización basados en la población sin visualización
        9
        Test_AO_CGO.mq5
        ScriptBanco de pruebas para el CGO

        Traducción del ruso hecha por MetaQuotes Ltd.
        Artículo original: https://www.mql5.com/ru/articles/17047

        Archivos adjuntos |
        CGO.zip (168.66 KB)
        Desarrollo de asesores expertos autooptimizables en MQL5 (Parte 5): Reglas de negociación autoadaptativas Desarrollo de asesores expertos autooptimizables en MQL5 (Parte 5): Reglas de negociación autoadaptativas
        Las mejores prácticas, que definen cómo utilizar un indicador de forma segura, no siempre son fáciles de seguir. Las condiciones de mercado tranquilas pueden producir, sorprendentemente, lecturas en el indicador que no califican como señal de negociación, lo que conlleva la pérdida de oportunidades para los operadores algorítmicos. Este artículo propondrá una posible solución a este problema, al analizar cómo construir aplicaciones de negociación capaces de adaptar sus reglas de negociación a los datos de mercado disponibles.
        Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 10): Flujo externo (II) VWAP Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 10): Flujo externo (II) VWAP
        ¡Domina el poder del VWAP con nuestra guía completa! Aprenda a integrar el análisis VWAP en su estrategia de trading utilizando MQL5 y Python. Maximice su conocimiento del mercado y mejore sus decisiones comerciales hoy mismo.
        Aprendizaje automático y Data Science (Parte 33): Pandas Dataframe en MQL5, recopilación de datos para facilitar el uso de ML Aprendizaje automático y Data Science (Parte 33): Pandas Dataframe en MQL5, recopilación de datos para facilitar el uso de ML
        Cuando se trabaja con modelos de aprendizaje automático, es esencial garantizar la coherencia de los datos utilizados para el entrenamiento, la validación y las pruebas. En este artículo, crearemos nuestra propia versión de la biblioteca Pandas en MQL5 para garantizar un enfoque unificado para el manejo de datos de aprendizaje automático, con el fin de asegurar que se apliquen los mismos datos dentro y fuera de MQL5, donde se lleva a cabo la mayor parte del entrenamiento.
        Redes neuronales en el trading: Modelos híbridos de secuencias de grafos (Final) Redes neuronales en el trading: Modelos híbridos de secuencias de grafos (Final)
        Continuamos nuestro estudio de los modelos híbridos de secuencias de grafos (GSM++) que integran las ventajas de distintas arquitecturas, proporcionando una gran precisión de análisis y una asignación eficiente de los recursos computacionales. Estos modelos revelan eficazmente patrones ocultos, reduciendo el impacto del ruido del mercado y mejorando la calidad de las previsiones.