English Русский Español Português
preview
Modifikation des Dingo-Optimierungsalgorithmus (DOAm)

Modifikation des Dingo-Optimierungsalgorithmus (DOAm)

MetaTrader 5 — Handelssysteme |
18 2
Andrey Dik
Andrey Dik

Inhaltsverzeichnis

  1. Einleitung
  2. Implementierung des Algorithmus
  3. Testergebnisse


Einleitung

Fragen wir uns einmal: Gibt es populationsbasierte metaheuristische Algorithmen, die mit einer begrenzten Anzahl von Iterationen – in unserem Fall 10.000 – ein Ergebnis von 100 % erzielen können? Die Leistungsfähigkeit eines solchen Algorithmus müsste ziemlich überwältigend sein. Tatsächlich bezweifle ich manchmal, dass es überhaupt möglich ist, im Bereich der Optimierung einen solchen Schatz zu entdecken.

Es mag solche Algorithmen für diesen Zweck geben, und heute werden wir eine der einzigartigen Optimierungsmethoden kennenlernen – genauer gesagt eine modifizierte Version des Dingo-Optimierungsalgorithmus, den ich bereits im vorherigen Artikel beschrieben habe. Diese Version bringt uns der Lösung einer solch schwierigen Aufgabe einen Schritt näher.


Implementierung des Algorithmus

Während meiner Arbeit am Dingo-Optimierungsalgorithmus begann ich mich für das Prinzip der Modellierung der Dingo-Jagd zu interessieren, bei der verschiedene Strategien zum Einsatz kommen. Wir haben uns mit diesem Algorithmus vertraut gemacht und seine Funktionsweise im Detail analysiert. Der Test des Algorithmus lieferte durchschnittliche Ergebnisse; er schaffte es nicht in die Rangliste, da er die Aufnahmeschwelle noch um 20 % verfehlte. Man könnte meinen, wir könnten das Thema ad acta legen und weitermachen. Ich habe mich jedoch entschlossen, ein wenig mit den Formeln zu experimentieren, und das ist dabei herausgekommen:

Formel für den Gruppenangriff (Gleichung 2), Originalfassung:

x⃗ᵢ(t+1) = β₁ · [Σₖ₌₁ⁿᵃ φ⃗ₖ(t)]/nₐ - x⃗*(t)

sieht nun so aus:

a[agentIdx].c[c] = cB[c] + beta1 * sumAttack;

Wie Sie sehen können, wurde das Vorzeichen geändert – statt die beste Lösung zu subtrahieren, verwenden wir nun die Addition. Außerdem ist die Berechnung von „sumAttack“ komplizierter – der Wert wird durch (na * coords) geteilt, statt einfach nur durch „na“.

Die Überlebensschwelle in der Originalversion lautet survival[r] <= 0.3; ändern wir sie auf survival[r] <= 0.01. Wir senken die Schwelle deutlich, was bedeutet, dass wir Überlebensstrategien nur auf die „schwächsten“ Agenten anwenden werden.

Die ursprüngliche Formel für die Aassuche (Gleichung 4):

x⃗ᵢ(t+1) = ½ · e^β₂ · |x⃗ᵣ₁(t) - (-1)^σ · x⃗ᵢ(t)|

Neue Version:

a[agentIdx].c[c] = (MathExp(beta2) * a[r1].c[c] - sign * a[agentIdx].c[c]) / 2.0;

Nun entfällt der Absolutbetrag, sodass negative Koordinaten möglich sind. Zudem führt der modifizierte Algorithmus die Mittelwertbildung der Positionsdifferenz gleichzeitig über alle Koordinaten durch statt für jede Koordinate einzeln.

Warum könnten diese Änderungen die Leistung des Algorithmus verbessern? Ein Vorzeichenwechsel beim Gruppenangriff kann eine Bewegung „hin zu einer besseren Lösung unter Berücksichtigung der Positionen der anderen“ bewirken, statt einer Bewegung weg von der besten Lösung wie in der Version der Autoren. Die Senkung der Überlebensschwelle ermöglicht es den meisten Agenten, grundlegende Jagdstrategien anzuwenden und nur in Extremfällen auf die Überlebensprozedur zurückzugreifen. Der Verzicht auf den Absolutbetrag in der Formel für die Aassuche ermöglicht eine freiere Bewegung im Suchraum.

DOA_M

Abbildung 1. Änderungen an der DOAm_dingo-Strategie

Die obige Abbildung zeigt die wesentlichen Unterschiede zwischen der modifizierten Version und der von den Autoren des Algorithmus beschriebenen Originalversion: Bei einem Gruppenangriff erfolgt die Bewegung auf einen Anführer zu statt von ihm weg. Die Überlebensschwelle wird auf 0,01 gesenkt, die Aassuche erfolgt nun ohne Absolutbetrag in der Formel, und bei der Mittelwertbildung wird durch (na × coords) statt nur durch (na) geteilt. Änderungen sind zur besseren Übersichtlichkeit rot markiert.

Kommen wir nun zur Beschreibung des Algorithmus-Codes und schauen wir uns das Ergebnis an. Die Klasse „C_AO_DOAm_dingo“ ist eine spezialisierte Version der Basisklasse „C_AO“. Es handelt sich um einen Optimierungsalgorithmus, der auf der Modifizierung des Verhaltens von Dingos basiert. Daher erbt die Klasse „Dingo-Optimierungsalgorithmus M“ von C_AO, was bedeutet, dass sie über die grundlegenden Funktionen verfügt. Für die Schlüsselparameter sind folgende Standardwerte festgelegt:

  • popSize (Populationsgröße, d. h. Anzahl der Dingos): 50.
  • P (Wahrscheinlichkeit für die Wahl zwischen Jagd und Aassuche): 0,5.
  • Q (Wahrscheinlichkeit, zwischen Gruppenangriff und Verfolgung zu wählen): 0,7.
Das Array „params“ wird zur Speicherung von Parametern und deren Werten vorbereitet, wobei die Anfangswerte entsprechend popSize, P und Q festgelegt werden. Mit der Methode „SetParams“ können wir die Parameterwerte (popSize, P, Q) aus einer externen Quelle (aus dem Array „params“) aktualisieren. Die Methoden „Init“, „Moving“ und „Revision“ sind in der Basisklasse C_AO definiert und werden hier überschrieben, um die spezifische Logik des Algorithmus zu implementieren.
  • Init – erstmaliger Start des Algorithmus, einschließlich der Initialisierung der Agenten (Dingos) und ihrer Parameter unter Verwendung der vorgegebenen Bereiche und Schrittweiten.
  • Moving – die Hauptphase des Algorithmus, in der sich die Agenten gemäß den Regeln des Algorithmus bewegen und miteinander interagieren.
  • Revision – Überprüfung oder Bewertung des Zustands des Algorithmus nach einer bestimmten Phase oder Epoche.
Öffentliche Membervariablen:
  • P – Wahrscheinlichkeit, dass ein Dingo jagt oder nach Aas sucht.
  • Q – Wahrscheinlichkeit, dass ein Dingo an einem Gruppenangriff oder einer Verfolgung teilnimmt.
Private Membervariablen:
  • beta1, beta2 – dienen zur Erzeugung von Zufallsvektoren oder Schritten bei der Optimierung innerhalb vorgegebener Wertebereiche;
  • naIni, naEnd — legen die minimale und maximale Anzahl der am Angriff beteiligten Dingos fest, die variieren kann;
  • survival — Array, in dem die „Überlebens“- bzw. Fitnessindikatoren jedes Dingos gespeichert sind.
Private Hilfsmethoden: Diese Methoden implementieren die interne Logik des Dingo-Algorithmus:
  • UpdateSurvivalRates — Aktualisierung der Überlebensraten der Agenten;
  • GroupAttack — Implementierung des Verhaltens bei Gruppenangriffen;
  • Persecution – Implementierung des Verhaltens bei der Verfolgung;
  • Scavenger – Implementierung des Verhaltens bei der Aassuche;
  • SurvivalProcedure – Prozedur im Zusammenhang mit dem Überleben der Agenten;
  • GetAttackVector — Abrufen eines Vektors, der die Angriffsrichtung bestimmt;
  • CalculateAttackSum – berechnet die gesamte „Wirkung“ des Angriffs.
//————————————————————————————————————————————————————————————————————
class C_AO_DOAm_dingo : public C_AO
{
  public: //----------------------------------------------------------
  ~C_AO_DOAm_dingo () { } 
  C_AO_DOAm_dingo ()
  {
    ao_name = "DOAm";
    ao_desc = "Dingo Optimization Algorithm M";
    ao_link = "https://www.mql5.com/en/articles/19187";

    popSize = 50;     // population size (number of dingoes)
    P       = 0.5;    // Hunting or Scavenger rate
    Q       = 0.7;    // Group attack or chase

    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  [],  // minimum values
             const double &rangeMaxP  [],  // maximum values
             const double &rangeStepP [],  // step change
             const int     epochsP = 0);   // number of epochs

  void Moving   ();
  void Revision ();

  //------------------------------------------------------------------
  double P;          // hunting or scavenging probability
  double Q;          // group attack or chase probability

  private: //---------------------------------------------------------
  double beta1;       // -2 < beta1 < 2
  double beta2;       // -1 < beta2 < 1
  int    naIni;       // minimum number of attacking dingoes
  int    naEnd;       // maximum number of attacking dingoes
  double survival []; // array of survival indicators

  // Auxiliary methods
  void   UpdateSurvivalRates ();
  void   GroupAttack         (int agentIdx, int na);
  void   Persecution         (int agentIdx);
  void   Scavenger           (int agentIdx);
  void   SurvivalProcedure   (int agentIdx);
  void   GetAttackVector     (int na, int &attackVector []);
  double CalculateAttackSum  (int agentIdx, int na);
};
//————————————————————————————————————————————————————————————————————

Diese Methode dient zur Initialisierung des Dingo-Optimierungsalgorithmus M. Sie bereitet den Algorithmus auf den Betrieb vor, indem sie die Anfangsbedingungen für die Optimierung festlegt, bestimmt, wie die Dingos Angriffsgruppen bilden, und ihren anfänglichen „Überlebenszustand“ festlegt.

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

  //------------------------------------------------------------------
  // Initialize algorithm parameters
  naIni = 2;               // minimum number of attackers
  naEnd = popSize / naIni; // maximum number of attackers

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

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

Die „Moving“-Methode ist die Hauptfunktion, die für die Ausführung eines Schritts (oder einer Iteration) des Algorithmus zuständig ist; sie simuliert das Verhalten eines Dingo-Rudels bei der Suche nach der optimalen Lösung. Die Methode steuert das Verhalten der Dingo-Population dynamisch und ermöglicht es ihr, den Lösungsraum mithilfe verschiedener Strategien zu erkunden, die auf ihrer Überlebensrate („survival“) und probabilistischen Entscheidungen beruhen. Eine ausführlichere Beschreibung der wichtigsten Methoden wurde im vorherigen Artikel gegeben. Hier werden wir uns die für diese Implementierung spezifischen Methoden genauer ansehen.

//————————————————————————————————————————————————————————————————————
//--- Main step of the algorithm
void C_AO_DOAm_dingo::Moving ()
{
  // Starting initialization of the population
  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;
  }

  //------------------------------------------------------------------
  // Update survival rates
  UpdateSurvivalRates ();

  // Update beta parameters for the current iteration
  //beta1 = -2.0 + 4.0 * u.RNDprobab ();
  //beta2 = -1.0 + 2.0 * u.RNDprobab ();
  beta1 = u.RNDfromCI (-2.0, 2.0);
  beta2 = u.RNDfromCI (-1.0, 1.0);

  // Main loop for all dingoes
  for (int r = 0; r < popSize; r++)
  {
    // Check the survival rate (Section 2.2.4)
    //if (survival[r] <= 0.3)
    if (survival [r] <= 0.01)
    {
      // Strategy 4: Survival (Eq. 6)
      SurvivalProcedure (r);
    }
    else
    {
      // Choose between hunting and scavenging
      if (u.RNDprobab () < P)  // If hunting
      {
        if (u.RNDprobab () < Q)  // If group attack
        {
          // Strategy 1: Group attack (Eq. 2)
          int na = naIni + (int)((naEnd - naIni) * u.RNDprobab ());
          GroupAttack (r, na);
        }
        else  // Chase
        {
          // Strategy 2: Chase (Eq. 3)
          Persecution (r);
        }
      }
      else  // Scavenging
      {
        // Strategy 3: Scavenging (Eq. 4)
        Scavenger (r);
      }
    }
  }
}
//————————————————————————————————————————————————————————————————————

Die Methode „GroupAttack“ implementiert „Strategie 1: Gruppenangriff“. Diese Strategie kommt zum Einsatz, wenn ein Dingo beschließt, als Teil einer Gruppe ein Beutetier anzugreifen. Zunächst wird die Hilfsmethode „CalculateAttackSum“ aufgerufen. Sie nimmt den Index des aktuellen Dingos (agentIdx) und die Anzahl der am Angriff beteiligten Dingos (na) als Eingabewerte und berechnet die Gesamtstärke bzw. -richtung des Angriffs, indem sie die Beiträge aller Teilnehmer addiert. Das Ergebnis dieser komplexen Operation wird in der Variablen „sumAttack“ gespeichert.

Anschließend aktualisiert die Methode die Position (Koordinaten) des aktuellen Dingos. Die Methode durchläuft nacheinander jede Koordinate c des Suchraums und berechnet einen neuen Wert für die Position des Dingos. Die aktualisierte Formel lautet wie folgt:

Neue Koordinate = Koordinate der besten Lösung + beta1 * gesamter Angriffsvektor

wobei:

  • cB [c] bezeichnet die c-te Koordinate der derzeit besten Lösung, die bei der Optimierung gefunden wurde,
  • beta1 — Koeffizient, der die Intensität oder Richtung der Wirkung des Gruppenangriffs regelt,
  • sumAttack — im vorherigen Schritt ermitteltes Ergebnis.

Der so ermittelte neue Koordinatenwert wird dann in den zulässigen Bereich „eingepasst“. Die u.SeInDiSp-Methode stellt sicher, dass der neue Wert innerhalb der festgelegten Mindest- (rangeMin) und Höchstgrenzen (rangeMax) bleibt, wobei die Schrittweite (rangeStep) der Änderung berücksichtigt wird.

Letztlich bildet die „GroupAttack“-Methode eine koordinierte Suche nach einer optimalen Lösung durch eine Gruppe von Dingos ab. Sie fasst Informationen von mehreren Individuen über „sumAttack“ zusammen, berücksichtigt die beste gefundene Lösung (cB) und ermittelt anhand eines zufälligen Koeffizienten beta1 eine neue, potenziell vorteilhaftere Position für den Dingo im Suchraum.

//————————————————————————————————————————————————————————————————————
//--- Strategy 1: Group attack (Eq. 2)
void C_AO_DOAm_dingo::GroupAttack (int agentIdx, int na)
{
  // Calculate the total attack vector
  double sumAttack = CalculateAttackSum (agentIdx, na);

  // Apply the group attack formula (Eq. 2)
  for (int c = 0; c < coords; c++)
  {
    // v = beta1 * sumatory - theBestVct
    a [agentIdx].c [c] = cB [c] + beta1 * sumAttack;
    a [agentIdx].c [c] = u.SeInDiSp (a [agentIdx].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
  }
}
//————————————————————————————————————————————————————————————————————

Die Methode „CalculateAttackSum“ dient zur Berechnung des gesamten Angriffsvektors, der in „Strategie 1: Gruppenangriff“ verwendet wird. Sie legt fest, wie ein bestimmter Dingo (agentIdx) mit anderen Dingos interagiert, die an einem Gruppenangriff (na) teilnehmen.

Zunächst erstellt die Methode eine temporäre Liste (attackVector), die die Indizes der direkt am Angriff beteiligten Dingos enthält. Die Größe dieser Liste wird durch den Parameter „na“ (Anzahl der Angreifer) bestimmt. Anschließend wird die Hilfsmethode „GetAttackVector“ aufgerufen. Diese Methode wählt auf der Grundlage des aktuellen Zustands der Population „na“ Dingos aus, die an dem Angriff teilnehmen sollen, und schreibt deren Indizes in den „attackVector“. Die Variable „sumatory“ wird mit null initialisiert. Als Nächstes folgt die Hauptschleife, die alle am Angriff beteiligten Dingos durchläuft; dabei wird der Index (attackerIdx) jedes angreifenden Dingos aus attackVector entnommen.

Innerhalb dieser Schleife befindet sich eine weitere Schleife, die alle Koordinaten (c) des Suchraums durchläuft (Schleife: von „0“ bis „coords - 1“). An jeder Koordinate wird die Differenz zwischen der Position des angreifenden Dingos und der Position des Dingos, für den der Gesamtangriff berechnet wird, bestimmt. Diese Differenz wird dann durch die Gesamtzahl der möglichen Angriffsteilnehmer (na) und die Gesamtzahl der Koordinaten (coords) geteilt und zu „sumatory“ addiert.

Schließlich gibt die Methode den Wert von „sumatory“ zurück. Dieser Wert gibt die durchschnittliche Positionsdifferenz zwischen den angreifenden Dingos und dem Ziel-Dingo unter Berücksichtigung der Anzahl der Teilnehmer und der Dimensionen an. Dieser Wert wird dann verwendet, um die Position des Ziel-Dingos im Rahmen eines Gruppenangriffs zu aktualisieren.

Somit sammelt „CalculateAttackSum“ Informationen über die aktuellen Positionen der an einem gemeinsamen Angriff beteiligten Dingos und gibt einen zusammengesetzten Wert aus, der deren gesamte Verschiebung relativ zum angegriffenen Dingo widerspiegelt. Dieser Wert bestimmt dann die Bewegung des angegriffenen Dingos.

//————————————————————————————————————————————————————————————————————
//--- Calculate the sum for a group attack
double C_AO_DOAm_dingo::CalculateAttackSum (int agentIdx, int na)
{
  // Create a vector of attacking dingoes
  int attackVector [];
  ArrayResize (attackVector, na);
  GetAttackVector (na, attackVector);

  // Calculate the average difference in positions
  double sumatory = 0.0;
  for (int j = 0; j < na; j++)
  {
    int attackerIdx = attackVector [j];
    // Calculate the average over all coordinates
    for (int c = 0; c < coords; c++)
    {
      sumatory += (a [attackerIdx].c [c] - a [agentIdx].c [c]) / (na * coords);
    }
  }

  return sumatory;
}
//————————————————————————————————————————————————————————————————————

Die Methode „GetAttackVector“ ist dafür zuständig, eine Liste von Dingos zu erstellen, die direkt am Gruppenangriff teilnehmen werden. Sie erzeugt eine Menge zufälliger, eindeutiger Indizes, von denen jeder einem Dingo aus der gesamten Population entspricht. Die Methode legt zunächst die Größe des Ausgabe-Arrays „attackVector“ auf die angegebene Zahl „na“ (die Anzahl der Angreifer) fest. Der Zähler „c“ wird ebenfalls mit null initialisiert. Er erfasst, wie viele Dingos bereits für den Angriff ausgewählt wurden.

Die Methode startet eine Schleife, die so lange fortgesetzt wird, bis „na“ Dingos ausgewählt sind. In jeder Iteration der Schleife wird ein zufälliger Dingo-Index (idx) aus der gesamten verfügbaren Population generiert (von „0“ bis „popSize - 1“). Bevor der generierte Index zur Liste der Angreifer hinzugefügt wird, wird eine Überprüfung durchgeführt. Die Methode durchläuft die bereits ausgewählten Indizes im Array „attackVector“ an den Positionen „0“ bis „c - 1“. Wenn der zufällig generierte Index (idx) mit einem der zuvor ausgewählten Indizes übereinstimmt (d. h. attackVector[i] == idx), wird das Flag „found“ auf „true“ gesetzt. Wenn das Flag weiterhin „false“ ist (das heißt, der angegebene Index wurde noch nicht ausgewählt), wird dieser neue, eindeutige Index (idx) dem Array „attackVector“ unter dem aktuellen Index „c“ hinzugefügt. Danach wird der Zähler „c“ um eins erhöht.

Im Wesentlichen ist „GetAttackVector“ dafür zuständig, zufällig „na“ verschiedene Dingos aus der gesamten Population auszuwählen, damit diese eine Angriffsgruppe bilden können. Dieser Vorgang stellt sicher, dass sich jeder Dingo in der Gruppe von den anderen unterscheidet, wodurch Doppelungen vermieden werden und Vielfalt in der Angriffsgruppe gewährleistet ist.

//————————————————————————————————————————————————————————————————————
//--- Form the attacking dingo vector
void C_AO_DOAm_dingo::GetAttackVector (int na, int &attackVector [])
{
  int c = 0;
  ArrayResize (attackVector, na);

  while (c < na)
  {
    int idx = u.RNDintInRange (0, popSize - 1);

    // Check that the index is not repeated
    bool found = false;
    for (int i = 0; i < c; i++)
    {
      if (attackVector [i] == idx)
      {
        found = true;
        break;
      }
    }

    if (!found)
    {
      attackVector [c] = idx;
      c++;
    }
  }
}
//————————————————————————————————————————————————————————————————————

Die Methode „Persecution“ implementiert „Strategie 2: Verfolgung“. Das Ziel dieser Methode ist es, die Position eines bestimmten Dingos (agentIdx) so zu aktualisieren, dass er die Verfolgung aufnimmt. Die Methode wählt zunächst einen zufälligen Dingo aus der gesamten Population aus; sein Index wird in der Variablen r1 gespeichert.

Als Nächstes folgt eine Schleife, die alle Dimensionen (c) des Raums durchläuft, in dem sich die Dingos befinden. Für jede Dimension wird die neue Position des Dingos (agentIdx) nach folgender Formel berechnet: Zum Basiswert (cB[c]), der die Position des besten Dingos darstellt, wird das Produkt aus drei Faktoren addiert: beta1, einem Koeffizienten, der die Stärke des Verfolgungseinflusses steuert; MathExp(beta2), der Exponentialfunktion des Koeffizienten beta2; und der Differenz zwischen der Position eines zufällig ausgewählten Dingos (a[r1].c[c]) und der aktuellen Position des angreifenden Dingos (a[agentIdx].c[c]) in der jeweiligen Dimension.

Die neue Position wird sofort mithilfe der Hilfsfunktion zur Normalisierung u.SeInDiSp angepasst, die sicherstellt, dass sie in jeder Dimension unter Berücksichtigung der Schrittweite rangeStep[c] innerhalb des zulässigen Bereichs von rangeMin[c] bis rangeMax[c] bleibt.

Letztlich bewirkt die Persecution-Methode, dass sich der angegebene Dingo (agentIdx) auf einen zufällig ausgewählten anderen Dingo (r1) zubewegt, wobei die als Grundlage dienende beste Position berücksichtigt wird und die Parameter beta1 und beta2 zur Anpassung der Verfolgungsintensität und -dynamik verwendet werden. In diesem Fall bleibt die neue Position stets innerhalb der festen Grenzen des Suchraums.

//————————————————————————————————————————————————————————————————————
//--- Strategy 2: Chase (Eq. 3)
void C_AO_DOAm_dingo::Persecution (int agentIdx)
{
  // Select a random dingo
  int r1 = u.RNDintInRange (0, popSize - 1);

  // Apply the chase formula (Eq. 3)
  for (int c = 0; c < coords; c++)
  {
    // v = theBestVct + beta1 * exp(beta2) * (Positions[r1] - Positions[r])
    a [agentIdx].c [c] = cB [c] + beta1 * MathExp (beta2) * (a [r1].c [c] - a [agentIdx].c [c]);
    a [agentIdx].c [c] = u.SeInDiSp (a [agentIdx].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
  }
}
//————————————————————————————————————————————————————————————————————

Die Scavenger-Methode implementiert „Strategie 3: Aassuche“. Das Ziel dieser Methode besteht darin, die Position eines bestimmten Dingos (agentIdx) so zu aktualisieren, dass er sich an eine neue Position bewegt, die eine Art „Kompromiss“ oder „Zwischenwert“ zwischen seiner aktuellen Position und der Position eines zufällig ausgewählten anderen Dingos darstellt.

Die Methode wählt zunächst zufällig einen Dingo aus der gesamten Population aus und speichert dessen Index in der Variablen r1. Dieser Dingo wird als eine Art Bezugspunkt dienen. Außerdem wird ein zufälliger binärer Wert für das Vorzeichen (sign) generiert. Dieser Wert ist entweder „1,0“ oder „-1,0“. Dadurch wird festgelegt, ob die Differenzbildung „vorwärts“ oder „rückwärts“ erfolgt.

Als Nächstes folgt eine Schleife, die alle Dimensionen des Raums durchläuft, in dem sich die Dingos befinden. Für jede Dimension wird die neue Position des Dingos (agentIdx) wie folgt berechnet: Die Position eines zufällig ausgewählten Dingos (a[r1].c[c]) wird mit dem Exponentialwert des Koeffizienten „beta2“ multipliziert; von diesem Wert wird die aktuelle Position des angreifenden Dingos abgezogen (oder addiert, je nach Vorzeichen), und der resultierende Wert wird durch 2,0 geteilt.

Das bedeutet im Grunde, dass die neue Position irgendwo zwischen der aktuellen Position des Dingos und einer neuen „attraktiven“ Position liegen wird, abhängig von beta2 und dem gewählten Dingo. Wie bei anderen Methoden wird die neue Position nach ihrer Berechnung sofort mithilfe der Hilfsfunktion „u.SeInDiSp“ angepasst. Diese Funktion stellt sicher, dass die neue Position für jede Dimension innerhalb des zulässigen Bereichs (von rangeMin[c] bis rangeMax[c]) bleibt.

Bei der Scavenger-Methode wird die Position des Dingos also so aktualisiert, dass er an einen Punkt verschoben wird, der dem Mittelwert aus seiner aktuellen Position und einer Position entspricht, die sich aus einer exponentiellen Transformation der Position des anderen Dingos und einem zufälligen Vorzeichen ergibt. Dies ahmt das Verhalten eines Tieres nach, das nach Beute sucht, die sich „unterwegs“ oder „irgendwo zwischen“ bekannten Punkten befinden könnte.

//————————————————————————————————————————————————————————————————————
//--- Strategy 3: Scavenging (Eq. 4)
void C_AO_DOAm_dingo::Scavenger (int agentIdx)
{
  // Select a random dingo
  int r1 = u.RNDintInRange (0, popSize - 1);
  double sign = u.RNDbool() ? 1.0 : -1.0;

  // Apply the scavenging formula (Eq. 4)
  for (int c = 0; c < coords; c++)
  {
    // v = (exp(beta2) * Positions[r1] - (-1)^binary * Positions[r]) / 2
    a [agentIdx].c [c] = (MathExp (beta2) * a [r1].c [c] - sign * a [agentIdx].c [c]) / 2.0;
    a [agentIdx].c [c] = u.SeInDiSp (a [agentIdx].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
  }
}
//————————————————————————————————————————————————————————————————————

Die Methode „SurvivalProcedure“ implementiert „Strategie 4: Überlebensprozedur“. Das Hauptziel dieser Methode besteht darin, die Position eines bestimmten Dingos (agentIdx) anhand von Informationen zweier anderer Dingos zu aktualisieren, um eine neue, vorteilhaftere Position zu finden. Die Methode wählt zunächst zufällig zwei verschiedene Dingos aus der gesamten Population aus. Ihre Indizes werden in den Variablen r1 und r2 gespeichert. Es ist garantiert, dass r1 und r2 nicht gleich sind.

Außerdem wird ein zufälliger binärer Wert (Vorzeichen) generiert, der entweder „1,0“ oder „-1,0“ sein kann. Damit wird festgelegt, ob die Position des zweiten Dingos mit unverändertem oder umgekehrtem Vorzeichen subtrahiert wird. Anschließend folgt eine Schleife, die alle Dimensionen durchläuft. Für jede Dimension wird eine neue Dingo-Position wie folgt berechnet: Zur besten gefundenen Position (cB[c]) wird die Hälfte der Differenz zwischen der Position des ersten zufällig ausgewählten Dingos (a[r1].c[c]) und der Position des zweiten zufällig ausgewählten Dingos (a[r2].c[c]) addiert, wobei das Vorzeichen der Position des zweiten Dingos abhängig von „sign“ umgekehrt werden kann. Nach der Berechnung der neuen Position sollte diese mithilfe der Hilfsfunktion „SeInDiSp“ angepasst werden.

Im Allgemeinen veranschaulicht die Methode „SurvivalProcedure“ eine Strategie, bei der ein Dingo seine Position aktualisiert, indem er diese als Abweichung von der besten gefundenen Position berechnet und dazu die Hälfte der Differenz zwischen den Positionen zweier anderer, zufällig ausgewählter Dingos addiert. Das zufällige Vorzeichen bringt ein Element der Unvorhersehbarkeit in die Richtungswahl für diese Differenz ein, und die Positionsbegrenzung stellt sicher, dass der Dingo in seinem Arbeitsbereich bleibt. Dies lässt sich als Versuch interpretieren, einen „Mittelwert“ zwischen zwei anderen potenziell „vielversprechenden“ Punkten zu ermitteln, wobei die beste bekannte Position berücksichtigt wird.

//————————————————————————————————————————————————————————————————————
//--- Strategy 4: Survival procedure (Eq. 6)
void C_AO_DOAm_dingo::SurvivalProcedure (int agentIdx)
{
  // Select two different random dingoes
  int r1, r2;
  do
  {
    r1 = u.RNDintInRange (0, popSize - 1);
    r2 = u.RNDintInRange (0, popSize - 1);
  }
  while (r1 == r2);

  double sign = u.RNDbool() ? 1.0 : -1.0;

  // Apply the survival formula (Eq. 6)
  for (int c = 0; c < coords; c++)
  {
    // v = theBestVct + (Positions[r1] - (-1)^binary * Positions[r2]) / 2
    a [agentIdx].c [c] = cB [c] + (a [r1].c [c] - sign * a [r2].c [c]) / 2.0;
    a [agentIdx].c [c] = u.SeInDiSp (a [agentIdx].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
  }
}
//————————————————————————————————————————————————————————————————————

Die Methode „UpdateSurvivalRates“ ist dafür zuständig, die „Überlebensraten“ für jeden Dingo in der Population zu berechnen und zu aktualisieren. Diese Indikatoren bestimmen die Wahrscheinlichkeit, mit der ein Dingo das Verhalten eines Agenten in der nächsten Iteration mitbestimmt.

Zunächst initialisiert die Methode zwei Variablen: minFitness und maxFitness. Anschließend durchläuft sie nacheinander alle Dingos in der Population. Für jeden Dingo wird sein aktueller Fitnesswert (a[i].f) mit den aktuellen Werten minFitness und maxFitness verglichen. Wenn die aktuelle Fitness kleiner als minFitness ist, wird minFitness aktualisiert. Ist die aktuelle Fitness größer als maxFitness, wird maxFitness aktualisiert. Nach dieser Schleife enthält minFitness den kleinsten Fitnesswert der gesamten Population und maxFitness den größten.

Ist der Unterschied zwischen maxFitness und minFitness sehr gering (praktisch null, was bedeutet, dass alle Dingos die gleiche Fitness aufweisen), wird allen Dingos ein Überlebenswert von „0,5“ zugewiesen. Dadurch wird eine Division durch Null verhindert und es werden gleiche Chancen für alle geschaffen.

Wenn sich die Fitness der Dingos unterscheidet, wird der Vorgang in einer Schleife für alle Dingos wiederholt. Für jeden Dingo wird dessen Überlebensrate (survival [i]) berechnet. Die Formel für diesen Indikator lautet wie folgt: (maxFitness - a [i].f) / (maxFitness - minFitness). Diese Formel normiert den Fitnesswert des Dingos auf den Bereich aller Fitnesswerte.

Der Dingo mit der geringsten Fitness, die nahe an minFitness liegt, hat eine Überlebensrate nahe 1,0 (da maxFitness - a[i].f groß ist). Ein Dingo mit der höchsten Fitness, die nahe an maxFitness liegt, hat eine Überlebensrate nahe 0,0 (da maxFitness - a[i].f nahe null liegt).

Letztlich wandelt die Methode „UpdateSurvivalRates“ absolute Dingo-Fitnesswerte in relative „Überlebensraten“ um, wobei höhere Fitnesswerte niedrigeren Überlebensraten entsprechen und umgekehrt. Dies lässt sich als eine Strategie interpretieren, bei der diejenigen, die „leiden“ (eine geringe Fitness aufweisen), eine größere Chance haben, zu „überleben“ oder sich zu verändern, während diejenigen, die am „erfolgreichsten“ sind (mit hoher Fitness), weniger Anreiz haben, sich zu verändern.

//————————————————————————————————————————————————————————————————————
//--- Update survival rates
void C_AO_DOAm_dingo::UpdateSurvivalRates ()
{
  // Find the minimum and maximum 'fitness'
  double minFitness =  DBL_MAX;
  double maxFitness = -DBL_MAX;

  for (int i = 0; i < popSize; i++)
  {
    if (a [i].f < minFitness) minFitness = a [i].f;
    if (a [i].f > maxFitness) maxFitness = a [i].f;
  }

  // Calculate survival rates
  if (MathAbs (maxFitness - minFitness) < DBL_EPSILON)
  {
    ArrayInitialize (survival, 0.5);
  }
  else
  {
    for (int i = 0; i < popSize; i++)
    {
      // survival_rate = (max - fit) / (max - min)
      survival [i] = (maxFitness - a [i].f) / (maxFitness - minFitness);
    }
  }
}
//————————————————————————————————————————————————————————————————————

Die Methode Revision sucht nach dem Sortieren den besten Dingo in der aktuellen Population und aktualisiert die Bewertungswerte der global besten Lösung, wenn dieser Dingo die bisher bekannten besten Ergebnisse übertrifft. Dies ist ein Standardverfahren bei Optimierungsalgorithmen, um die im Verlauf der Suche gefundene beste Lösung zu speichern und zu verfolgen.

//————————————————————————————————————————————————————————————————————
//--- Update the best and worst solutions
void C_AO_DOAm_dingo::Revision ()
{
  // Sort the population to find the best and worst
  static S_AO_Agent aT [];
  ArrayResize (aT, popSize);
  u.Sorting (a, aT, popSize);

  // Update the global best solution
  if (a [0].f > fB)
  {
    fB = a [0].f;
    ArrayCopy (cB, a [0].c, 0, 0, WHOLE_ARRAY);
  }
}
//————————————————————————————————————————————————————————————————————


Testergebnisse

Ergebnisse aus 50 Durchläufen statt der üblichen 10 (um den Einfluss ungewöhnlich guter, aber zufallsbedingter Ergebnisse abzumildern)

DOA|Dingo Optimization Algorithm|50.0|0.5|0.7|
=============================
5 Hilly's; Func runs: 10000; result: 0.4796838225601811
25 Hilly's; Func runs: 10000; result: 0.4536754883347326
500 Hilly's; Func runs: 10000; result: 0.4636906699500103
=============================
5 Forest's; Func runs: 10000; result: 0.9414536230352631
25 Forest's; Func runs: 10000; result: 0.8790978288567921
500 Forest's; Func runs: 10000; result: 0.9145376343407303
=============================
5 Megacity's; Func runs: 10000; result: 0.7861538461538461
25 Megacity's; Func runs: 10000; result: 0.8606153846153848
500 Megacity's; Func runs: 10000; result: 0.8480461538461537
=============================
All score: 6.62695 (73.63%)

Die Visualisierung zeigt ein komplexes, sich veränderndes Muster im Suchbereich, das mit dem Einsatz verschiedener Jagdstrategien zusammenhängt (die charakteristischen diagonalen Muster, die vom Vorgängeralgorithmus übernommen wurden, sind weiterhin erkennbar). Trotz der hohen Gesamtwerte gibt es jedoch bei allen Testfunktionen eine sehr große Streuung der Ergebnisse.

Hilly

DOAm_dingo auf der Testfunktion Hilly

Forest

DOAm_dingo auf der Testfunktion Forest

Megacity

DOAm_dingo auf der Testfunktion Megacity

Aufgrund der Testergebnisse belegt der DOAm_dingo-Algorithmus den ersten Platz in unserer Rangliste der populationsbasierten Optimierungsverfahren.

#AOBeschreibungHillyHilly
Final
ForestForest
Final
Megacity (diskret)Megacity
Final
Final
Result
% von
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)
1DOAm_dingodingo_optimization_algorithm_M0.479680.453670.463691.397040.941450.879090.914542.735080.786150.860610.848052.494816.62773,63
1ANSnachbarschaftsübergreifende Suche0.949480.847760.438572.235811.000000.923340.399882.323230.709230.634770.230911.574916.13468,15
2CLACodeschloss-Algorithmus (joo)0.953450.871070.375902.200420.989420.917090.316422.222940.796920.693850.193031.683806.10767,86
3AMOmOptimierung der Tiermigration M0.903580.843170.462842.209590.990010.924360.465982.380340.567690.591320.237731.396755.98766,52
4(P+O)ES(P+O)-Evolutionsstrategien0.922560.881010.400212.203790.977500.874900.319452.171850.673850.629850.186341.490035.86665,17
5CTAKometenschweif-Algorithmus (joo)0.953460.863190.277702.094350.997940.857400.339492.194840.887690.564310.105121.557125.84664,96
6TETAAlgorithmus der zeitlichen Entwicklung und Bewegung (joo)0.913620.823490.319902.057010.970960.895320.293242.159520.734620.685690.160211.580525.79764,41
7SDSmStochastische Diffusionssuche M0.930660.854450.394762.179880.999830.892440.196192.088460.723330.611000.106701.441035.70963,44
8BOAmBillard-Optimierungsalgorithmus M0.957570.825990.252352.035901.000000.900360.305022.205380.735380.525230.095631.356255.59862,19
9AAmBogenschieß-Algorithmus M0.917440.708760.421602.047800.925270.758020.353282.036570.673850.552000.237381.463235.54861,64
10ESGEvolution sozialer Gruppen (joo)0.999060.796540.350562.146161.000000.828630.131021.959650.823330.553000.047251.423585.52961,44
11SIAsimuliertes isotropes Annealing (joo)0.957840.842640.414652.215130.982390.795860.205071.983320.686670.493000.090531.270205.46960,76
12EOmextremal_optimization_M0.761660.772420.317471.851550.999990.767510.235272.002770.747690.539690.142491.429875.28458,71
13BBObiogeografiebasierte Optimierung0.949120.694560.350311.993990.938200.673650.256821.868670.746150.482770.173691.402615.26558,50
14ACSkünstliche kooperative Suche0.755470.747440.304071.806981.000000.888610.224132.112740.690770.481850.133221.305835.22658,06
15DAdialektischer Algorithmus0.861830.700330.337241.899400.981630.727720.287181.996530.703080.452920.163671.319675.21657,95
16BHAmBlack-Hole-Algorithmus M0.752360.766750.345831.864930.935930.801520.271772.009230.650770.516460.154721.321955.19657,73
17ASOAnarchy-Society-Optimierung0.848720.746460.314651.909830.961480.791500.238031.991010.570770.540620.166141.277525.17857,54
18RFORoyal-Flush-Optimierung (joo)0.833610.737420.346291.917330.894240.738240.240981.873460.631540.502920.164211.298675.08956,55
19AOSmAtomorbital-Suche M0.802320.704490.310211.817020.856600.694510.219961.771070.746150.528620.143581.418355.00655,63
20TSEASchildkrötenpanzer-Evolutionsalgorithmus (joo)0.967980.644800.296721.909490.994490.619810.227081.841390.690770.426460.135981.253225.00455,60
21BSABacktracking-Suchalgorithmus0.973090.545340.290981.809410.999990.585430.217471.802890.847690.369530.129781.347004.95955,10
22DEDifferential Evolution0.950440.616740.303081.870260.953170.788960.166521.908650.786670.360330.029531.176534.95555,06
23SRASuccessful Restaurateur Algorithm (joo)0.968830.634550.292171.895550.946370.555060.191241.692670.749230.440310.125261.314804.90354,48
24CROChemical Reaction Optimization0.946290.661120.298531.905930.879060.584220.211461.674730.758460.426460.126861.311784.89254,36
25BIOBlood Inheritance Optimization (joo)0.815680.653360.308771.777810.899370.653190.217601.770160.678460.476310.139021.293784.84253,80
26DOAdream_optimization_algorithm0.855560.700850.372801.929210.734210.489050.241471.464730.772310.473540.185611.431464.82553,62
27BSABird Swarm Algorithm0.893060.649000.262501.804550.924200.711210.249391.884790.693850.326150.100121.120124.80953,44
28DEADelfin-Echolokationsalgorithmus0.759950.675720.341711.777380.895820.642230.239411.777460.615380.440310.151151.206844.76252,91
29HSHarmony Search0.865090.687820.325271.878180.999990.680020.095901.775920.620000.422670.054581.097254.75152,79
30SSGSaplings Sowing and Growing0.778390.649250.395431.823080.859730.624670.174291.658690.646670.441330.105981.193984.67651,95
31BCOmBacterial Chemotaxis Optimization M0.759530.622680.314831.697040.893780.613390.225421.732590.653850.420920.144351.219124.64951,65
32ABOAfrican Buffalo Optimization0.833370.622470.299641.755480.921700.586180.197231.705110.610000.431540.132251.173784.63451,49
33(PO)ES(PO)-Evolutionsstrategien0.790250.626470.429351.846060.876160.609430.195911.681510.590000.379330.113221.082554.61051,22
34FBAfraktalbasierter Algorithmus0.790000.651340.289651.730990.871580.568230.188771.628580.610770.460620.123981.195374.55550,61
35TSmTabu-Suche M0.877950.614310.291041.783300.928850.518440.190541.637830.610770.382150.121571.114494.53650,40
36BSOBrain-Storm-Optimierung0.937360.576160.296881.810410.931310.558660.235371.725340.552310.290770.119140.962224.49849,98
37WOAmWal-Optimierungsalgorithmus M0.845210.562980.262631.670810.931000.522780.163651.617430.663080.411380.113571.188034.47649,74
38AEFAAlgorithmus des künstlichen elektrischen Feldes0.877000.617530.252351.746880.927290.726980.180641.834900.666150.116310.095080.877544.45949,55
39AEOOptimierungsalgorithmus auf Basis künstlicher Ökosysteme0.913800.467130.264701.645630.902230.437050.214001.553270.661540.308000.285631.255174.45449,49
40CAmKamel-Algorithmus M0.786840.560420.351331.698590.827720.560410.243361.631490.648460.330920.134181.113564.44449,37
41ACOmAmeisenkolonie-Optimierung M0.881900.661270.303771.846930.858730.586800.150511.596040.596670.373330.024720.994724.43849,31
42CMAESKovarianzmatrix-Adaptions-Evolutionsstrategie0.762580.720890.000001.483470.820560.796160.000001.616720.758460.490770.000001.249234.34948,33
43DA_duelistduelist_algorithm0.927820.537780.277921.743520.869570.475360.181931.526860.621530.335690.117151.074374.34548,28
44BFO-GABacterial Foraging Optimization - GA0.891500.551110.315291.757900.969820.396120.063051.428990.726670.275000.035251.036924.22446,93
RWRandom Walk0.487540.321590.257811.066940.375540.219440.158770.753750.279690.149170.098470.527342.34826.09


Zusammenfassung

Die hier betrachtete Modifikation des DOA_dingo-Algorithmus zeichnet sich durch ihre hohe Suchleistung aus. Es ist jedoch zu beachten, dass es sich bei diesen beeindruckenden Ergebnissen um Durchschnittswerte handelt, die in einer Reihe von Tests ermittelt wurden. Das bedeutet, dass der Benutzer die Optimierung mehrmals durchführen muss, um eine ausreichende Erkundung des Suchraums zu gewährleisten.

Andererseits weist der Algorithmus bei glatten Funktionen eine eher mäßige Konvergenzgeschwindigkeit auf. Dennoch ist DOA_dingo eine sehr nützliche und vielversprechende Methode. Ich würde empfehlen, diese Methode in der Anfangsphase der Suche einzusetzen und anschließend auf präzisere Algorithmen umzusteigen. Außerdem ist es äußerst wichtig, alle Parameter vorab auf denselben Wertebereich zu normalisieren.

Tabelle

Abbildung 2. Farbcodierter Vergleich der Algorithmen in den jeweiligen Tests

Diagramm

Abbildung 3. Histogramm der Ergebnisse der Algorithmustests (Skala von 0 bis 100, je höher, desto besser; wobei 100 das höchstmögliche theoretische Ergebnis darstellt; im Archiv befindet sich ein Skript zur Berechnung der Bewertungstabelle)

Vor- und Nachteile von DOAm_dingo:

Vorteile:

  1. Schnell.
  2. Sehr hohe Durchschnittswerte.

Nachteile:

  1. Große Schwankungsbreite bei den Ergebnissen.
  2. Neigung, sich festzufahren.

Dem Artikel liegt ein Archiv mit den aktuellen Versionen der Algorithmus-Quellcodes bei. Der Autor des Artikels übernimmt keine Gewähr für die absolute Richtigkeit der Beschreibung der kanonischen Algorithmen. An vielen von ihnen wurden Änderungen vorgenommen, um die Suchfähigkeiten zu verbessern. Die in den Artikeln dargelegten Schlussfolgerungen und Einschätzungen basieren auf den Ergebnissen der Experimente.


Im Artikel verwendete Programme

#NameTypBeschreibung
1#C_AO.mqh
Include
Basisklasse für populationsbasierte Optimierungsalgorithmen
2#C_AO_enum.mqh
Include
Enumeration populationsbasierter Optimierungsalgorithmen
3TestFunctions.mqh
Include
Bibliothek mit Testfunktionen
4
TestStandFunctions.mqh
Include
Funktionsbibliothek für den Teststand
5
Utilities.mqh
Include
Bibliothek mit Hilfsfunktionen
6
CalculationTestResults.mqh
Include
Skript zur Berechnung der Ergebnisse für die Vergleichstabelle
7
Testing AOs.mq5
SkriptDer einheitliche Teststand für alle populationsbasierten Optimierungsalgorithmen
8
Simple use of population optimization algorithms.mq5
Skript
Ein einfaches Beispiel für die Verwendung populationsbasierter Optimierungsalgorithmen ohne Visualisierung
9
Test_AO_DOAm_dingo.mq5
SkriptTestumgebung für DOAm_dingo

Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/19187

Beigefügte Dateien |
DOAm_Dingo.zip (279.94 KB)
Letzte Kommentare | Zur Diskussion im Händlerforum (2)
Yevgeniy Koshtenko
Yevgeniy Koshtenko | 23 Sept. 2025 in 18:39
MetaQuotes:

Es wurde ein Artikel mit dem Titel „Modifikation des Dingo-Optimierungsalgorithmus – Dingo Optimization Algorithm M (DOAm)“ veröffentlicht:

Autor: Andrey Dik

Ein hervorragender Algorithmus! Unglaublich
cemal
cemal | 25 Juli 2026 in 10:17
Wie lässt sich dieser Algorithmus für den Handel nutzen? Können Sie einige Beispiele für Regressions- oder Klassifikationsaufgaben nennen?
Die Übertragung der Trading-Signale in einem universalen Expert Advisor. Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
In diesem Artikel wurden die verschiedenen Möglichkeiten beschrieben, um die Trading-Signale von einem Signalmodul des universalen EAs zum Steuermodul der Positionen und Orders zu übertragen. Es wurden die seriellen und parallelen Interfaces betrachtet.
Von den Grundlagen zur Mittelstufe: Bubblesort anpassen und optimieren Von den Grundlagen zur Mittelstufe: Bubblesort anpassen und optimieren
In diesem Artikel wird ein sehr einfacher und leicht verständlicher Mechanismus erläutert, dessen Zweck darin besteht, ein beliebiges Array zu sortieren. Dabei werden wir sehen, dass das erzielte Ergebnis nicht immer den Erwartungen entspricht, sodass die Implementierung selbst angepasst werden muss, um die gewünschten Ergebnisse zu erzielen.
Eine alternative Log-datei mit der Verwendung der HTML und CSS Eine alternative Log-datei mit der Verwendung der HTML und CSS
In diesem Artikel werden wir eine sehr einfache, aber leistungsfähige Bibliothek zur Erstellung der HTML-Dateien schreiben, dabei lernen wir auch, wie man eine ihre Darstellung einstellen kann (nach seinem Geschmack) und sehen wir, wie man es leicht in seinem Expert Advisor oder Skript hinzufügen oder verwenden kann.
Marktsimulation: Erste Schritte mit SQL in MQL5 (II) Marktsimulation: Erste Schritte mit SQL in MQL5 (II)
Obwohl viele Menschen glauben, dass man SQL-Code problemlos in anderen Code einbetten kann, ist dies in der Regel nicht der Fall. Der Grund dafür ist, dass der SQL-Code als Zeichenkette in der ausführbaren Datei enthalten ist. Das Einbetten von SQL-Code als Zeichenkette ist zwar bei kleinen Codeausschnitten kein Problem, kann uns aber letztlich einiges an Kopfzerbrechen bereiten.