English Русский Español 日本語 Português
preview
Entwicklung eines Expert Advisors für mehrere Währungen (Teil 20): Ordnung in den Ablauf der automatischen Projektoptimierungsphasen bringen (I)

Entwicklung eines Expert Advisors für mehrere Währungen (Teil 20): Ordnung in den Ablauf der automatischen Projektoptimierungsphasen bringen (I)

MetaTrader 5Tester |
49 8
Yuriy Bykov
Yuriy Bykov

Einführung

In dieser Artikelserie versuchen wir, ein automatisches Optimierungssystem zu entwickeln, das es ermöglicht, gute Kombinationen von Parametern einer Handelsstrategie ohne menschliches Eingreifen zu finden. Diese Kombinationen werden dann zu einem endgültigen EA kombiniert. Das Ziel wird in Teil 9 und Teil 11 ausführlicher dargelegt. Der Prozess einer solchen Suche selbst wird von einem EA (optimizing EA) gesteuert, und alle Daten, die während des Betriebs gespeichert werden müssen, werden in der Hauptdatenbank festgelegt.

In der Datenbank gibt es Tabellen, in denen Informationen über verschiedene Klassen von Objekten gespeichert werden. Einige haben ein Statusfeld, das Werte aus einer festen Reihe von Werten annehmen kann („Queued“, „Process“, „Done“), aber nicht alle Klassen verwenden dieses Feld. Genauer gesagt, wird es derzeit nur für Optimierungsaufgaben (Task) verwendet. Unser optimierendes EA sucht in der Aufgabentabelle (Aufgaben) nach den Aufgaben in der Warteschlange, um die nächste auszuführende Aufgabe auszuwählen. Nach Abschluss jeder Aufgabe ändert sich ihr Status in der Datenbank auf Erledigt.

Versuchen wir, automatische Statusaktualisierungen nicht nur für Aufgaben, sondern auch für alle anderen Klassen von Objekten (Aufträge, Phasen, Projekte) zu implementieren und die automatische Ausführung aller erforderlichen Phasen bis zur Erlangung des endgültigen EA zu organisieren, der unabhängig ohne Verbindung zur Datenbank arbeiten kann.


Der Weg ist vorgezeichnet

Zunächst werden wir uns alle Klassen von Objekten in der Datenbank, die einen Status haben, genau ansehen und klare Regeln für die Änderung des Status formulieren. Wenn dies möglich ist, können wir diese Regeln als Aufrufe zusätzlicher SQL-Abfragen entweder vom optimierenden EA oder von den Stage EAs implementieren. Es wäre auch möglich, sie als Trigger in der Datenbank zu implementieren, die beim Auftreten bestimmter Datenänderungsereignisse aktiviert werden.

Als Nächstes müssen wir uns auf eine Methode zur Festlegung der Reihenfolge einigen, in der die Aufgaben erledigt werden. Das war vorher kein großes Problem, da wir während der Entwicklung jedes Mal auf einer neuen Datenbank trainierten und Projektphasen, Arbeiten und Aufgaben genau in der Reihenfolge hinzufügten, in der sie erledigt werden mussten. Wenn man jedoch dazu übergeht, Informationen über mehrere Projekte in der Datenbank zu speichern oder sogar automatisch neue Projekte hinzuzufügen, kann man sich nicht mehr auf diese Methode zur Bestimmung der Rangfolge von Aufgaben verlassen. Lassen Sie uns also etwas Zeit für dieses Thema aufwenden.

Um den Betrieb des gesamten Ablaufs zu testen, bei dem alle Aufgaben des Auto-Optimierungsprojekts nacheinander ausgeführt werden, müssen wir einige weitere Aktionen automatisieren. Vorher haben wir sie manuell durchgeführt. Nach Abschluss der zweiten Optimierungsphase haben wir beispielsweise die Möglichkeit, die besten Gruppen für die Verwendung im endgültigen EA auszuwählen. Wir haben diese Operation durchgeführt, indem wir die dritte Phase des EA manuell, d. h. außerhalb des automatischen Optimierungsprogramms, ausgeführt haben. Um die Startparameter für diesen EA festzulegen, haben wir auch die IDs der Durchgänge der zweiten Phase mit den besten Ergebnissen manuell ausgewählt, indem wir eine Datenbankzugangsschnittstelle eines Drittanbieters in Verbindung mit MQL5 verwendet haben. Wir werden versuchen, auch in diesem Bereich etwas zu tun.

Nach den Änderungen, die wir vorgenommen haben, erwarten wir, dass wir endlich einen vollständigen, fertigen Ablauf für die Durchführung von Auto-Optimierungsstufen erstellen können, um den endgültigen EA zu erhalten. Auf dem Weg dorthin werden wir auch einige andere Fragen im Zusammenhang mit der Steigerung der Arbeitseffizienz betrachten. Zum Beispiel scheint es, dass die zweite und die folgenden Phasen der EAs für verschiedene Handelsstrategien gleich sind. Prüfen wir, ob das stimmt. Wir werden auch sehen, was praktischer ist - die Erstellung verschiedener kleinerer Projekte oder die Erstellung einer größeren Anzahl von Phasen oder Arbeiten in einem größeren Projekt.


Regeln für Statusänderungen

Beginnen wir mit der Formulierung der Regeln für die Statusänderung. Wie Sie sich vielleicht erinnern, enthält unsere Datenbank Informationen über die folgenden Objekte, die ein Statusfeld (status) haben:

  • Projekte. Kombiniert einen oder mehrere Abschnitte, die in der Tabelle projects gespeichert sind;
  • Phasen. Kombiniert einen oder mehrere Aufträge, die in der Tabelle stages gespeichert sind;
  • Job. Kombiniert eine oder mehrere Aufgaben, die in der jobs gespeichert sind;
  • Aufgabe. Kombiniert in der Regel mehrere Testdurchläufe, die in der Tabelle tasks gespeichert werden.

Die möglichen Statuswerte sind für jede dieser vier Objektklassen gleich und können einen der folgenden Werte annehmen:

  • Queued. Das Objekt wurde zur Bearbeitung in die Warteschlange gestellt.
  • Process. Das Objekt wird gerade bearbeitet.
  • Done. Die Objektbehandlung ist abgeschlossen oder wurde nicht gestartet.
An dieser Stelle sei erwähnt, dass in der vorherigen Version der Datenbank die Zusammensetzung der Statuswerte etwas anders war. Ein Projekt hatte beispielsweise den vierten Status - „Created“ (erstellt), der bei der Erstellung des Projekts zugewiesen wurde, während bei Aufgaben der Status „Prozess“ als „Processing“ bezeichnet wurde. Nun werden wir die Zusammensetzung und die Namen der Status für alle Objekte vereinheitlichen.

Beschreiben wir die Regeln für die Änderung des Status von Objekten in der Datenbank in Übereinstimmung mit dem normalen Zyklus des Ablaufs für die automatische Projektoptimierung. Der Zyklus beginnt, wenn ein Projekt für die Optimierung in die Warteschlange gestellt wird, d.h. den Status „Queued“ erhält.

Wenn sich der Projektstatus in der Warteschlange ändert:

  • setzen wir den Status aller Phasen dieses Projekts auf Queued.

Wenn sich der Status einer Phase in Warteschleife ändert:

  • setzen wir den Status aller Aufträge in dieser Phase auf Queued.

Wenn der Auftragsstatus in der Warteschlange wechselt:

  • setzen wir den Status aller Aufgaben dieses Auftrags auf Queued.

Wenn der Status der Aufgabe in der Warteschlange wechselt:

  • löschen wir das Start- und Enddatum.

Die Änderung des Projektstatus auf „Queued“ führt also zu einer kaskadenartigen Aktualisierung der Status aller Phasen, Arbeiten und Aufgaben dieses Projekts auf „Queued“. Alle diese Objekte bleiben in diesem Status, bis die EA Optimization.ex5 gestartet wird.

Nach dem Start muss mindestens eine Aufgabe im Status „Queued“ gefunden werden. Später werden wir die Sortierreihenfolge bei mehreren Aufgaben betrachten. Der Status der Aufgabe ändert sich in Prozess. Dies führt zu den folgenden Aktionen:

Wenn der Status der Aufgabe auf „Process“ wechselt:

  • setzen wir das Startdatum auf die aktuelle Uhrzeit;
  • löschen wir alle zuvor im Rahmen der Aufgabe durchgeführten Durchgänge;
  • setzen wir den Status des Auftrags, der mit dieser Aufgabe verbunden ist, auf Prozess.

Wenn der Auftragsstatus auf Prozess wechselt:

  • setzen wir den Status der Phase, die mit diesem Auftrag verbunden ist, auf Prozess.

Wenn sich der Status einer Phase in Prozess ändert:

  • setzen wir den Status des Projekts, das mit dieser Phase verbunden ist, auf Prozess.

Danach werden die Aufgaben im Rahmen der Projektphasen nacheinander ausgeführt. Weitere Statusänderungen können erst nach Abschluss der nächsten Aufgabe erfolgen. An diesem Punkt ändert sich der Aufgabenstatus in Erledigt und kann dazu führen, dass dieser Status an übergeordnete Objekte weitergegeben wird.

Wenn der Aufgabenstatus auf Done wechselt:

  • setzen wir das Enddatum gleich der aktuellen Uhrzeit;
  • rufen wir eine Liste aller Aufgaben in der Warteschlange ab, die Teil des Auftrags sind, in dem diese Aufgabe ausgeführt wird. Wenn es keine gibt, setzen wir den Status des mit dieser Aufgabe verbundenen Auftrags auf Done.

Wenn der Auftragsstatus auf Done wechselt:

  • rufen wir eine Liste aller in der Warteschlange befindlichen Aufträge ab, die zu der Phase gehören, in der dieser Auftrag ausgeführt wird. Wenn es keine gibt, setzen wir den Status der mit dieser Arbeit verbundenen Phase auf Done.

Wenn der Status einer Phase auf Done wechselt:

  • rufen wir eine Liste aller im Projekt enthaltenen Warteschlangenabschnitte ab, in denen dieser Abschnitt ausgeführt wird. Wenn es keine gibt, setzen wir den Status des mit dieser Phase verbundenen Projekts auf Done.

Wenn also die letzte Aufgabe des letzten Auftrags der letzten Phase abgeschlossen ist, wird das Projekt selbst in den Zustand completed übergehen.

Nachdem nun alle Regeln formuliert sind, können wir mit der Erstellung von Triggern in der Datenbank fortfahren, die diese Aktionen umsetzen.


Auslöser erstellen

Beginnen wir mit dem Auslöser für die Änderung des Projektstatus in der Warteschlange. Hier ist ein möglicher Weg, dies umzusetzen:

CREATE TRIGGER upd_project_status_queued
         AFTER UPDATE OF status
            ON projects
          WHEN NEW.status = 'Queued'
BEGIN
    UPDATE stages
       SET status = 'Queued'
     WHERE id_project = NEW.id_project;
END;

Nach der Fertigstellung werden auch die Projektphasen in die Warteschleife gestellt. Daher sollten wir die entsprechenden Auslöser für Phasen, Jobs und Aufgaben starten:

CREATE TRIGGER upd_stage_status_queued
         AFTER UPDATE
            ON stages
          WHEN NEW.status = 'Queued' AND 
               OLD.status <> NEW.status
BEGIN
    UPDATE jobs
       SET status = 'Queued'
     WHERE id_stage = NEW.id_stage;
END;

CREATE TRIGGER upd_job_status_queued
         AFTER UPDATE OF status
            ON jobs
          WHEN NEW.status = 'Queued'
BEGIN
    UPDATE tasks
       SET status = 'Queued'
     WHERE id_job = NEW.id_job;
END;

CREATE TRIGGER upd_task_status_queued
         AFTER UPDATE OF status
            ON tasks
          WHEN NEW.status = 'Queued'
BEGIN
    UPDATE tasks
       SET start_date = NULL,
           finish_date = NULL
     WHERE id_task = NEW.id_task;
END;

Der Start der Aufgabe wird durch den folgenden Auslöser abgewickelt, der das Startdatum der Aufgabe festlegt, die Durchlaufdaten des vorherigen Starts der Aufgabe löscht und den Auftragsstatus auf Prozess aktualisiert:

CREATE TRIGGER upd_task_status_process
         AFTER UPDATE OF status
            ON tasks
          WHEN NEW.status = 'Process'
BEGIN
    UPDATE tasks
       SET start_date = DATETIME('NOW') 
     WHERE id_task = NEW.id_task;
    DELETE FROM passes
          WHERE id_task = NEW.id_task;
    UPDATE jobs
       SET status = 'Process'
     WHERE id_job = NEW.id_job;
END;

Anschließend werden die Phasen- und Projektstatus, innerhalb derer dieser Auftrag ausgeführt wird, an Process weitergegeben:

CREATE TRIGGER upd_job_status_process
         AFTER UPDATE OF status
            ON jobs
          WHEN NEW.status = 'Process'
BEGIN
    UPDATE stages
       SET status = 'Process'
     WHERE id_stage = NEW.id_stage;
END;

CREATE TRIGGER upd_stage_status_process
         AFTER UPDATE OF status
            ON stages
          WHEN NEW.status = 'Process'
BEGIN
    UPDATE projects
       SET status = 'Process'
     WHERE id_project = NEW.id_project;
END;

In dem Auslöser, der aktiviert wird, wenn der Aufgabenstatus auf Erledigt aktualisiert wird, d. h., wenn die Aufgabe erledigt ist, aktualisieren wir das Datum der Aufgabenerledigung und dann (je nach Vorhandensein oder Nichtvorhandensein anderer Aufgaben in der Warteschlange für die Ausführung innerhalb des aktuellen Aufgabenauftrags) aktualisieren wir den Auftragsstatus entweder auf Process oder Done:

CREATE TRIGGER upd_task_status_done
         AFTER UPDATE OF status
            ON tasks
          WHEN NEW.status = 'Done'
BEGIN
    UPDATE tasks
       SET finish_date = DATETIME('NOW') 
     WHERE id_task = NEW.id_task;
    UPDATE jobs
       SET status = (
               SELECT CASE WHEN (
                                    SELECT COUNT( * ) 
                                      FROM tasks t
                                     WHERE t.status = 'Queued' AND 
                                           t.id_job = NEW.id_job
                                )
=                         0 THEN 'Done' ELSE 'Process' END
           )
     WHERE id_job = NEW.id_job;
END;

Dasselbe gilt für den Status von Phasen und Projekten:

CREATE TRIGGER upd_job_status_done
         AFTER UPDATE OF status
            ON jobs
          WHEN NEW.status = 'Done'
BEGIN
    UPDATE stages
       SET status = (
               SELECT CASE WHEN (
                                    SELECT COUNT( * ) 
                                      FROM jobs j
                                     WHERE j.status = 'Queued' AND 
                                           j.id_stage = NEW.id_stage
                                )
=                         0 THEN 'Done' ELSE 'Process' END
           )
     WHERE id_stage = NEW.id_stage;
END;

CREATE TRIGGER upd_stage_status_done
         AFTER UPDATE OF status
            ON stages
          WHEN NEW.status = 'Done'
BEGIN
    UPDATE projects
       SET status = (
               SELECT CASE WHEN (
                                    SELECT COUNT( * ) 
                                      FROM stages s
                                     WHERE s.status = 'Queued' AND 
                                           s.name <> 'Single tester pass' AND 
                                           s.id_project = NEW.id_project
                                )
=                         0 THEN 'Done' ELSE 'Process' END
           )
     WHERE id_project = NEW.id_project;
END;

Wir werden auch die Möglichkeit bieten, alle Projektelemente in den Status „Erledigt“ zu versetzen, wenn dieser Status für das Projekt selbst gesetzt wird. Wir haben dieses Szenario nicht in die obige Liste der Regeln aufgenommen, da es sich nicht um eine obligatorische Aktion im normalen Verlauf der automatischen Optimierung handelt. In diesem Auslöser setzen wir den Status aller nicht ausgeführten oder laufenden Aufgaben auf Erledigt, was dazu führt, dass alle Projektaufträge und -phasen denselben Status erhalten:

CREATE TRIGGER upd_project_status_done
         AFTER UPDATE OF status
            ON projects
          WHEN NEW.status = 'Done'
BEGIN
    UPDATE tasks
       SET status = 'Done'
     WHERE id_task IN (
        SELECT t.id_task
          FROM tasks t
               JOIN
               jobs j ON j.id_job = t.id_job
               JOIN
               stages s ON s.id_stage = j.id_stage
               JOIN
               projects p ON p.id_project = s.id_project
         WHERE p.id_project = NEW.id_project AND 
               t.status <> 'Done'
    );
END;

Sobald alle diese Auslöser erstellt sind, müssen wir herausfinden, wie wir die Reihenfolge der Aufgabenausführung festlegen.


Ablauf

Da wir bisher nur mit einem Projekt in der Datenbank gearbeitet haben, wollen wir uns zunächst die Regeln für die Bestimmung der Reihenfolge der Aufgaben in diesem Fall ansehen. Sobald wir verstanden haben, wie die Reihenfolge der Aufgaben für ein Projekt festgelegt wird, können wir über die Reihenfolge der Aufgaben für mehrere gleichzeitig gestartete Projekte nachdenken.

Natürlich können Optimierungsaufgaben, die sich auf dieselbe Aufgabe beziehen und sich nur im Optimierungskriterium unterscheiden, in beliebiger Reihenfolge durchgeführt werden: der sequentielle Start der genetischen Optimierung für verschiedene Kriterien nutzt keine Informationen aus früheren Optimierungen. Um die Vielfalt der gefundenen guten Parameterkombinationen zu erhöhen, werden verschiedene Optimierungskriterien verwendet. Es wurde beobachtet, dass genetische Optimierungen mit denselben Bereichen von versuchten Eingaben, wenn auch mit unterschiedlichen Kriterien, zu unterschiedlichen Kombinationen konvergieren.

Daher ist es nicht erforderlich, der Aufgabentabelle ein Sortierfeld hinzuzufügen. Wir können die Reihenfolge verwenden, in der die Aufgaben eines Auftrags in die Datenbank aufgenommen wurden, d.h. wir können sie nach id_task sortieren.

Wenn es nur eine Aufgabe innerhalb eines Auftrags gibt, hängt die Reihenfolge der Ausführung von der Ausführungsreihenfolge der Aufträge ab. Die Aufträge wurden so konzipiert, dass sie Aufgaben gruppieren oder, genauer gesagt, in verschiedene Kombinationen von Symbolen und Zeitrahmen unterteilen. Betrachten wir ein Beispiel mit drei Symbolen (EURGBP, EURUSD, GBPUSD) und zwei Zeitrahmen (H1, M30) und zwei Phasen (Stage1, Stage2), dann können wir zwei mögliche Aufträge auswählen:

  • Gruppierung nach Symbol und Zeitrahmen:
    • EURGBP H1 Stage1
    • EURGBP H1 Stage2

    • EURGBP M30 Stage1
    • EURGBP M30 Stage2

    • EURUSD H1 Stage1
    • EURUSD H1 Stage2

    • EURUSD M30 Stage1
    • EURUSD M30 Stage2

    • GBPUSD H1 Stage1
    • GBPUSD H1 Stage2

    • GBPUSD M30 Stage1
    • GBPUSD M30 Stage2

  • Gruppierung nach Phasen:
    • Stage1 EURGBP H1
    • Stage1 EURGBP M30
    • Stage1 EURUSD H1
    • Stage1 EURUSD M30
    • Stage1 GBPUSD H1
    • Stage1 GBPUSD M30


    • Stage2 EURGBP H1
    • Stage2 EURGBP M30
    • Stage2 EURUSD H1
    • Stage2 EURUSD M30
    • Stage2 GBPUSD H1
    • Stage2 GBPUSD M30

Mit der ersten Methode der Gruppierung (nach Symbol und Zeitrahmen), nach jedem Abschluss der zweiten Phase, werden wir in der Lage sein, etwas fertig, das heißt, die endgültige EA zu erhalten. Sie enthält Sätze einzelner Kopien von Handelsstrategien für die Symbole und Zeitrahmen, die bereits beide Optimierungsstufen durchlaufen haben.

Bei der zweiten Methode der Gruppierung (durch die Phasen) kann der endgültige EA erst dann auftreten, wenn alle Arbeiten der ersten Phase und mindestens eine Arbeit der zweiten Phase abgeschlossen sind.

Bei Aufträgen, die nur die Ergebnisse der vorherigen Schritte für dasselbe Symbol und denselben Zeitrahmen verwenden, gibt es keinen Unterschied zwischen den beiden Methoden. Aber wenn wir ein wenig in die Zukunft blicken, wird es eine weitere Phase geben, in der die Ergebnisse der zweiten Phasen für verschiedene Symbole und Zeitrahmen kombiniert werden. Wir sind noch nicht so weit, sie als automatische Optimierungsstufe zu implementieren, aber wir haben bereits eine EA-Phase dafür vorbereitet und sie sogar gestartet, wenn auch manuell. Für diese Phase ist die erste Gruppierungsmethode nicht geeignet, sodass wir die zweite Methode verwenden werden.

Es sei darauf hingewiesen, dass es, wenn wir weiterhin die erste Methode verwenden wollen, vielleicht ausreicht, mehrere Projekte für jede Kombination von Symbol und Zeitrahmen zu erstellen. Aber im Moment scheinen die Vorteile unklar zu sein.

Wenn wir also mehrere Aufträge innerhalb einer Phase haben, kann die Reihenfolge ihrer Ausführung beliebig sein, und bei Aufträgen verschiedener Phasen wird die Reihenfolge durch die Reihenfolge der Priorität der Phasen bestimmt. Mit anderen Worten, wie bei den Aufgaben ist es nicht notwendig, der Tabelle der Aufträge ein Sortierfeld hinzuzufügen. Wir können die Reihenfolge verwenden, in der die Aufträge einer Phase in die Datenbank aufgenommen wurden, d.h. wir sortieren sie nach id_job.

Um die Reihenfolge der Phasen zu bestimmen, können wir auch die bereits in der Tabelle der Phasen (stages) vorhandenen Daten verwenden. Ich habe dieser Tabelle das Feld für die übergeordnete Phase (id_parent_stage) ganz am Anfang hinzugefügt, aber es wurde noch nicht verwendet. Wenn wir nur zwei Zeilen in der Tabelle für zwei Phasen haben, ist es kein Problem, sie in der richtigen Reihenfolge zu erstellen - zuerst eine Zeile für die erste Phase und dann für die zweite. Wenn es mehr davon gibt und Phasen für andere Projekte auftauchen, wird es schwieriger, die richtige Reihenfolge manuell einzuhalten.

Nutzen wir also die Gelegenheit, eine Hierarchie von Ausführungsstufen aufzubauen, bei der jede Phase nach Beendigung ihrer übergeordneten Phase ausgeführt wird. Mindestens eine Phase sollte keine übergeordnete Phase haben, um in der Hierarchie an erster Stelle zu stehen. Schreiben wir eine Test-SQL-Abfrage, die Daten aus den Tabellen Aufgaben, Aufträge und Phasen kombiniert und alle Aufgaben der aktuellen Phase anzeigt. Wir fügen alle Felder in die Spaltenliste dieser Abfrage ein, damit wir die vollständigsten Informationen sehen können.

SELECT t.id_task,
       t.optimization_criterion,
       t.status AS task_status,
       j.id_job,
       j.symbol AS job_symbol,
       j.period AS job_period,
       j.tester_inputs AS job_tester_inputs,
       j.status AS job_status,
       s.id_stage,
       s.name AS stage,
       s.expert AS stage_expert,
       s.status AS stage_status,
       ps.name AS parent_stage,
       ps.status AS parent_stage_status,
       p.id_project,
       p.status AS project_status
  FROM tasks t
       JOIN
       jobs j ON j.id_job = t.id_job
       JOIN
       stages s ON s.id_stage = j.id_stage
       LEFT JOIN
       stages ps ON ps.id_stage = s.id_parent_stage
       JOIN
       projects p ON p.id_project = s.id_project
 WHERE t.id_task > 0 AND 
       t.status IN ('Queued', 'Process') AND 
       (ps.id_stage IS NULL OR 
        ps.status = 'Done') 
 ORDER BY j.id_stage,
          j.symbol,
          j.period,
          t.status,
          t.id_task;


Abbildung 1. Ergebnisse einer Abfrage zur Ermittlung von Aufgaben der aktuellen Phase nach dem Start einer Aufgabe

Später werden wir die Anzahl der angezeigten Spalten reduzieren, wenn wir eine ähnliche Abfrage verwenden, um eine andere Aufgabe zu finden. In der Zwischenzeit sollten wir sicherstellen, dass wir die nächste Etappe (mit den dazugehörigen Aufträgen und Aufgaben) korrekt erhalten. Die in Abbildung 1 gezeigten Ergebnisse entsprechen dem Zeitpunkt, zu dem die Aufgabe mit id_task=3 gestartet wurde. Dies ist die Aufgabe, die zu id_job=10 gehört, die Teil von id_stage=10 ist. Diese Phase heißt „First“, gehört zu dem Projekt mit id_project=1 und hat keine übergeordnete Phase (parent_stage=NULL). Wir sehen, dass eine laufende Aufgabe dazu führt, dass der Status Prozess sowohl für die Aufgabe als auch für das Projekt, in dem diese Aufgabe ausgeführt wird, angezeigt wird. Der andere Auftrag mit id_job=5 hat jedoch immer noch den Status „Queued“ (in der Warteschlange), da noch keine der Auftragsaufgaben gestartet wurde.

Versuchen wir nun, die erste Aufgabe zu erledigen (indem wir das Statusfeld in der Tabelle einfach auf Done setzen), und sehen wir uns die Ergebnisse der gleichen Abfrage an:

Abb. 2. Ergebnisse einer Abfrage zur Ermittlung von Aufgaben der aktuellen Phase nach Abschluss einer laufenden Aufgabe

Wie Sie sehen, ist die abgeschlossene Aufgabe aus der Liste verschwunden, und die oberste Zeile wird nun von einer anderen Aufgabe eingenommen, die als Nächstes gestartet werden kann. So weit ist alles korrekt. Starten und erledigen wir nun die ersten beiden Aufgaben aus dieser Liste, und starten wir die dritte Aufgabe mit id_task=7 zur Ausführung:

Abb. 3. Ergebnisse einer Abfrage, um die Aufgaben der aktuellen Phase zu erhalten, nachdem die Aufgaben des ersten Auftrags abgeschlossen sind und die nächste Aufgabe begonnen wurde

Jetzt hat der Auftrag mit id_job=5 den Status Process erhalten. Als Nächstes führen wir die drei Aufgaben aus, die jetzt in den Ergebnissen der letzten Abfrage angezeigt werden, und erledigen sie. Sie werden nach und nach aus den Abfrageergebnissen verschwinden. Nachdem die letzte Abfrage abgeschlossen ist, führen wir die Abfrage erneut aus und erhalten das folgende Ergebnis:

Abb. 4. Ergebnisse einer Abfrage, um die Aufgaben der aktuellen Phase zu erhalten, nachdem alle Aufgaben der ersten Phase erledigt sind

Die Abfrageergebnisse enthalten nun Aufgaben aus den Aufträgen der folgenden Phasen. id_stage=2 ist die Gruppierung der Ergebnisse der ersten Phase, während id_stage=3 die zweite Phase ist, auf der die Gruppierung der guten Beispiele für Handelsstrategien aus der ersten Phase erfolgt. In dieser Phase wird kein Clustering verwendet, sodass sie unmittelbar nach der ersten Phase durchgeführt werden kann. Es ist also kein Fehler, dass es auf dieser Liste steht. Beide Phasen haben eine übergeordnete Phase mit dem Namen First, die sich jetzt im Zustand Done befindet. 

Simulieren wir den Start und den Abschluss der ersten beiden Aufgaben und betrachten wir die Abfrageergebnisse erneut:

Abb. 5. Ergebnisse einer Abfrage, um Aufgaben zu erhalten, nachdem alle Aufgaben der Clustering-Phase abgeschlossen sind

Die obersten Zeilen der Ergebnisse werden erwartungsgemäß von zwei Aufgaben der zweiten Phase (genannt „Second“) belegt, aber die letzten beiden Zeilen enthalten nun Aufgaben der zweiten Phase mit Clustering (genannt „Second with clustering“). Ihr Auftreten ist etwas unerwartet, widerspricht aber nicht der zulässigen Reihenfolge. Wenn wir das Clustering bereits abgeschlossen haben, können wir auch die Phase starten, in der die Ergebnisse des Clustering verwendet werden. Die beiden Schritte, die in den Abfrageergebnissen angezeigt werden, sind unabhängig voneinander, sodass sie in beliebiger Reihenfolge durchgeführt werden können.

Lassen Sie uns jede Aufgabe noch einmal ausführen und abschließen, wobei wir jeweils die oberste Aufgabe in den Ergebnissen auswählen. Die Liste der Aufgaben, die nach jeder Statusänderung empfangen wurde, verhielt sich wie erwartet, die Status von Aufträgen und Phasen änderten sich korrekt. Nach Abschluss der letzten Aufgabe waren die Abfrageergebnisse leer, da alle zugewiesenen Aufgaben aller Aufträge aller Phasen abgeschlossen waren und das Projekt in den Status Erledigt überging.

Lassen Sie uns diese Abfrage in den optimierenden EA integrieren.


Modifikation des optimierenden EA

Wir müssen Änderungen an der Methode zum Abrufen der ID der nächsten Optimierungsaufgabe vornehmen, wenn es bereits eine SQL-Abfrage gibt, die diese Aufgabe ausführt. Nehmen wir die oben entwickelte Abfrage und entfernen die zusätzlichen Felder, sodass nur id_task übrig bleibt. Wir können auch die Sortierung nach einigen Feldern der Jobtabelle (j.symbol, j.period) durch j.id_job ersetzen, da jeder Job nur einen Wert in diesen beiden Feldern hat. Am Ende fügen wir eine Begrenzung der Anzahl der zurückgegebenen Zeilen hinzu. Wir benötigen nur eine Zeile.

Die Methode GetNextTaskId() sieht nun wie folgt aus:

//+------------------------------------------------------------------+
//| Get the ID of the next optimization task from the queue          |
//+------------------------------------------------------------------+
ulong COptimizer::GetNextTaskId() {
// Result
   ulong res = 0;

// Request to get the next optimization task from the queue
   string query = "SELECT t.id_task"
                  "  FROM tasks t "
                  "       JOIN "
                  "       jobs j ON j.id_job = t.id_job "
                  "       JOIN "
                  "       stages s ON s.id_stage = j.id_stage "
                  "       LEFT JOIN "
                  "       stages ps ON ps.id_stage = s.id_parent_stage "
                  "       JOIN "
                  "       projects p ON p.id_project = s.id_project "
                  " WHERE t.id_task > 0 AND "
                  "       t.status IN ('Queued', 'Process') AND "
                  "       (ps.id_stage IS NULL OR "
                  "        ps.status = 'Done') "
                  " ORDER BY j.id_stage, "
                  "          j.id_job, "
                  "          t.status, "
                  "          t.id_task"
                  " LIMIT 1;";

// ... here we get the query result

   return res;
}

Da wir uns entschieden haben, mit dieser Datei zu arbeiten, nehmen wir eine weitere Änderung vor: Wir entfernen die Übergabe des Status über den Methodenparameter aus der Methode zur Ermittlung der Anzahl der Aufgaben in der Warteschlange. In der Tat verwenden wir diese Methode nie, um die Anzahl der Aufgaben mit dem Status „Queued“ und „Process“ zu ermitteln, die dann einzeln und nicht als Summe verwendet werden. Ändern wir also die SQL-Abfrage in der Methode TotalTasks() so, dass sie immer die Gesamtzahl der Aufgaben mit diesen beiden Status zurückgibt, und entfernen wir die Statuseingabe der Methode:

//+------------------------------------------------------------------+
//| Get the number of tasks with the specified status                |
//+------------------------------------------------------------------+
int COptimizer::TotalTasks() {
// Result
   int res = 0;

// Request to get the number of tasks with the specified status
   string query = "SELECT COUNT(*)"
                  "  FROM tasks t"
                  "       JOIN"
                  "       jobs j ON t.id_job = j.id_job"
                  "       JOIN"
                  "       stages s ON j.id_stage = s.id_stage"
                  " WHERE t.status IN ('Queued', 'Process') "
                  " ORDER BY s.id_stage, j.id_job, t.status LIMIT 1;";

// ... here we get the query result
   
   return res;
}

Speichern wir die Änderungen in der Datei Optimizer.mqh des aktuellen Ordners.

Zusätzlich zu diesen Änderungen müssen wir auch die alte Statusbezeichnung „Processing“ in mehreren Dateien durch „Process“ ersetzen, da wir uns oben darauf geeinigt haben, sie zu verwenden. 

Es wäre auch nützlich, die Möglichkeit zu haben, Informationen über Fehler zu erhalten, die während der Ausführung der Aufgabe, die das Python-Programm startet, aufgetreten sind. Wenn ein solches Programm abnormal beendet wird, bleibt der optimierende EA einfach in der Phase stecken, in der er darauf wartet, dass die Aufgabe abgeschlossen wird, oder genauer gesagt, dass Informationen über dieses Ereignis in der Datenbank erscheinen. Wenn das Programm mit einem Fehler endet, kann es den Aufgabenstatus in der Datenbank nicht aktualisieren. Dadurch kann sich der Ablauf in diesem Stadium nicht fortsetzen. 

Bisher besteht die einzige Möglichkeit, dieses Hindernis zu überwinden, darin, das Python-Programm manuell mit den in der Aufgabe angegebenen Parametern erneut auszuführen, die Fehlerursachen zu analysieren, sie zu beseitigen und das Programm erneut auszuführen.


Änderungen von SimpleVolumesStage3.mq5

Als Nächstes planten wir, die dritte Phase zu automatisieren, in der wir für jeden Auftrag der zweiten Phase (die sich durch das verwendete Symbol und den Zeitrahmen unterscheiden) den besten Durchlauf zur Aufnahme in den endgültigen EA auswählen.

Bislang hat der EA für Phase 3 eine Liste von Phase-2-Pass-IDs als Eingabe verwendet, und wir mussten diese IDs irgendwie manuell aus der Datenbank auswählen. Abgesehen davon hat dieser EA nur die Erstellung, die Bewertung der Inanspruchnahme und die Speicherung einer Gruppe dieser Pässe in der Bibliothek durchgeführt. Die endgültige EA wurde nicht als Ergebnis des Starts der dritten Phase der EA erstellt, da eine Reihe anderer Maßnahmen erforderlich war. Wir werden später auf die Automatisierung dieser Aktionen zurückkommen, aber jetzt wollen wir erst einmal die dritte Phase des EA modifizieren.

Es gibt verschiedene Methoden, die zur automatischen Auswahl von Pass-IDs verwendet werden können.

Zum Beispiel können wir aus allen Ergebnissen der Durchgänge, die wir im Rahmen einer Arbeit der zweiten Phase erhalten haben, den besten im Hinblick auf den Indikator des normalisierten durchschnittlichen Jahresgewinns auswählen. Ein solcher Durchlauf wiederum ist das Ergebnis einer Gruppe von 16 einzelnen Instanzen von Handelsstrategien. Der endgültige EA wird dann eine Gruppe von mehreren Gruppen von Instanzen einzelner Strategien enthalten. Wenn wir drei Symbole und zwei Zeitrahmen nehmen, dann haben wir in der zweiten Phase 6 Aufträge. In der dritten Phase erhalten wir dann eine Gruppe, die 6 * 16 = 96 Kopien einzelner Strategien umfasst. Diese Methode ist am einfachsten zu realisieren.

Ein Beispiel für eine komplexere Auswahlmethode ist folgende: Für jeden Auftrag der zweiten Phase nehmen wir eine Anzahl der besten Durchgänge und versuchen verschiedene Kombinationen aus allen ausgewählten Durchgängen. Dies ist sehr ähnlich zu dem, was wir in der zweiten Phase gemacht haben, nur dass wir jetzt eine Gruppe nicht aus 16 einzelnen Instanzen rekrutieren, sondern aus 6 Gruppen, und in der ersten der sechs Gruppen nehmen wir einen der besten Durchgänge des ersten Jobs, in der zweiten - einen der besten Durchgänge des zweiten Jobs, und so weiter. Diese Methode ist komplizierter, aber es ist unmöglich, im Voraus zu sagen, dass sie die Ergebnisse erheblich verbessern wird.

Daher werden wir zunächst die einfachere Methode anwenden und die kompliziertere auf später verschieben.

In diesem Stadium brauchen wir die EA-Parameter nicht mehr zu optimieren. Dies wird nun ein einziger Durchgang sein. Dazu müssen wir die entsprechenden Parameter in den Phaseneinstellungen in der Datenbank angeben: Die Optimierungsspalte sollte 0 sein.

Abb. 6. Inhalt der Tabelle „stages“

Im EA-Code fügen wir die ID der Optimierungsaufgabe zu den Eingaben hinzu, damit dieser EA in der Förderanlage gestartet werden kann und die Ergebnisse des Durchlaufs korrekt in der Datenbank gespeichert werden:

//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
sinput int      idTask_  = 0;       // - Optimization task ID
sinput string fileName_  = "database911.sqlite"; // - File with the main database

input group "::: Selection for the group"
input string     passes_ = "";      // - Comma-separated pass IDs

input group "::: Saving to library"
input string groupName_  = "";      // - Group name (if empty - no saving)

Der Parameter passes_ kann entfernt werden, aber ich lasse ihn vorsichtshalber noch stehen. Schreiben wir eine SQL-Abfrage, die eine Liste der besten Pass-IDs für die Aufträge der zweiten Phase liefert. Wenn der Parameter passes_ leer ist, werden die IDs der besten Pässe verwendet. Wenn der Parameter passes_ bestimmte IDs weitergibt, werden diese angewendet.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
// Set parameters in the money management class
   CMoney::DepoPart(expectedDrawdown_ / 10.0);
   CMoney::FixedBalance(fixedBalance_);
   CTesterHandler::TesterInit(idTask_, fileName_);

// Initialization string with strategy parameter sets
   string strategiesParams = NULL;

// If the connection to the main database is established,
   if(DB::Connect(fileName_)) {
      // Form a request to receive passes with the specified IDs
      string query = (passes_ == "" ?
                      StringFormat("SELECT DISTINCT FIRST_VALUE(p.params) OVER (PARTITION BY p.id_task ORDER BY custom_ontester DESC) AS params "
                                   "  FROM passes p "
                                   " WHERE p.id_task IN ("
                                   "           SELECT pt.id_task "
                                   "             FROM tasks t "
                                   "                  JOIN "
                                   "                  jobs j ON j.id_job = t.id_job "
                                   "                  JOIN "
                                   "                  stages s ON s.id_stage = j.id_stage "
                                   "                  JOIN "
                                   "                  jobs pj ON pj.id_stage = s.id_parent_stage "
                                   "                  JOIN "
                                   "                  tasks pt ON pt.id_job = pj.id_job "
                                   "            WHERE t.id_task = %d "
                                   " ) ", idTask_)
                      : StringFormat("SELECT params"
                                     "  FROM passes "
                                     " WHERE id_pass IN (%s);", passes_)
                     );

      Print(query);
      int request = DatabasePrepare(DB::Id(), query);

      if(request != INVALID_HANDLE) {
         // Structure for reading results
         struct Row {
            string         params;
         } row;

         // For all query result strings, concatenate initialization rows 
         while(DatabaseReadBind(request, row)) {
            strategiesParams += row.params + ",";
         }
      }
      DB::Close();
   }

// ... 

// Successful initialization
   return(INIT_SUCCEEDED);
}

Wir speichern die an der Datei SimpleVolumesStage3.mq5 vorgenommenen Änderungen im aktuellen Ordner.

Damit sind die Änderungen der dritten Phase der EA abgeschlossen. Verschieben wir das Projekt in der Datenbank in die Warteschlange und starten wir den optimierenden EA.


Optimierung der Ablaufergebnisse

Obwohl wir noch nicht alle geplanten Schritte umgesetzt haben, verfügen wir jetzt schon über ein Werkzeug, das automatisch einen fast fertigen EA liefert. Nach Abschluss der dritten Phase haben wir zwei Einträge in der Parameter-Bibliothek (Tabelle strategy_groups):

Der erste enthält die ID des Durchgangs, in dem die besten Gruppen der zweiten Phase ohne Clustering zusammengefasst werden. Die zweite ist die ID des Durchgangs, in dem die besten Gruppen der zweiten Phase mit Clustering zusammengefasst werden. Dementsprechend können wir für diese Pass-IDs die Initialisierungszeichenfolgen aus der Tabelle passes abrufen und die Ergebnisse dieser beiden Kombinationen betrachten.

Abb. 7. Ergebnisse der kombinierten Gruppe von Instanzen, die ohne Clustering ermittelt wurden


Abb. 8. Ergebnisse der kombinierten Gruppe von Instanzen, die durch Clustering erhalten wurden

Die Variante ohne Clustering zeigt den höheren Gewinn. Die Variante mit Clustering weist jedoch eine höhere Sharpe Ratio und eine bessere Linearität auf. Wir werden diese Ergebnisse jedoch vorerst nicht im Detail analysieren, da sie noch nicht endgültig sind.

Der nächste Schritt ist das Hinzufügen von Phasen für den Zusammenbau des endgültigen EA. Wir müssen die Bibliothek exportieren, um die Include-Datei ExportedGroupsLibrary.mqh im Datenordner zu erhalten. Dann sollten wir diese Datei in den Arbeitsordner kopieren. Dieser Vorgang kann entweder mit einem Python-Programm oder mit den Systemkopierfunktionen der DLL durchgeführt werden. In der letzten Phase müssen wir nur noch den endgültigen EA kompilieren und das Terminal mit der neuen EA-Version starten.

All dies erfordert eine beträchtliche Menge an Zeit für die Umsetzung, sodass wir die Beschreibung im nächsten Artikel fortsetzen werden.



Schlussfolgerung

Schauen wir uns also an, was wir haben. Wir haben die automatische Ausführung der ersten Phasen des automatischen OptimierungsAblaufs in Auftrag gegeben und deren korrekte Funktionsweise erreicht. Wir können uns die Zwischenergebnisse ansehen und z. B. entscheiden, den Schritt des Clusterns aufzugeben. Oder aber Sie lassen es und entfernen die Option ohne Clustering.

Mit einem solchen Instrument können wir in Zukunft Experimente durchführen und versuchen, schwierige Fragen zu beantworten. Nehmen wir zum Beispiel an, dass wir in der ersten Phase eine Optimierung für verschiedene Bereiche von Eingaben durchführen. Was ist besser - sie getrennt oder zusammen mit denselben Symbolen und Zeitrahmen zu kombinieren?

Durch das Hinzufügen von Phasen zum Ablauf können wir die schrittweise Montage von immer komplexeren EA realisieren.

Schließlich können wir die Frage der partiellen Re-Optimierung und sogar der kontinuierlichen Re-Optimierung durch die Durchführung eines entsprechenden Experiments prüfen. Re-Optimierung bedeutet hier die wiederholte Optimierung in einem anderen Zeitintervall. Aber dazu beim nächsten Mal mehr.

Vielen Dank für Ihre Aufmerksamkeit! Bis bald!


Wichtige Warnung

Alle in diesem Artikel und in allen vorangegangenen Artikeln dieser Reihe vorgestellten Ergebnisse beruhen lediglich auf historischen Testdaten und sind keine Garantie für zukünftige Gewinne. Die Arbeiten im Rahmen dieses Projekts haben Forschungscharakter. Alle veröffentlichten Ergebnisse können von jedermann auf eigenes Risiko verwendet werden.


Inhalt des Archivs

#
 Name
Version  Beschreibung   Jüngste Änderungen
 MQL5/Experten/Artikel.16134
1 Advisor.mqh 1.04 EA-Basisklasse Teil 10
2 ClusteringStage1.py 1.01 Programm zum Clustern der Ergebnisse der ersten Optimierungsstufe Teil 20
3 Database.mqh 1.07 Klasse für den Umgang mit der Datenbank Teil 19
4 database.sqlite.schema.sql 1.05
Struktur der Datenbank Teil 20
5 ExpertHistory.mqh 1.00. Klasse für den Export der Handelshistorie in eine Datei Teil 16
6 ExportedGroupsLibrary.mqh
Generierte Datei mit den Namen der Strategiegruppen und dem Array ihrer Initialisierungszeichenfolgen Teil 17
7 Factorable.mqh 1.02 Basisklasse von Objekten, die aus einer Zeichenkette erstellt werden Teil 19
8 GroupsLibrary.mqh 1.01 Klasse für die Arbeit mit einer Bibliothek ausgewählter Strategiegruppen Teil 18
9 HistoryReceiverExpert.mq5 1.00. EA für die Wiedergabe der Historie von Geschäften mit dem Risikomanager Teil 16  
10 HistoryStrategy.mqh  1.00. Klasse der Handelsstrategie für die Wiederholung der Handelshistorie  Teil 16
11 Interface.mqh 1.00. Basisklasse zur Visualisierung verschiedener Objekte Teil 4
12 LibraryExport.mq5 1.01 EA, der Initialisierungszeichenfolgen ausgewählter Durchläufe aus der Bibliothek in der Datei ExportedGroupsLibrary.mqh speichert Teil 18
13 Macros.mqh 1.02 Nützliche Makros für Array-Operationen Teil 16  
14 Money.mqh 1.01  Grundkurs Geldmanagement Teil 12
15 NewBarEvent.mqh 1.00.  Klasse zur Definition eines neuen Balkens für ein bestimmtes Symbol  Teil 8
16 Optimization.mq5  1.03 EA verwaltet die Einleitung von Optimierungsaufgaben Teil 19
17 Optimizer.mqh 1.01 Klasse für den Projektautooptimierungsmanager Teil 20
18 OptimizerTask.mqh 1.01 Klasse der Optimierungsaufgaben Teil 20
19 Receiver.mqh 1.04  Basisklasse für die Umwandlung von offenen Volumina in Marktpositionen  Teil 12
20 SimpleHistoryReceiverExpert.mq5 1.00. Vereinfachter EA für die Wiedergabe des Geschäftsverlaufs   Teil 16
21 SimpleVolumesExpert.mq5 1.20 EA für den parallelen Betrieb von mehreren Gruppen von Modellstrategien. Die Parameter werden aus der integrierten Gruppenbibliothek übernommen. Teil 17
22 SimpleVolumesStage1.mq5
1.18 Handelsstrategie Einzelinstanzoptimierung EA (Phase 1)  Teil 19
23 SimpleVolumesStage2.mq5
1.02 Handelsstrategien Instanzen Gruppe Optimierung EA (Phase 2)
Teil 19
24 SimpleVolumesStage3.mq5 1.02 Der EA, der eine generierte standardisierte Gruppe von Strategien in einer Bibliothek von Gruppen mit einem bestimmten Namen speichert. Teil 20
25 SimpleVolumesStrategy.mqh 1.09  Klasse der Handelsstrategie mit Tick-Volumen Teil 15
26 Strategy.mqh 1.04  Handelsstrategie-Basisklasse Teil 10
27 TesterHandler.mqh  1.05 Klasse zur Behandlung von Optimierungsereignissen  Teil 19  
28 VirtualAdvisor.mqh  1.07  Klasse des EA, der virtuelle Positionen (Aufträge) bearbeitet Teil 18
29 VirtualChartOrder.mqh  1.01  Grafische virtuelle Positionsklasse Teil 18  
30 VirtualFactory.mqh 1.04  Objekt-Fabrik-Klasse  Teil 16
31 VirtualHistoryAdvisor.mqh 1.00.  Die Klasse des EA zur Wiederholung des Handelsverlaufs  Teil 16
32 VirtualInterface.mqh  1.00.  EA GUI-Klasse  Teil 4  
33 VirtualOrder.mqh 1.07  Klasse der virtuellen Aufträge und Positionen  Teil 19
34 VirtualReceiver.mqh 1.03  Klasse für die Umwandlung von offenen Volumina in Marktpositionen (Empfänger)  Teil 12
35 VirtualRiskManager.mqh  1.02  Klasse Risikomanagement (Risikomanager)  Teil 15
36 VirtualStrategy.mqh 1.05  Klasse einer Handelsstrategie mit virtuellen Positionen  Teil 15
37 VirtualStrategyGroup.mqh  1.00.  Klasse der Handelsstrategien Gruppe(n) Teil 11 
38 VirtualSymbolReceiver.mqh  1.00. Symbol-Empfängerklasse  Teil 3

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

Beigefügte Dateien |
MQL5.zip (90.37 KB)
Letzte Kommentare | Zur Diskussion im Händlerforum (8)
CapeCoddah
CapeCoddah | 4 Dez. 2024 in 12:34

Hallo Yuriy

ich habe Google Translate benutzt, um zu Teil 20 zu gelangen. Googeln Sie "Google Translate" und öffnen Sie eine neue Registerkarte im Browser. In der Suchleiste ganz rechts wird ein Symbol angezeigt. Laden Sie die Seite in ihrer Muttersprache und drücken Sie auf das Symbol, um die Sprache des Artikels und die Sprache, in die übersetzt werden soll, auszuwählen. Und schon bin ich bei Teil 20! Die Übersetzung ist zwar nicht perfekt, aber zu 99 % nützlich.

Ich habe Ihre Archivquelle in Excel geladen und ein paar Spalten zum Sortieren hinzugefügt, um den Inhalt zu ordnen. Neben der Sortierung in Excel kann die Tabelle auch direkt in eine OutLook-Datenbank importiert werden.


Ich habe Probleme, den Startartikel für die Einrichtung der SQL-Datenbank zu identifizieren. Ich habe versucht, Simple Volume Stage 1 auszuführen und erhielt eine flache Linie, was mir zeigt, dass ich wahrscheinlich zurückgehen und eine andere SQL-Datenbank erstellen muss. Es wäre äußerst hilfreich, eine Tabelle mit der Reihenfolge der Ausführung der erforderlichen Programme zu haben, um ein funktionierendes System zu erhalten. Vielleicht könnte man sie in die Tabelle der Archivquellen aufnehmen.

Eine weitere kleine Bitte ist die Verwendung der <>-Option für Include-Dateispezifikationen anstelle von "". Ich halte Ihr System in meinen Verzeichnissen Experts und Include getrennt, #include <!!!! MultiCurrency\VirtualAdvisor.mqh>, so dass diese Änderung das Hinzufügen der Unterverzeichnisspezifikation/ erleichtern wird.

Vielen Dank für Ihren Beitrag

CapeCoddah

Yuriy Bykov
Yuriy Bykov | 5 Dez. 2024 in 09:54

Hallo.

Über die anfängliche Befüllung der Datenbank mit Informationen über das Projekt, die Phasen, Arbeiten und Aufgaben können Sie in den Teilen 13, 18 und 19 lesen. Dies ist nicht das Hauptthema, so dass die Informationen, die Sie benötigen, irgendwo näher am Ende der Artikel zu finden sind. Zum Beispiel in Teil 18:

Проверив, что в базу данных теперь корректно попадают результаты проходов, совершаемых с использованием форвард-периода, проведём более приближенный к реальным условиям тест работы автоматической оптимизации. Для этого в чистую базу данных добавим уже два этапа. На первом будет оптимизироваться одиночный экземпляр торговой стратегии, но только на одном символе и периоде (EURGBP H1) на промежутке 2018 - 2023 годов. Форвард-период на этом этапе использоваться не будет. На втором этапе будет оптимизироваться группа из хороших одиночных экземпляров, полученных на первом этапе. Теперь форвард период уже будет использоваться: под него отводится весь 2023 год.

Oder in Teil 19:

Legen wir für unser Projekt vier Stufen in der Datenbank an, die wir "Erste", "Clustering Pässe der ersten Stufe", "Zweite" und "Zweite mit Clustering" nennen. Für jede Phase werden wir zwei Werke für EURGBP- und GBPUSD-Symbole auf dem H1-Zeitrahmen erstellen. Für die Arbeiten der ersten Stufe werden wir drei Optimierungsaufgaben mit unterschiedlichen Kriterien (komplex, maximaler Gewinn und benutzerdefiniert) erstellen. Für den Rest der Arbeiten werden wir jeweils eine Aufgabe erstellen. Als Optimierungsintervall nehmen wir den Zeitraum von 2018 bis 2023. Für jede Aufgabe werden wir die richtigen Werte der Eingabeparameter angeben.

Oder Sie warten auf den nächsten Artikel, der sich unter anderem mit der Erstbefüllung der Datenbank mit Hilfe eines Hilfsskripts befassen wird.

Die Umstellung auf die Verwendung des Include-Ordners für die Speicherung von Bibliotheksdateien ist geplant, aber es ist noch nicht so weit.

CapeCoddah
CapeCoddah | 5 Dez. 2024 in 10:44
Yuriy Bykov Speicherung der Bibliothek ist zwar geplant, aber bisher noch nicht erfolgt.

Vielen Dank

CapeCoddah
CapeCoddah | 6 Dez. 2024 in 11:39

Hallo Yuriy,

Haben Sie den nächsten Artikel eingereicht oder wissen Sie, wann er veröffentlicht wird?

Yuriy Bykov
Yuriy Bykov | 8 Dez. 2024 in 18:24
Hallo, höchstwahrscheinlich in etwa einem Monat.
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.
Neuronale Netze im Handel: Optimierung des Transformers für Zeitreihenprognosen (LSEAttention) Neuronale Netze im Handel: Optimierung des Transformers für Zeitreihenprognosen (LSEAttention)
Der LSEAttention-Rahmen bietet Verbesserungen der Transformer-Architektur. Es wurde speziell für langfristige multivariate Zeitreihenprognosen entwickelt. Die von den Autoren der Methode vorgeschlagenen Ansätze können angewandt werden, um Probleme des Entropiekollapses und der Lerninstabilität zu lösen, die bei einem einfachen Transformer häufig auftreten.
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.
Von der Grundstufe bis zur Mittelstufe: Rekursion Von der Grundstufe bis zur Mittelstufe: Rekursion
In diesem Artikel werden wir uns mit einem sehr interessanten und recht anspruchsvollen Programmierkonzept befassen, das allerdings mit großer Vorsicht zu genießen ist, da sein Missbrauch oder Missverständnis relativ einfache Programme in etwas unnötig Komplexes verwandeln kann. Aber wenn sie richtig eingesetzt und perfekt an geeignete Situationen angepasst wird, ist die Rekursion ein hervorragender Verbündeter bei der Lösung von Problemen, die sonst viel mühsamer und zeitaufwändiger wären. Die hier vorgestellten Materialien sind ausschließlich für Bildungszwecke bestimmt. Die Anwendung sollte unter keinen Umständen zu einem anderen Zweck als zum Erlernen und Beherrschen der vorgestellten Konzepte verwendet werden.