Русский
preview
Algoritmo de otimização do dingo - Dingo Optimization Algorithm (DOA)

Algoritmo de otimização do dingo - Dingo Optimization Algorithm (DOA)

MetaTrader 5Negociação |
27 0
Andrey Dik
Andrey Dik

Conteúdo

  1. Introdução
  2. Implementação do algoritmo
  3. Resultados dos testes


Introdução

Neste artigo, vamos conhecer o algoritmo de otimização do dingo (Dingo Optimization Algorithm, DOA), desenvolvido em 2021 por um grupo internacional de pesquisadores liderado por Hernán Peraza-Vázquez. O trabalho foi publicado na revista Mathematical Problems in Engineering (DOI: 10.1155/2021/9107547).

O algoritmo é inspirado no comportamento de caça dos dingos australianos (Canis lupus dingo), os maiores mamíferos predadores da Austrália. Os dingos demonstram um comportamento social complexo e utilizam diferentes estratégias de caça conforme o tamanho e o tipo da presa.


Implementação do algoritmo

O DOA modela três estratégias principais de caça dos dingos:

  1. Ataque em grupo: os dingos cercam a presa e atacam em conjunto, o que é especialmente eficaz na caça de animais de grande porte, como cangurus;
  2. Perseguição: caçada individual de presas pequenas, na qual o dingo persegue a vítima até a exaustão;
  3. Busca de carniça: comportamento oportunista durante a exploração de novos territórios e a procura de presas mortas.

Além disso, o algoritmo inclui um mecanismo de sobrevivência, que atualiza as posições dos indivíduos mais fracos da população, simulando a seleção natural. O algoritmo equilibra a diversificação (exploration) e a intensificação (exploitation) no espaço de busca por meio de dois parâmetros probabilísticos: P, a probabilidade de escolher entre caça e busca de carniça, e Q, a probabilidade de escolher entre ataque em grupo e perseguição durante a caça.

Imagine que você tem uma matilha de 50 dingos em busca do melhor local para caçar em um território amplo. Cada dingo representa uma solução potencial do problema de otimização, enquanto o território corresponde ao espaço de busca.

1. Ataque em grupo (probabilidade de 35%). A dança dos predadores


Na savana australiana, uma matilha de dingos cerca uma manada de cangurus. Não se trata de uma perseguição caótica, mas de uma operação coordenada. Vários indivíduos, de dois corajosos até metade da matilha, avançam e formam uma rede invisível de posições.

Cada dingo atacante compartilha sua experiência com o grupo: onde está, o que vê. O conhecimento coletivo desses dingos converge para um único ponto de referência, uma média da sabedoria da matilha. Então entra em cena o paradoxo da caça: a nova posição é determinada por um movimento para longe do alfa, do líder. Por quê? Porque, se todos seguirem cegamente o líder, a matilha se transformará em uma multidão previsível. O coeficiente β₁ atua como a força do vento, às vezes a favor (positivo), às vezes contra (negativo), criando manobras imprevisíveis para a matilha. Como resultado: caos guiado pela lógica. Os dingos se espalham em leque pelo território, explorando cantos da área de caça que o líder poderia ter deixado passar. Por enquanto, estas são hipóteses que precisam ser validadas na prática.

Quando os dingos caçam em grupo, de 2 a 25 indivíduos são escolhidos aleatoriamente para o ataque. A nova posição do dingo é calculada como:

Nova_posição = β₁ × (Posição_média_dos_atacantes) - Posição_do_líder

Exemplo: se 5 dingos estão nos pontos [10, 20, 30, 40, 50], a posição média deles é 30. Com β₁ = 1.5 e posição do líder = 45:

Nova posição = 1.5 × 30 - 45 = 0

O dingo se desloca para longe do líder, explorando novas regiões.

2. Perseguição (probabilidade de 35%). O caçador solitário


Um jovem dingo se separa da matilha. À sua frente está uma lebre, rápida e esquiva. É uma caça individual, na qual o que importa não é a força do grupo, mas a habilidade de cada caçador. O dingo mantém duas referências no campo de visão: a posição do alfa (a sabedoria acumulada do melhor caçador) e um vizinho aleatório nas proximidades. A distância até o vizinho define a amplitude do bote: quanto mais distante o vizinho, mais ousado é o salto. A função exponencial e^β₂ atua como adrenalina no sangue: com β₂ positivo, há um pico de energia e o salto se alonga; com β₂ negativo, prevalecem a cautela e movimentos curtos e precisos.

A trajetória da perseguição é sinuosa: o dingo se move em direção à posição do líder, mas seu caminho é distorcido pela presença do vizinho, criando uma espiral de perseguição que se contrai gradualmente em torno do alvo. É uma caça solitária, na qual o dingo se desloca em relação ao líder da matilha e a um vizinho aleatório:

Nova_posição = Posição_do_líder + β₁ × e^β₂ × |Posição_do_vizinho - Posição_atual|

Exemplo: o líder está no ponto 100, o dingo atual está no ponto 60 e o vizinho está no ponto 80:

Com β₁ = 1.5, β₂ = 0.5: Nova posição = 100 + 1.5 × e^0.5 × |80 - 60| = 100 + 1.5 × 1.65 × 20 ≈ 149.5

O dingo se move seguindo o líder, mas levando em conta a distância até o vizinho.

3. Busca de carniça (probabilidade de 30%). A errância do oportunista


O sol do meio-dia queima a terra vermelha. Alguns dingos passam para o modo carniceiro, e isso não é sinal de fraqueza, mas de sabedoria evolutiva. Por que gastar energia em uma perseguição se é possível encontrar uma presa já pronta?

O dingo carniceiro escolhe um vizinho aleatório como referência, mas então ocorre um truque quântico: com probabilidade de 50%, sua própria posição é "refletida" em torno do zero (multiplicada por -1), como se ele visse seu reflexo espelhado no bebedouro. Isso gera uma distância enorme a ser usada no cálculo: a distância entre o vizinho real e o "anti-eu" fantasmagórico.

A nova posição é definida como uma parte dessa distância fantasma, ajustada pelo efeito exponencial do estado de ânimo (e^β₂). O resultado: saltos imprevisíveis pelo território, com exploração dos lugares mais inesperados. É assim que se encontram oásis escondidos e carcaças esquecidas.

Comportamento de diversificação para explorar novas regiões:

Nova_posição = 0.5 × e^β₂ × |Posição_do_vizinho ± Posição_atual|

Exemplo: posição atual = 40, vizinho = 70, β₂ = 0.3, sinal positivo:

Nova posição = 0.5 × e^0.3 × |70 - 40| = 0.5 × 1.35 × 30 ≈ 20.25

Isso cria um movimento mais aleatório para diversificar o espaço de busca.

4. Mecanismo de sobrevivência. Uma segunda chance para os que ficaram para trás


Em qualquer matilha há indivíduos que ficam para trás. Seu indicador de sobrevivência cai abaixo do limite crítico de 0.3: eles estão em posições desfavoráveis, e suas tentativas de caça fracassam. A natureza lhes dá uma chance de renascer. O dingo fraco recebe uma "injeção genética" de dois congêneres aleatórios. As posições deles, possivelmente com a inversão de uma delas (uma mutação natural), criam um vetor de variação. Esse vetor, reduzido à metade por segurança, é adicionado à posição do alfa.

A metáfora é simples: o fraco segue o forte, mas com uma dose de aleatoriedade vinda do acervo genético da matilha. Não se trata de simplesmente copiar o líder: é uma evolução controlada, na qual os que falharam recebem uma direção, mas preservam sua individualidade. Após cada iteração, calcula-se o "indicador de sobrevivência" de cada dingo:

Sobrevivência = (Pior_resultado - Resultado_atual) / (Pior - Melhor)

Se sobrevivência < 0.3 (indivíduo fraco), a posição é atualizada:

Nova_posição = Posição_do_líder + 0.5 × |Posição_dingo1 ± Posição_dingo2|

Exemplo:

Dingo fraco: posição [5, 5], fitness = 90 (ruim)
Líder: [45, 50]
Dingo r₁: [30, 35]
Dingo r₂: [25, 20]
σ = 0 (sinal positivo)

Vetor de diferença = |[30, 35] - [25, 20]| = |[5, 15]| = [5, 15]; Nova posição = [45, 50] + 0.5 × [5, 15] = [45, 50] + [2.5, 7.5] = [47.5, 57.5]

Movemos as soluções fracas para mais perto do líder, com uma pequena variação aleatória. Agora podemos resumir todas as informações em um algoritmo passo a passo:

  1. Inicialização: posicionamos 50 dingos aleatoriamente no espaço de busca
  2. Laço principal (500 iterações):
    • Para cada dingo, geramos β₁ ∈ [-2, 2] e β₂ ∈ [-1, 1]
    • Lançamos uma "moeda" com probabilidade P = 0.5:
      • Se o resultado for caça, lançamos novamente com Q = 0.7:
        • 70% de chance: ataque em grupo
        • 30% de chance: perseguição
      • Se o resultado for busca de carniça: usamos a estratégia de busca de carniça
    • Verificamos a sobrevivência e, se necessário, aplicamos o procedimento de sobrevivência
  3. Atualização: registramos a melhor solução encontrada

A ilustração abaixo representa visualmente todas as quatro estratégias do algoritmo DOA: ataque em grupo, que mostra como vários dingos formam uma posição média e se deslocam para longe do líder; perseguição, que demonstra o movimento em direção ao líder levando em conta a distância até o vizinho; busca de carniça, que ilustra a diversificação aleatória com possível inversão da posição; e sobrevivência, que mostra o deslocamento dos indivíduos fracos em direção ao líder com a adição de um vetor aleatório. Cada estratégia inclui a fórmula matemática e uma representação visual dos vetores de movimento.

doa_strategies

Figura 1. Modelagem matemática da estratégia dingo

Após a análise detalhada, passemos à implementação em código. A classe "C_AO_DOA_dingo" representa uma implementação do algoritmo de otimização DOA e deriva da classe mais geral "C_AO", o que pressupõe a presença de recursos herdados para dar suporte a algoritmos de otimização. Principais características da classe:

Parâmetros do algoritmo:
  • popSize: define o tamanho da "população" (quantidade de "dingos").
  • P: controla a probabilidade de escolha entre duas estratégias de comportamento do dingo: caça ou busca de carniça.
  • Q: define a probabilidade de ataque em grupo ou de perseguição da presa.
Configuração dos parâmetros:: o método "SetParams ()" serve para atualizar os parâmetros internos do algoritmo (popSize, P, Q) com base em dados externos armazenados no array "params".
Inicialização: o método "Init ()" é o ponto de entrada para a inicialização do algoritmo, recebendo os intervalos de valores permitidos dos parâmetros, os incrementos desses valores e o número de épocas (ciclos de funcionamento do algoritmo).
Laço principal:
  • Moving (): método que implementa a fase principal de "movimento" ou de busca de uma solução pelo algoritmo, na qual os agentes (dingos) interagem e se deslocam no espaço de busca.
  • Revision (): método responsável pela "revisão" das decisões tomadas, pela avaliação dos resultados e pelo ajuste do comportamento dos agentes.
Dados internos:
  • survival: array que armazena os indicadores de "sobrevivência" de cada agente.
  • attackVector: array usado para registrar os índices dos agentes que participam do ataque.
Métodos auxiliares (privados):
  • UpdateSurvivalRates (): atualiza os indicadores de sobrevivência dos agentes.
  • GroupAttack (): implementa a estratégia de ataque em grupo.
  • Persecution (): descreve a perseguição da presa.
  • Scavenger (): implementa o comportamento de busca de carniça.
  • SurvivalProcedure (): executa o procedimento associado à sobrevivência do agente.

De modo geral, a classe "C_AO_DOA_dingo" modela o comportamento de um grupo de dingos, usando seus instintos naturais de caça, busca de carniça e interação em grupo para resolver problemas de otimização. Ela possui um sistema flexível de parâmetros, que permite ajustar seu comportamento, e usa uma série de métodos internos para simular a dinâmica que leva à busca da solução ótima.

//————————————————————————————————————————————————————————————————————
class C_AO_DOA_dingo : public C_AO
{
  public: //----------------------------------------------------------
  ~C_AO_DOA_dingo () { }
  C_AO_DOA_dingo ()
  {
    ao_name = "DOA";
    ao_desc = "Dingo Optimization Algorithm";
    ao_link = "https://www.mql5.com/ru/articles/19458";

    popSize = 50;     // размер популяции (количество динго)
    P       = 0.5;    // вероятность охоты или поиска падали
    Q       = 0.7;    // вероятность групповой атаки или преследования

    ArrayResize (params, 3);

    params [0].name = "popSize"; params [0].val = popSize;
    params [1].name = "P";       params [1].val = P;
    params [2].name = "Q";       params [2].val = Q;
  }

  void SetParams ()
  {
    popSize = (int)params [0].val;
    P       = params [1].val;
    Q       = params [2].val;
  }

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

  void Moving   ();
  void Revision ();

  //------------------------------------------------------------------
  double P;          // вероятность охоты или поиска падали
  double Q;          // вероятность групповой атаки или преследования

  private: //---------------------------------------------------------
  double survival []; // массив показателей выживания
  int    attackVector []; // массив для хранения индексов атакующих

  // Вспомогательные методы
  void UpdateSurvivalRates ();
  void GroupAttack         (int agentIdx, int na, double beta1);
  void Persecution         (int agentIdx, double beta1, double beta2);
  void Scavenger           (int agentIdx, double beta2);
  void SurvivalProcedure   (int agentIdx);
};
//————————————————————————————————————————————————————————————————————

O método "Init" é o ponto de entrada para a inicialização do algoritmo DOA. Ele realiza as seguintes tarefas principais:

Inicialização padrão:

  • Logo na primeira linha, é chamado outro método, "StandardInit", que executa as ações comuns a todos os algoritmos de otimização para configurar os intervalos de busca dos parâmetros (rangeMinP, rangeMaxP) e os incrementos desses valores (rangeStepP).
  • Se a inicialização padrão falhar (retornar "false"), o método também interrompe sua execução.
De modo geral, o método "Init" prepara todas as estruturas de dados necessárias e define os estados iniciais para que o algoritmo possa iniciar sua operação principal de busca da solução ótima.
//————————————————————————————————————————————————————————————————————
//--- Инициализация
bool C_AO_DOA_dingo::Init (const double &rangeMinP  [],
                           const double &rangeMaxP  [],
                           const double &rangeStepP [],
                           const int     epochsP = 0)
{
  if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;

  ArrayResize     (survival, popSize);
  ArrayInitialize (survival, 1.0);

  // Резервируем максимальный размер для вектора атакующих
  ArrayResize (attackVector, popSize / 2);

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

O método "Moving" é a função principal que executa uma etapa iterativa do algoritmo. Ele modela o comportamento da população de "dingos" voltado à busca da solução ótima.

Inicialização preliminar: na primeira chamada, quando o sinalizador "revision" está definido como false, o método distribui aleatoriamente os valores de todos os parâmetros (coordenadas) de cada indivíduo da população. Os intervalos e incrementos desses parâmetros são definidos previamente. Após a inicialização, o sinalizador "revision" é definido como true, e o método encerra sua execução nesta etapa.

Avaliação da sobrevivência: se a inicialização já tiver sido realizada, o método começa chamando a sub-rotina que atualiza os indicadores de "sobrevivência" de todos os indivíduos da população. Esse indicador reflete quão bem a solução atual (posição do indivíduo) corresponde ao objetivo definido, ou seja, seu grau de fitness. Em seguida, o método percorre cada indivíduo da população.

Para o indivíduo atual, são gerados dois parâmetros aleatórios. Esses parâmetros influenciam os detalhes da estratégia de comportamento escolhida. Com base nas probabilidades definidas, o indivíduo escolhe uma das estratégias:
  • Probabilidade P: se o número aleatório for menor que "P", o indivíduo passa para a estratégia de "caça".
  • Probabilidade Q (no contexto da caça): se o indivíduo tiver escolhido "caça", com probabilidade "Q", ele aplica o "ataque em grupo". No ataque em grupo, o indivíduo se desloca levando em conta as posições de vários outros indivíduos da população. O número de outros indivíduos participantes é definido aleatoriamente dentro de um intervalo determinado.
  • Perseguição (no contexto da caça): se o indivíduo tiver escolhido "caça", mas não "ataque em grupo" (com probabilidade 1-Q), ele aplica a estratégia de "perseguição". Na perseguição, o indivíduo se desloca tomando como referência as melhores soluções e atacando a "presa".
  • Busca de carniça (alternativa à caça): se o número aleatório for maior ou igual a "P", o indivíduo escolhe a estratégia de "busca de carniça". Essa estratégia simula a busca de presas remanescentes ou a diversificação aleatória no espaço de soluções.
  • Verificação da sobrevivência e ajuste: após a aplicação da estratégia principal escolhida (caça/perseguição/busca de carniça), o método verifica o indicador de sobrevivência do indivíduo atual. Se a sobrevivência estiver abaixo de um determinado limiar (neste caso, 0.3), é aplicado um procedimento especial de "sobrevivência". Esse procedimento tem como objetivo ajudar o indivíduo fraco a melhorar seus indicadores ou sobreviver, por meio do ajuste da posição.

    Assim, o método "Moving" gerencia a evolução da população, permitindo que cada indivíduo tome decisões sobre seu comportamento, interaja com os demais e se adapte às condições, imitando o comportamento natural dos dingos.

    //————————————————————————————————————————————————————————————————————
    //--- Основной шаг алгоритма
    void C_AO_DOA_dingo::Moving ()
    {
      // Начальная инициализация популяции
      if (!revision)
      {
        for (int i = 0; i < popSize; i++)
        {
          for (int j = 0; j < coords; j++)
          {
            a [i].c [j] = u.RNDfromCI (rangeMin [j], rangeMax [j]);
            a [i].c [j] = u.SeInDiSp (a [i].c [j], rangeMin [j], rangeMax [j], rangeStep [j]);
          }
        }
        revision = true;
        return;
      }
    
      //------------------------------------------------------------------
      // Обновляем показатели выживания для всей популяции
      UpdateSurvivalRates ();
    
      // Основной цикл по всем динго
      for (int i = 0; i < popSize; i++)
      {
        // Генерируем beta для каждого агента
        double beta1 = u.RNDfromCI (-2.0, 2.0);
        double beta2 = u.RNDfromCI (-1.0, 1.0);
    
        // Сначала выбираем стратегию
        if (u.RNDprobab () < P)  // Охота
        {
          if (u.RNDprobab () < Q)  // Групповая атака
          {
            // Стратегия 1: Групповая атака (Eq. 2)
            int na = 2 + (int)((popSize / 2 - 2) * u.RNDprobab ());
            GroupAttack (i, na, beta1);
          }
          else  // Преследование
          {
            // Стратегия 2: Преследование (Eq. 3)
            Persecution (i, beta1, beta2);
          }
        }
        else  // Поиск падали
        {
          // Стратегия 3: Поиск падали (Eq. 4)
          Scavenger (i, beta2);
        }
    
        // После основной стратегии проверяем выживаемость
        if (survival [i] <= 0.3)
        {
          // Стратегия 4: Процедура выживания для слабых особей (Eq. 6)
          SurvivalProcedure (i);
        }
      }
    }
    //————————————————————————————————————————————————————————————————————

    O método seguinte, "GroupAttack", implementa uma das principais estratégias de comportamento no algoritmo: Estratégia 1, ataque em grupo. Ele modela a situação em que um grupo de dingos se une para atacar.

    Escolha dos participantes do ataque. Primeiro, o método determina quantos outros indivíduos (a quantidade dinâmica "na") participarão do ataque junto com o indivíduo atual "agentIdx". Em seguida, ele escolhe aleatoriamente "na" índices únicos de indivíduos da população inteira. Esses indivíduos selecionados formam o "grupo atacante". É importante que os indivíduos escolhidos sejam distintos, para evitar o uso repetido do mesmo indivíduo.

    Aplicação da fórmula de ataque. O método percorre cada coordenada (parâmetro) da solução "c". Para cada coordenada, ele calcula o valor médio dessa coordenada entre todos os indivíduos que fazem parte do grupo atacante. Em seguida, o método usa esse valor médio, o parâmetro "beta1" (gerado anteriormente) e o valor "cB [c]" (que representa a melhor solução conhecida no momento) para calcular um novo valor para essa coordenada do indivíduo atual "agentIdx". A fórmula de atualização da posição baseia-se na subtração, a partir da melhor solução, do produto de "beta1" pelo valor médio da coordenada dos indivíduos.

    Depois de calcular o novo valor da coordenada, ele é ajustado aos limites permitidos e ao passo de discretização, de forma semelhante ao que foi feito na inicialização.

    //————————————————————————————————————————————————————————————————————
    //--- Стратегия 1: Групповая атака (Equation 2)
    void C_AO_DOA_dingo::GroupAttack (int agentIdx, int na, double beta1)
    {
      // x_i(t+1) = beta1 * [sum(phi_k(t))/na] - x*(t)
    
      // Формируем подмножество атакующих динго
      ArrayResize (attackVector, na);
      int count = 0;
    
      while (count < na)
      {
        int idx = u.RNDintInRange (0, popSize - 1);
    
        bool unique = true;
        for (int j = 0; j < count; j++)
        {
          if (attackVector [j] == idx)
          {
            unique = false;
            break;
          }
        }
    
        if (unique)
        {
          attackVector [count++] = idx;
        }
      }
    
      // Применяем формулу
      for (int c = 0; c < coords; c++)
      {
        double sum = 0.0;
    
        for (int j = 0; j < na; j++)
        {
          sum += a [attackVector [j]].c [c];
        }
    
        //a [agentIdx].c [c] = beta1 * (sum / na) - cB [c];
        a [agentIdx].c [c] = cB [c] - beta1 * (sum / na);
        a [agentIdx].c [c] = u.SeInDiSp (a [agentIdx].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }
    //————————————————————————————————————————————————————————————————————

    O método "Persecution" (Perseguição) implementa a Estratégia 2, baseada no princípio de "perseguir" determinado objeto-alvo. Essa estratégia destina-se a atualizar a posição de um indivíduo específico da população. Primeiro, o método escolhe outro indivíduo aleatório da população. Esse indivíduo passa a ser chamado de "atacante" (r1). É importante que o indivíduo atacante não seja o próprio indivíduo que estamos atualizando, ou seja, "agentIdx" não deve coincidir com "r1".

    A estratégia "Perseguição" tenta deslocar o indivíduo-alvo (agentIdx) em uma direção definida pela combinação da melhor solução encontrada (cB) com a diferença entre outro indivíduo aleatório e o próprio indivíduo-alvo.

    • cB (melhor solução) garante que o movimento seja direcionado para a melhor solução conhecida.
    • beta1 e exp (beta2): esses parâmetros controlam a "força" ou o "alcance" do passo de perseguição. Um valor maior de "beta1" ou "beta2" levará a deslocamentos mais significativos.
    • |x_r1 (t) - x_i (t)| (diferença) define quão distante está o outro indivíduo. Quanto maior a diferença, mais forte será o efeito da perseguição.

    Assim, essa estratégia modela o comportamento em que um indivíduo (ou, mais precisamente, suas ações) tenta "alcançar" ou se aproximar de outro indivíduo aleatório, mas toda essa dinâmica é deslocada em direção à melhor solução encontrada na população.

    //————————————————————————————————————————————————————————————————————
    //--- Стратегия 2: Преследование (Equation 3)
    void C_AO_DOA_dingo::Persecution (int agentIdx, double beta1, double beta2)
    {
      // x_i(t+1) = x*(t) + beta1 * exp(beta2) * |x_r1(t) - x_i(t)|
    
      int r1;
      do
      {
        r1 = u.RNDintInRange (0, popSize - 1);
      }
      while (r1 == agentIdx);
    
      double expBeta2 = MathExp (beta2);
    
      for (int c = 0; c < coords; c++)
      {
        double diff = MathAbs (a [r1].c [c] - a [agentIdx].c [c]);
        a [agentIdx].c [c] = cB [c] + beta1 * expBeta2 * diff;
        a [agentIdx].c [c] = u.SeInDiSp (a [agentIdx].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }
    //————————————————————————————————————————————————————————————————————
    

    O método "Scavenger" descreve a Estratégia 3: Busca de carniça, imitando o comportamento de um indivíduo (dingo) que procura restos de presas. Em primeiro lugar, o método escolhe aleatoriamente outro indivíduo (r1) da população inteira. Esse indivíduo passa a ser a referência da busca. O indivíduo escolhido não pode coincidir com o indivíduo atual que executa a busca. Para determinar a direção da busca, usa-se o sinal aleatório "sigma". Esse sinal pode ser +1 ou -1 e é escolhido aleatoriamente. Isso adiciona um elemento de imprevisibilidade à direção da busca.

    Em seguida, para cada característica (coordenada) da solução, calcula-se a diferença entre o valor dessa característica no outro indivíduo e no indivíduo atual, multiplicada pelo sinal aleatório escolhido "sigma". Isso significa que a posição atual do indivíduo é somada à posição do outro indivíduo ou subtraída dela. Dessa diferença, toma-se o valor absoluto (MathAbs), para obter a magnitude da distância.

    Essa diferença absoluta é multiplicada por metade da exponencial de "beta2", parâmetro que, na forma exponencial, define a intensidade da variação da posição. O multiplicador 0.5 dimensiona esse efeito. O valor obtido como resultado da multiplicação se torna a nova coordenada do indivíduo atual. Como nos demais métodos, o novo valor da coordenada é então restringido aos limites permitidos, definidos por "rangeMin", "rangeMax" e "rangeStep".

    A estratégia "Busca de carniça" incentiva o indivíduo a se deslocar por uma distância que depende da diferença entre sua própria posição e a de outro indivíduo, e essa direção pode estar tanto "à frente" quanto "atrás" do indivíduo atual, de acordo com o sinal aleatório "sigma". A intensidade desse deslocamento também é regulada pelo parâmetro "beta2". Essa estratégia adiciona um componente de busca mais aleatório e, possivelmente, menos direcionado, modelando o comportamento em que o indivíduo pode seguir o rastro da presa ou procurar restos.

    //————————————————————————————————————————————————————————————————————
    //--- Стратегия 3: Поиск падали (Equation 4)
    void C_AO_DOA_dingo::Scavenger (int agentIdx, double beta2)
    {
      // x_i(t+1) = 0.5 * exp(beta2) * |x_r1(t) - (-1)^sigma * x_i(t)|
    
      int r1;
      do
      {
        r1 = u.RNDintInRange (0, popSize - 1);
      }
      while (r1 == agentIdx);
    
      double sigma = u.RNDbool () ? 1.0 : -1.0;
      double halfExpBeta2 = 0.5 * MathExp (beta2);
    
      for (int c = 0; c < coords; c++)
      {
        double diff = MathAbs (a [r1].c [c] - sigma * a [agentIdx].c [c]);
        a [agentIdx].c [c] = halfExpBeta2 * diff;
        a [agentIdx].c [c] = u.SeInDiSp (a [agentIdx].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }
    //————————————————————————————————————————————————————————————————————

    O método "SurvivalProcedure" descreve a Estratégia 4: procedimento de sobrevivência. Ele simula um cenário em que um indivíduo (dingo) atualiza sua posição, tentando sobreviver ou melhorar suas chances com base nas posições de outros indivíduos.

    O método escolhe dois indivíduos distintos (r1 e r2) da população, cada um deles obrigatoriamente diferente do indivíduo atual que executa o procedimento de sobrevivência (agentIdx). Além disso, esses dois indivíduos escolhidos também devem ser diferentes entre si.

    Para cada característica (coordenada), é aplicada uma mudança aleatória de sinal (sigma). Esse sinal pode ser +1 ou -1 e é escolhido aleatoriamente. Isso determina se o segundo indivíduo (r2) entra no cálculo diretamente ou com valor invertido. Para cada coordenada:

    • calcula-se a diferença entre as características correspondentes do primeiro indivíduo escolhido (a [r1].c [c]) e do segundo indivíduo (a [r2].c [c]), com a aplicação do sinal aleatório "sigma";
    • toma-se o valor absoluto dessa diferença, "diff";
    • a diferença absoluta obtida é multiplicada por 0.5;
    • metade dessa diferença é adicionada à melhor solução conhecida no momento (cB [c]). Isso significa que a nova posição do indivíduo é deslocada a partir da melhor solução, em uma direção definida pela diferença entre dois outros indivíduos. O novo valor calculado se torna a nova coordenada do indivíduo atual;
    • como nos métodos anteriores, o valor obtido para a coordenada é então ajustado para permanecer dentro dos limites permitidos.

    A estratégia "Procedimento de sobrevivência" representa um mecanismo no qual o indivíduo atualiza sua posição usando informações de dois outros indivíduos. A atualização da posição ocorre como um deslocamento a partir da melhor solução atual (cB), e a amplitude e a direção desse deslocamento dependem da diferença entre as posições de dois indivíduos aleatórios. Isso pode ser interpretado como a busca de um "nicho" ou "recurso" situado em algum ponto intermediário entre dois outros indivíduos, mas com certa aleatoriedade na definição da direção exata do movimento.

    //————————————————————————————————————————————————————————————————————
    //--- Стратегия 4: Процедура выживания (Equation 6)
    void C_AO_DOA_dingo::SurvivalProcedure (int agentIdx)
    {
      // x_i(t) = x*(t) + 0.5 * |x_r1(t) - (-1)^sigma * x_r2(t)|
    
      int r1, r2;
    
      r1 = u.RNDintInRange (0, popSize - 1);
      while (r1 == agentIdx)
      {
        r1 = u.RNDintInRange (0, popSize - 1);
      }
    
      r2 = u.RNDintInRange (0, popSize - 1);
      while (r2 == agentIdx || r2 == r1)
      {
        r2 = u.RNDintInRange (0, popSize - 1);
      }
    
      double sigma = u.RNDbool () ? 1.0 : -1.0;
    
      for (int c = 0; c < coords; c++)
      {
        double diff = MathAbs (a [r1].c [c] - sigma * a [r2].c [c]);
        a [agentIdx].c [c] = cB [c] + 0.5 * diff;
        a [agentIdx].c [c] = u.SeInDiSp (a [agentIdx].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }
    //————————————————————————————————————————————————————————————————————

    O método "UpdateSurvivalRates" é responsável por atualizar os indicadores de sobrevivência de cada indivíduo da população. Trata-se de uma etapa importante, que ajuda a determinar a probabilidade de cada indivíduo "sobreviver" e manter sua posição (ou, ao contrário, ser descartado) ao longo da evolução.

    Primeiro, o método percorre todos os indivíduos da população para determinar dois valores extremos: o fitness mínimo (minFitness) e o fitness máximo (maxFitness). Nesse caso, o primeiro indivíduo é usado como estimativa inicial para esses valores. Em seguida, calcula-se o intervalo (range) entre o fitness máximo e o mínimo. Esse intervalo reflete a variabilidade do sucesso das soluções na população atual.

    Se o intervalo de fitness for igual a zero, o que significa que todos os indivíduos têm o mesmo fitness, o indicador de sobrevivência de cada indivíduo é definido como 0.5. Nesse caso, assume-se que todos os indivíduos têm chances iguais de sobrevivência, já que não há um líder nem um indivíduo claramente desfavorecido.

    Se o intervalo de fitness não for igual a zero, calcula-se o indicador de sobrevivência de cada indivíduo (survival [i]), pela seguinte fórmula: (fitness máximo - fitness do indivíduo atual) / intervalo de fitness.

    O método normaliza o fitness de cada indivíduo em relação aos melhores e piores valores da população, transformando-o em um indicador que será usado posteriormente por outras partes do algoritmo para decidir quais indivíduos devem variar sua posição com mais intensidade e quais devem preservá-la.

    //————————————————————————————————————————————————————————————————————
    //--- Обновление показателей выживания (Equation 5)
    void C_AO_DOA_dingo::UpdateSurvivalRates ()
    {
      // survival(i) = (fitness_max - fitness(i)) / (fitness_max - fitness_min)
    
      double minFitness = a [0].f;
      double maxFitness = a [0].f;
    
      for (int i = 1; i < popSize; i++)
      {
        if (a [i].f < minFitness) minFitness = a [i].f;
        if (a [i].f > maxFitness) maxFitness = a [i].f;
      }
    
      double range = maxFitness - minFitness;
    
      if (range < DBL_EPSILON)
      {
        ArrayInitialize (survival, 0.5);
      }
      else
      {
        for (int i = 0; i < popSize; i++)
        {
          survival [i] = (maxFitness - a [i].f) / range;
        }
      }
    }
    //————————————————————————————————————————————————————————————————————

    O método "Revision" é crucial para a maioria dos algoritmos heurísticos de otimização. Sua tarefa é preservar a melhor solução encontrada até este momento (ou em qualquer momento anterior). Isso garante que o algoritmo não "esqueça" uma boa solução, mesmo que outros indivíduos continuem evoluindo e talvez encontrem soluções que, temporariamente, pareçam menos bem-sucedidas. Assim, "fB" e "cB" sempre armazenam o melhor valor de fitness encontrado e suas coordenadas correspondentes.

    //————————————————————————————————————————————————————————————————————
    //--- Обновление лучшего решения
    void C_AO_DOA_dingo::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);
        }
      }
    }
    //————————————————————————————————————————————————————————————————————

    Depois de implementar um método de otimização tão promissor e versátil, finalmente podemos passar aos testes.


    Resultados dos testes

    De acordo com os resultados dos testes, o algoritmo obtém 35% dos 100% possíveis; infelizmente, as expectativas não foram totalmente atendidas.

    DOA|Dingo Optimization Algorithm|50.0|0.5|0.7|
    =============================
    5 Hilly's; Func runs: 10000; result: 0.49066480903390775
    25 Hilly's; Func runs: 10000; result: 0.399914179876301
    500 Hilly's; Func runs: 10000; result: 0.35798310869836164
    =============================
    5 Forest's; Func runs: 10000; result: 0.29643143556801427
    25 Forest's; Func runs: 10000; result: 0.20458050042664944
    500 Forest's; Func runs: 10000; result: 0.17091405461356773
    =============================
    5 Megacity's; Func runs: 10000; result: 0.36615384615384616
    25 Megacity's; Func runs: 10000; result: 0.4489230769230771
    500 Megacity's; Func runs: 10000; result: 0.45393846153845924
    =============================
    All score: 3.18950 (35.44%)

    Na visualização, é possível observar, pelo padrão complexo de movimento dos agentes, como as estratégias do algoritmo se alternam. De modo geral, a estranha distribuição dos agentes pela "diagonal" do espaço de busca indica um possível erro cometido pelos autores na lógica interna do algoritmo.

    Hilly

    DOA_dingo na função de teste Hilly

    Forest

    DOA_dingo na função de teste Forest

    Megacity

    DOA_dingo na função de teste Megacity

    Na tabela de classificação, o algoritmo DOA_dingo é apresentado após os testes realizados apenas para fins informativos.

    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)
    1 ANS across neighbourhood search 0,94948 0,84776 0,43857 2,23581 1,00000 0,92334 0,39988 2,32323 0,70923 0,63477 0,23091 1,57491 6,134 68,15
    2 CLA code lock algorithm (joo) 0,95345 0,87107 0,37590 2,20042 0,98942 0,91709 0,31642 2,22294 0,79692 0,69385 0,19303 1,68380 6,107 67,86
    3 AMOm animal migration ptimization M 0,90358 0,84317 0,46284 2,20959 0,99001 0,92436 0,46598 2,38034 0,56769 0,59132 0,23773 1,39675 5,987 66,52
    4 (P+O)ES (P+O) evolution strategies 0,92256 0,88101 0,40021 2,20379 0,97750 0,87490 0,31945 2,17185 0,67385 0,62985 0,18634 1,49003 5,866 65,17
    5 CTA comet tail algorithm (joo) 0,95346 0,86319 0,27770 2,09435 0,99794 0,85740 0,33949 2,19484 0,88769 0,56431 0,10512 1,55712 5,846 64,96
    6 TETA time evolution travel algorithm (joo) 0,91362 0,82349 0,31990 2,05701 0,97096 0,89532 0,29324 2,15952 0,73462 0,68569 0,16021 1,58052 5,797 64,41
    7 SDSm stochastic diffusion search M 0,93066 0,85445 0,39476 2,17988 0,99983 0,89244 0,19619 2,08846 0,72333 0,61100 0,10670 1,44103 5,709 63,44
    8 BOAm billiards optimization algorithm M 0,95757 0,82599 0,25235 2,03590 1,00000 0,90036 0,30502 2,20538 0,73538 0,52523 0,09563 1,35625 5,598 62,19
    9 AAm archery algorithm M 0,91744 0,70876 0,42160 2,04780 0,92527 0,75802 0,35328 2,03657 0,67385 0,55200 0,23738 1,46323 5,548 61,64
    10 ESG evolution of social groups (joo) 0,99906 0,79654 0,35056 2,14616 1,00000 0,82863 0,13102 1,95965 0,82333 0,55300 0,04725 1,42358 5,529 61,44
    11 SIA simulated isotropic annealing (joo) 0,95784 0,84264 0,41465 2,21513 0,98239 0,79586 0,20507 1,98332 0,68667 0,49300 0,09053 1,27020 5,469 60,76
    12 EOm extremal_optimization_M 0,76166 0,77242 0,31747 1,85155 0,99999 0,76751 0,23527 2,00277 0,74769 0,53969 0,14249 1,42987 5,284 58,71
    13 BBO biogeography based optimization 0,94912 0,69456 0,35031 1,99399 0,93820 0,67365 0,25682 1,86867 0,74615 0,48277 0,17369 1,40261 5,265 58,50
    14 ACS artificial cooperative search 0,75547 0,74744 0,30407 1,80698 1,00000 0,88861 0,22413 2,11274 0,69077 0,48185 0,13322 1,30583 5,226 58,06
    15 DA dialectical algorithm 0,86183 0,70033 0,33724 1,89940 0,98163 0,72772 0,28718 1,99653 0,70308 0,45292 0,16367 1,31967 5,216 57,95
    16 BHAm black hole algorithm M 0,75236 0,76675 0,34583 1,86493 0,93593 0,80152 0,27177 2,00923 0,65077 0,51646 0,15472 1,32195 5,196 57,73
    17 ASO anarchy society optimization 0,84872 0,74646 0,31465 1,90983 0,96148 0,79150 0,23803 1,99101 0,57077 0,54062 0,16614 1,27752 5,178 57,54
    18 RFO royal flush optimization (joo) 0,83361 0,73742 0,34629 1,91733 0,89424 0,73824 0,24098 1,87346 0,63154 0,50292 0,16421 1,29867 5,089 56,55
    19 AOSm atomic orbital search M 0,80232 0,70449 0,31021 1,81702 0,85660 0,69451 0,21996 1,77107 0,74615 0,52862 0,14358 1,41835 5,006 55,63
    20 TSEA turtle shell evolution algorithm (joo) 0,96798 0,64480 0,29672 1,90949 0,99449 0,61981 0,22708 1,84139 0,69077 0,42646 0,13598 1,25322 5,004 55,60
    21 BSA backtracking_search_algorithm 0,97309 0,54534 0,29098 1,80941 0,99999 0,58543 0,21747 1,80289 0,84769 0,36953 0,12978 1,34700 4,959 55,10
    22 DE differential evolution 0,95044 0,61674 0,30308 1,87026 0,95317 0,78896 0,16652 1,90865 0,78667 0,36033 0,02953 1,17653 4,955 55,06
    23 SRA successful restaurateur algorithm (joo) 0,96883 0,63455 0,29217 1,89555 0,94637 0,55506 0,19124 1,69267 0,74923 0,44031 0,12526 1,31480 4,903 54,48
    24 CRO chemical reaction optimisation 0,94629 0,66112 0,29853 1,90593 0,87906 0,58422 0,21146 1,67473 0,75846 0,42646 0,12686 1,31178 4,892 54,36
    25 BIO blood inheritance optimization (joo) 0,81568 0,65336 0,30877 1,77781 0,89937 0,65319 0,21760 1,77016 0,67846 0,47631 0,13902 1,29378 4,842 53,80
    26 DOA dream_optimization_algorithm 0,85556 0,70085 0,37280 1,92921 0,73421 0,48905 0,24147 1,46473 0,77231 0,47354 0,18561 1,43146 4,825 53,62
    27 BSA bird swarm algorithm 0,89306 0,64900 0,26250 1,80455 0,92420 0,71121 0,24939 1,88479 0,69385 0,32615 0,10012 1,12012 4,809 53,44
    28 DEA dolphin_echolocation_algorithm 0,75995 0,67572 0,34171 1,77738 0,89582 0,64223 0,23941 1,77746 0,61538 0,44031 0,15115 1,20684 4,762 52,91
    29 HS harmony search 0,86509 0,68782 0,32527 1,87818 0,99999 0,68002 0,09590 1,77592 0,62000 0,42267 0,05458 1,09725 4,751 52,79
    30 SSG saplings sowing and growing 0,77839 0,64925 0,39543 1,82308 0,85973 0,62467 0,17429 1,65869 0,64667 0,44133 0,10598 1,19398 4,676 51,95
    31 BCOm bacterial chemotaxis optimization M 0,75953 0,62268 0,31483 1,69704 0,89378 0,61339 0,22542 1,73259 0,65385 0,42092 0,14435 1,21912 4,649 51,65
    32 ABO african buffalo optimization 0,83337 0,62247 0,29964 1,75548 0,92170 0,58618 0,19723 1,70511 0,61000 0,43154 0,13225 1,17378 4,634 51,49
    33 (PO)ES (PO) evolution strategies 0,79025 0,62647 0,42935 1,84606 0,87616 0,60943 0,19591 1,68151 0,59000 0,37933 0,11322 1,08255 4,610 51,22
    34 FBA fractal-based Algorithm 0,79000 0,65134 0,28965 1,73099 0,87158 0,56823 0,18877 1,62858 0,61077 0,46062 0,12398 1,19537 4,555 50,61
    35 TSm tabu search M 0,87795 0,61431 0,29104 1,78330 0,92885 0,51844 0,19054 1,63783 0,61077 0,38215 0,12157 1,11449 4,536 50,40
    36 BSO brain storm optimization 0,93736 0,57616 0,29688 1,81041 0,93131 0,55866 0,23537 1,72534 0,55231 0,29077 0,11914 0,96222 4,498 49,98
    37 WOAm wale optimization algorithm M 0,84521 0,56298 0,26263 1,67081 0,93100 0,52278 0,16365 1,61743 0,66308 0,41138 0,11357 1,18803 4,476 49,74
    38 AEFA artificial electric field algorithm 0,87700 0,61753 0,25235 1,74688 0,92729 0,72698 0,18064 1,83490 0,66615 0,11631 0,09508 0,87754 4,459 49,55
    39 AEO artificial ecosystem-based optimization algorithm 0,91380 0,46713 0,26470 1,64563 0,90223 0,43705 0,21400 1,55327 0,66154 0,30800 0,28563 1,25517 4,454 49,49
    40 CAm camel algorithm M 0,78684 0,56042 0,35133 1,69859 0,82772 0,56041 0,24336 1,63149 0,64846 0,33092 0,13418 1,11356 4,444 49,37
    41 ACOm ant colony optimization M 0,88190 0,66127 0,30377 1,84693 0,85873 0,58680 0,15051 1,59604 0,59667 0,37333 0,02472 0,99472 4,438 49,31
    42 CMAES covariance_matrix_adaptation_evolution_strategy 0,76258 0,72089 0,00000 1,48347 0,82056 0,79616 0,00000 1,61672 0,75846 0,49077 0,00000 1,24923 4,349 48,33
    43 DA_duelist duelist_algorithm 0,92782 0,53778 0,27792 1,74352 0,86957 0,47536 0,18193 1,52686 0,62153 0,33569 0,11715 1,07437 4,345 48,28
    44 BFO-GA bacterial foraging optimization - ga 0,89150 0,55111 0,31529 1,75790 0,96982 0,39612 0,06305 1,42899 0,72667 0,27500 0,03525 1,03692 4,224 46,93
    45 SOA simple optimization algorithm 0,91520 0,46976 0,27089 1,65585 0,89675 0,37401 0,16984 1,44060 0,69538 0,28031 0,10852 1,08422 4,181 46,45

    DOA_dingo dingo_optimization_algorithm 0,49066 0,39991 0,35798 1,24855 0,29643 0,20458 0,17091 0,67192 0,36615 0,44892 0,45394 1,26901 3,189 35,44

    RW random walk 0,48754 0,32159 0,25781 1,06694 0,37554 0,21944 0,15877 0,75375 0,27969 0,14917 0,09847 0,52734 2,348 26,09


    Conclusões

    Neste artigo, analisamos um algoritmo de otimização interessante, notável pelas abordagens que utiliza. À primeira vista, o algoritmo pode parecer não ser a melhor forma de buscar a solução ótima. No entanto, em numerosos experimentos, surgiu um potencial inesperado: com o devido refinamento das ideias presentes no DOA, o algoritmo é capaz de apresentar resultados bastante sólidos, no nível dos melhores métodos populacionais.

    O que exatamente foi descoberto? Falaremos sobre isso no próximo artigo. Além disso, um pequeno presente aguarda os amantes da otimização mais atentos: no arquivo, é possível encontrar uma pequena modificação no código do algoritmo que já afetou significativamente os resultados do algoritmo. Deixe sua opinião nos comentários. 

    tab

    Figura 2. Gradação de cores dos algoritmos nos testes correspondentes

    chart

    Figura 3. Histograma dos resultados dos testes dos algoritmos (em uma escala de 0 a 100, quanto maior, melhor, onde 100 é o resultado teórico máximo possível; no arquivo há um script para calcular a tabela de classificação)

    Pontos fortes e fracos do algoritmo DOA_dingo:

    Pontos fortes:

    1. Rápido.

    Pontos fracos:

    1. Alta variação nos resultados.
    2. Baixa diversificação do espaço de busca.

    Foi anexado ao artigo um arquivo com as versões atualizadas dos códigos dos algoritmos. O autor do artigo não se responsabiliza pela precisão absoluta na descrição dos algoritmos canônicos, pois muitos deles foram modificados para melhorar sua capacidade de busca. As conclusões e avaliações apresentadas nos artigos baseiam-se nos resultados dos experimentos realizados.


    Programas utilizados no artigo

    # Nome Tipo Descrição
    1 #C_AO.mqh
    Arquivo de inclusão
    Classe base dos algoritmos populacionais de otimização
    2 #C_AO_enum.mqh
    Arquivo de inclusão
    Enumeração dos algoritmos populacionais de otimização
    3 TestFunctions.mqh
    Arquivo de inclusão
    Biblioteca de funções de teste
    4
    TestStandFunctions.mqh
    Arquivo de inclusão
    Biblioteca de funções da bancada de testes
    5
    Utilities.mqh
    Arquivo de inclusão
    Biblioteca de funções auxiliares
    6
    CalculationTestResults.mqh
    Arquivo de inclusão
    Script para calcular os resultados da tabela comparativa
    7
    Testing AOs.mq5
    Script Bancada de testes unificada para todos os algoritmos populacionais de otimização
    8
    Simple use of population optimization algorithms.mq5
    Script
    Exemplo simples de uso de algoritmos populacionais de otimização sem visualização
    9
    Test_AO_DOA_dingo.mq5
    Script Bancada de testes para o DOA_dingo

    Traduzido do russo pela MetaQuotes Ltd.
    Artigo original: https://www.mql5.com/ru/articles/19458

    Arquivos anexados |
    DOA_Dingo.ZIP (340.02 KB)
    Redes neurais no trading: uma visão unificada sobre espaço e tempo (Global-Local Attention) Redes neurais no trading: uma visão unificada sobre espaço e tempo (Global-Local Attention)
    Continuamos a trabalhar na implementação das abordagens propostas pelos autores do framework Extralonger. Desta vez, vamos nos concentrar na implementação do módulo Global-Local Spatial Attention em MQL5, examinando tanto sua estrutura quanto sua integração prática ao fluxo computacional geral.
    Introdução ao MQL5 (Parte 15): Criando Indicadores Personalizados com MQL5 — Guia para Iniciantes (IV) Introdução ao MQL5 (Parte 15): Criando Indicadores Personalizados com MQL5 — Guia para Iniciantes (IV)
    Neste artigo, você aprenderá a criar um indicador de Price Action em MQL5, com foco em pontos-chave como mínima (L), máxima (H), mínima mais alta (HL), máxima mais alta (HH), mínima mais baixa (LL) e máxima mais baixa (LH) para análise de tendências. Você também aprenderá a identificar as zonas de prêmio e desconto, marcar o nível de retração de 50% e utilizar a relação risco-retorno para calcular metas de lucro. O artigo aborda a determinação dos pontos de entrada, stop loss (SL) e take profit (TP) com base na estrutura da tendência.
    Criando um Painel de Administração de Trading em MQL5 (Parte IX): Organização do Código (V): Classe AnalyticsPanel Criando um Painel de Administração de Trading em MQL5 (Parte IX): Organização do Código (V): Classe AnalyticsPanel
    Nesta discussão, exploramos como recuperar dados de mercado em tempo real e informações da conta de negociação, realizar diversos cálculos e exibir os resultados em um painel personalizado. Para alcançar esse objetivo, vamos nos aprofundar no desenvolvimento de uma classe AnalyticsPanel que encapsula todos esses recursos, incluindo a criação do painel. Este trabalho faz parte da nossa expansão contínua do EA New Admin Panel, introduzindo funcionalidades avançadas utilizando princípios de design modular e boas práticas de organização de código.
    Arbitragem Estatística via Reversão à Média no Trading de Pares: Superando o Mercado com Matemática Arbitragem Estatística via Reversão à Média no Trading de Pares: Superando o Mercado com Matemática
    Este artigo descreve os fundamentos da arbitragem estatística em nível de portfólio. Seu objetivo é facilitar a compreensão dos princípios da arbitragem estatística para leitores sem conhecimentos aprofundados em matemática e propor uma estrutura conceitual inicial. O artigo inclui um Expert Advisor funcional, algumas observações sobre seu backtest de um ano e as respectivas configurações do backtest (arquivo .ini) para a reprodução do experimento.