English Русский 中文 Español 日本語 Português
preview
Erstellen eines EA, der automatisch funktioniert (Teil 14): Automatisierung (VI)

Erstellen eines EA, der automatisch funktioniert (Teil 14): Automatisierung (VI)

MetaTrader 5Handel | 29 Juni 2023, 10:27
348 0
Daniel Jose
Daniel Jose

Einführung

Im vorhergehenden Artikel „Erstellen eines EA, der automatisch arbeitet (Teil 13): Automation (V)“ habe ich erklärt, wie ein Händler auch ohne Programmierkenntnisse die nötigen Grundlagen schaffen kann, um ein Handelssystem in einen automatisierten EA umzuwandeln. Das ist es, was wir in dieser Artikelserie getan haben. Diese Konzepte und Informationen gelten für jeden EA, auch für den von Ihnen erstellten. In diesem Artikel werden wir eine der vielen Möglichkeiten zur Bewältigung dieser Aufgabe betrachten.

Es ist sehr wichtig, den Inhalt des vorhergehenden Artikels vollständig zu verstehen, um wirklich zu begreifen, was wir hier besprechen werden. Ohne dieses Wissen könnte es schwierig sein, den Inhalt dieses Artikels zu verstehen. Wenn Sie also den vorherigen Artikel noch nicht gelesen haben, empfehle ich Ihnen, ihn zu lesen, bevor Sie fortfahren. Kommen wir nun zum Hauptthema des Artikels: wie man einen ursprünglich manuellen Expert EA in einen automatisierten umwandelt.


Die Geburt der Klasse C_Automaton

Die folgende Abbildung haben wir bereits in einem früheren Artikel gesehen:

Abbildung 01

Abbildung 01 - Manueller Modus

In dieser Abbildung sehen wir, wie der Händler mit der Plattform interagiert, um Positionen auf dem Handelsserver zu öffnen und zu schließen. Um diesen Prozess zu automatisieren, müssen wir einige Änderungen an dieser Abbildung vornehmen. So wird aus der Abbildung 01, die das manuelle Modell darstellt, die Abbildung 02. Diese Abbildung stellt einen EA dar, der automatisch auf der Grundlage einiger operativer Regeln arbeitet, die in der Programmierphase definiert wurden.

Abbildung 02

Abbildung 02 - Automatischer Modus

Achten Sie darauf, dass in Abbildung 02 eine Person abgebildet ist, die als Systembetreuer fungiert. Ein automatisiertes System sollte nie unbeaufsichtigt betrieben werden. Der Händler muss den Prozess immer kontrollieren, auch wenn er nur zuschaut und sonst nichts tut.

Die gleiche Abbildung enthält eine zusätzliche Klasse zwischen der EA- und der C_Manager-Klasse, die C_Automaton genannt wird. Dieser Artikel befasst sich hauptsächlich mit dieser Klasse und ihrer Verbindung mit dem EA und der Klasse C_Manager, die den Händler beim Öffnen und Schließen von Positionen oder beim Platzieren von Pending Orders im Orderbuch ersetzt.

Auch hier ist es wichtig zu erwähnen, dass wir keine Änderungen am bestehenden System vornehmen, das bereits korrekt, sicher, zuverlässig, robust und stabil funktionieren sollte, bevor wir die Klasse C_Automaton implementieren. Und wenn Sie etwas am System selbst ändern wollen, sollten Sie die Klasse C_Automaton entfernen, C_Mouse wiederherstellen und das System mit allen Änderungen testen. Erst wenn Sie sicher sind, dass das System einwandfrei funktioniert, können Sie die Klasse C_Automaton wieder hinzufügen, damit der EA ohne menschliches Zutun funktioniert. Aber denken Sie immer daran, dass eine Überwachung notwendig ist. Menschliches Eingreifen sollte das letzte Mittel sein, aber es sollte ständig überwacht werden.

Bevor wir uns ansehen, wie der C_Automaton programmiert ist, werfen wir einen Blick auf den EA-Code, der für die automatische Verwendung modifiziert wurde. Der vollständige EA-Code wird unten angezeigt:

#property copyright "Daniel Jose"
#property description "This one is an automatic Expert Advisor"
#property description "for demonstration. To understand how to"
#property description "develop yours in order to use a particular"
#property description "operational, see the articles where there"
#property description "is an explanation of how to proceed."
#property version   "1.14"
#property link      "https://www.mql5.com/pt/articles/11318"
//+------------------------------------------------------------------+
#include <Generic Auto Trader\C_Automaton.mqh>
//+------------------------------------------------------------------+
C_Automaton *automaton;
//+------------------------------------------------------------------+
input int       user01   = 1;           //Leverage Factor
input double    user02   = 100;         //Take Profit ( FINANCE )
input double    user03   = 75;          //Stop Loss ( FINANCE )
input bool      user04   = true;        //Day Trade ?
input double    user08   = 35;          //BreakEven ( FINANCE )
//+------------------------------------------------------------------+
input string    user90  = "00:00 - 00:00";      //Sunday
input string    user91  = "09:05 - 17:35";      //Monday
input string    user92  = "10:05 - 16:50";      //Tuesday
input string    user93  = "09:45 - 13:38";      //Wednesday
input string    user94  = "11:07 - 15:00";      //Thursday
input string    user95  = "12:55 - 16:25";      //Friday
input string    user96  = "00:00 - 00:00";      //Saturday
//+------------------------------------------------------------------+
#define def_MAGIC_NUMBER 987654321
//+------------------------------------------------------------------+
int OnInit()
{
        string szInfo;
        
        automaton = new C_Automaton(def_MAGIC_NUMBER, user03, user02, user01, user04, user08, PERIOD_M5);
        for (ENUM_DAY_OF_WEEK c0 = SUNDAY; c0 <= SATURDAY; c0++)
        {
                switch (c0)
                {
                        case SUNDAY     : szInfo = user90; break;
                        case MONDAY     : szInfo = user91; break;
                        case TUESDAY    : szInfo = user92; break;
                        case WEDNESDAY  : szInfo = user93; break;
                        case THURSDAY   : szInfo = user94; break;
                        case FRIDAY     : szInfo = user95; break;
                        case SATURDAY   : szInfo = user96; break;
                }
                (*automaton).SetInfoCtrl(c0, szInfo);
        }
        (*automaton).CheckToleranceLevel();
        EventSetMillisecondTimer(100);

        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        delete automaton;
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick() { }
//+------------------------------------------------------------------+
void OnTimer()
{
        (*automaton).Triggers();
}
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result)
{
        switch (trans.type)
        {
                case TRADE_TRANSACTION_POSITION:
                        (*automaton).UpdatePosition(trans.position);
                        break;
                case TRADE_TRANSACTION_ORDER_DELETE:
                        if (trans.order == trans.position) (*automaton).PendingToPosition();
                        else
                        {
                                (*automaton).UpdatePosition(trans.position);
                                (*automaton).EraseTicketPending(trans.order);
                        }
                        break;
                case TRADE_TRANSACTION_ORDER_UPDATE:
                        (*automaton).UpdatePending(trans.order);
                        break;
                case TRADE_TRANSACTION_REQUEST: if ((request.symbol == _Symbol) && (result.retcode == TRADE_RETCODE_DONE) && (request.magic == def_MAGIC_NUMBER)) switch (request.action)
                        {
                                case TRADE_ACTION_DEAL:
                                        (*automaton).UpdatePosition(request.order);
                                        break;
                                case TRADE_ACTION_SLTP:
                                        (*automaton).UpdatePosition(trans.position);
                                        break;
                                case TRADE_ACTION_REMOVE:
                                        (*automaton).EraseTicketPending(request.order);
                                        break;
                        }
                        break;
        }
}
//+------------------------------------------------------------------+

Beachten Sie, dass an diesem Code nur wenige Änderungen vorgenommen wurden. Die Ereignisbehandlung OnChartEvent wurde entfernt, da er nicht mehr benötigt wird und das Ereignis OnTime eine neue Funktion erhalten hat. Weitere Einzelheiten werden zu einem späteren Zeitpunkt bekannt gegeben. Der Rest des Codes blieb derselbe wie im vorherigen manuellen Betriebsmodus. Es ist äußerst wichtig zu beachten, dass Sie nicht den gesamten EA-Code ändern sollten, wenn Sie ihn automatisieren. Sie sollten nur die notwendigen Änderungen vornehmen, was in unserem Fall nur das Hinzufügen einer neuen Funktion im Zeitereignis bedeutet.

Trotz allem ist dieser EA-Code KEIN endgültiger und unveränderlicher Code. Je nach dem System, das Sie verwenden werden, kann es mehr oder weniger Dinge geben, die vom Nutzer definiert werden müssen, was wir hier sehen werden. Daher kann es Variationen in den Konstruktoren der Klasse C_Automaton geben. Sie können also mehr oder weniger Parameter benötigen. Glauben Sie also nicht, dass dieser Code in allen möglichen Fällen verwendet werden kann.

Aber abgesehen von den bereits erwähnten Punkten wird es im Wesentlichen ohne größere Änderungen bleiben. Daher empfehle ich Ihnen, zu prüfen, was für das System, das Sie verwenden wollen, wirklich erforderlich ist. Belassen Sie bestimmte vorkonfigurierte Teile, die vom Händler nicht angepasst werden sollten, und erlauben Sie dem Nutzer, je nach Szenario nur die notwendigen Teile anzupassen.

Eine andere Sache, die Sie vielleicht bemerkt haben, ist, dass die Klasse C_Automaton die Klasse C_Manager erbt. Aus diesem Grund hat der Code praktisch keine Änderungen erfahren. Wie Sie also sehen können, findet alles innerhalb der Klasse C_Automaton statt.

Wenn Sie dieselbe EA-Struktur und dieselben Klassen wie ich verwenden möchten, reicht es aus, die Klasse C_Automaton zu modifizieren, um Ihr Handelssystem innerhalb dieser Klasse zu haben. Dadurch wird die Erstellung neuer EAs, die verschiedene Handelssysteme nutzen, schneller, sicherer und konsistenter, da der einzige Unterschied zwischen ihnen die Klasse C_Automaton selbst ist. Bei der Erstellung der Klasse können Sie mit Hilfe des Konstruktors einige bestimmte Dinge in Übereinstimmung mit dem Handelssystem selbst mitteilen. Dadurch wird ein hohes Maß an Flexibilität, Nutzerfreundlichkeit, Robustheit und Wiederverwendbarkeit gewährleistet.

Ihr EA wird immer ein gutes Qualitätsniveau haben, das von den tatsächlichen Nutzern verlangt wird. Aber trotzdem kann man einige Änderungen vornehmen, um die Dinge interessanter zu gestalten. Vielleicht werde ich in Zukunft einige dieser Änderungen öffentlich machen. In jedem Fall empfehle ich Ihnen, das System zu ändern und an Ihre Arbeitsweise anzupassen. Dafür schreibe ich ja diese Artikel und gewähre freien Zugang zu dem Code.

Meine einzige Bitte ist, dass Sie, wenn Sie sie verwenden, auch wenn es nur ein Teil davon ist, die Quelle des Inhalts angeben. Es ist nichts Schändliches, aber es ist nicht gut, etwas zu verwenden oder zu verbreiten, ohne die Quelle anzugeben.

Schauen wir uns nun an, was sich in der Blackbox der Klasse C_Automaton befindet.


Analysieren des Klassencodes von C_Automaton

Wie bereits erwähnt, hängen sowohl der EA-Code als auch der Code der Klasse C_Automaton davon ab, was, wie und wann Sie handeln werden. Unabhängig davon wird die Klasse C_Automaton im Wesentlichen drei interne Funktionen haben: einen Konstruktor, eine Funktion, die durch das Zeitereignis des EA aufgerufen wird, und eine weitere interne und private Funktion der Klasse.

Es ist wichtig, dass Sie auf diese drei Funktionen achten. Es kann vorkommen, dass aus anderen Gründen mehr oder weniger Funktionen zur Unterstützung dieser drei benötigt werden, aber im Wesentlichen werden wir immer diese drei Funktionen haben.

Um sich nicht auf die Theorie zu beschränken, schauen wir uns das folgende Video an. Er mag lang erscheinen, aber es lohnt sich, ihn anzuschauen. Ich möchte betonen, dass unabhängig davon, mit welchem System Sie handeln, ausnahmslos jeder irgendeine Art von Verlust erleiden wird, ob groß oder klein. Aber sehen Sie sich zuerst das Video an, um zu verstehen, was im Folgenden erklärt wird.


Video 01 - Demonstration des automatisierten EA (ca. 25 Minuten)

In diesem Video verwende ich das Handelssystem, das auf dem exponentiell gleitenden 9-Perioden-Durchschnitt basiert, den der EA verwendet, um zu Beginn eines jeden neuen Balkens Einstiege zu erstellen. Die Erstellung dieses Systems wurde im vorigen Artikel beschrieben. Ich empfehle daher, diesen Artikel sorgfältig zu lesen, um alle zugrunde liegenden Prozesse zu verstehen. Auch hier sollten wir uns nicht auf die Theorie beschränken. Um zu verstehen, wie die Klasse C_Automaton es dem EA ermöglicht, Positionen zu eröffnen, zu verwalten und zu schließen, sehen wir uns einige Code-Beispiele an, die das spezifische Setup erstellen.

Verfolgen Sie die Erläuterungen zu jeder Methode und sehen Sie, wie sie entwickelt und kodiert wurde. Auf diese Weise können Sie praktisch jedes Setup entwickeln, auch wenn es sehr spezielle Fälle geben kann, die ein wenig mehr Code erfordern. Da sie aber selten sind und die große Mehrheit tatsächlich Indikatoren verwendet, werden diese Beispiele bei der Erstellung des 100% automatischen Modells sehr hilfreich sein. Bevor wir uns mit dem Code befassen, sollten wir uns einige kleine Details ansehen.


Gemeinsame Teile, abhängige Teile

Wir müssen einige Klarstellungen vornehmen, damit Sie beim Betrachten der Beispiele in der Klasse C_Automaton nicht verwirrt werden.

Der Code der Klasse C_Automaton ist sehr eigenartig, aber für erfahrene Programmierer ist er etwas ganz Alltägliches. Es gibt Teile, die für alle Vorgänge gleich sind, und Teile, die für einen bestimmten Vorgang spezifisch sind. Achten Sie darauf, wenn Sie Ihre Methode beschreiben, wie im vorherigen Artikel beschrieben. Denn wenn Sie nicht verstehen, dass alle Modelle gemeinsame Teile haben, könnten Sie denken, dass die Klasse C_Automaton Ihr Modell nicht abdecken kann, während sie in Wirklichkeit jedes Modell abdecken kann. Manchmal werden Sie einige Variablen hinzufügen müssen, aber ich werde Ihnen zeigen, wie Sie das richtig machen, damit Sie mit jedem Modelltyp arbeiten können.

Gemeinsame Codeteile werden immer wiederholt, unabhängig von dem Modell, das Sie verwenden möchten. Abhängige Teile machen Ihr Modell einzigartig und werden nicht in anderen Modellen wiederholt.

Hier ist der allgemeine Code für jedes Modell:

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#include "C_Manager.mqh"
//+------------------------------------------------------------------+
class C_Automaton : public C_Manager

{
        protected:
                enum eTrigger {TRIGGER_NONE, TRIGGER_BUY, TRIGGER_SELL};
        private :
                struct st00
                {
                        int     Shift,
                                nBars;
                        double  OverBought,
                                OverSold;
                }m_Infos;
                double  m_Buff[];
                int     m_nBars,
                        m_Handle;
                ENUM_TIMEFRAMES m_TF;
//+------------------------------------------------------------------+
static eTrigger m_Memory;
//+------------------------------------------------------------------+  
inline eTrigger CheckTrigger(void)
                        {
                               int iRet;

                               if (((iRet = iBars(NULL, m_TF)) > m_nBars) && (m_Handle != INVALID_HANDLE))
			       {
			       }

                               return TRIGGER_NONE;
                        }
//+------------------------------------------------------------------+  
        public  :
//+------------------------------------------------------------------+
                C_Automaton(const ulong magic, double FinanceStop, double FinanceTake, uint Leverage,
                                                bool IsDayTrade, double Trailing, const ENUM_TIMEFRAMES iPeriod,
                                                const double OverBought = 70, const double OverSold = 30, const int iShift = 1)
                        :C_Manager(magic, FinanceStop, FinanceTake, Leverage, IsDayTrade, Trailing, true, 10),
                         m_TF(iPeriod),
                         m_Handle(INVALID_HANDLE)
                        {
                                m_Infos.Shift      = iShift;
                                m_Infos.OverBought = OverBought;
                                m_Infos.OverSold   = OverSold;
                                ArraySetAsSeries(m_Buff, true);
                                m_nBars = iBars(NULL, m_TF);
                        }
//+------------------------------------------------------------------+
inline virtual void Triggers(void) final
                        {
                                if (!CtrlTimeIsPassed()) ClosePosition(); else switch (CheckTrigger())
                                {
                                        case TRIGGER_BUY:
                                                if (m_Memory == TRIGGER_SELL) ClosePosition();
                                                if (m_Memory != TRIGGER_BUY) ToMarket(ORDER_TYPE_BUY);
                                                m_Memory = TRIGGER_BUY;
                                                break;
                                        case TRIGGER_SELL:
                                                if (m_Memory == TRIGGER_BUY) ClosePosition();
                                                if (m_Memory != TRIGGER_SELL) ToMarket(ORDER_TYPE_SELL);
                                                m_Memory = TRIGGER_SELL;
                                                break;
                                }
                        };
//+------------------------------------------------------------------+  
};
//+------------------------------------------------------------------+
static C_Automaton::eTrigger C_Automaton::m_Memory = TRIGGER_NONE;
//+------------------------------------------------------------------+

Alles, was Sie im obigen Code sehen, ist Teil des allgemeinen Codes, der in jedem Modell vorhanden ist. Unabhängig vom Modell wird dieser Code immer verwendet. Es stimmt, dass es einige neue Variablen oder C_Manager-Aufrufe geben kann, wie Sie in den Beispielcodes sehen werden. Der obige Code bleibt jedoch weitgehend erhalten.

Alles, was in diesem Code nicht enthalten ist, ist Teil des modellabhängigen Codes, der für Ihr Modell spezifisch ist. Schauen wir uns also den Code an, um zu verstehen, wie er funktioniert. Auf diese Weise werden Sie in der Lage sein zu verstehen, was Sie dem Code hinzufügen oder nicht hinzufügen müssen, um ein spezifischeres Modell abzudecken.

Beginnen wir mit der Klassendeklaration im folgenden Code:

#include "C_Manager.mqh"
//+------------------------------------------------------------------+
class C_Automaton : public C_Manager
{
        protected:
                enum eTrigger {TRIGGER_NONE, TRIGGER_BUY, TRIGGER_SELL};

Hier erklären wir, dass die Klasse C_Automaton öffentlich von der Klasse C_Manager geerbt wird. Dies ermöglicht uns den Zugriff auf die Prozeduren der Klasse C_Manager, wenn wir die Klasse C_Automaton verwenden. Dies ist wichtig für die Initialisierung einiger Mitglieder, die mit der Steuerklasse verbunden sind. Wenn Sie sich den EA-Code ansehen, können Sie diese Punkte sehen, an denen auf die Verfahren zugegriffen wird. Obwohl diese Prozeduren nicht in der Klasse C_Automaton deklariert sind, stammen sie aus anderen Klassen. Dies wurde bereits in einem anderen Artikel in dieser Reihe erläutert.

Wir haben auch einen Enumerator erstellt, um eine hochklassige Programmierung in der Klasse zu haben. Diese Enumeration gibt an, welche Art von Auslöser aktiviert wurde. Ein weiteres Detail: Obwohl dieser Enumerator in einem geschützten Teil des Codes deklariert ist, wird er außerhalb der Klasse nicht verwendet. Aber es war notwendig, sie in diesen Teil zu setzen, um eine statische Klassenvariable initialisieren zu können. Aber dazu später mehr.

Sehen wir uns nun die Variablen im folgenden Code an:

        private :
                struct st00
                {
                        int     Shift,
                                nBars;
                        double  OverBought,
                                OverSold;
                }m_Infos;
                double  m_Buff[];
                int     m_nBars,
                        m_Handle;
                ENUM_TIMEFRAMES m_TF;
//+------------------------------------------------------------------+
static eTrigger m_Memory;

An dieser Struktur werden wir kaum Änderungen vornehmen müssen, da sie ein breites Spektrum von Fällen im Zusammenhang mit Indikatoren abdeckt. Wenn Sie jedoch mehr als einen Indikator verwenden, müssen Sie möglicherweise weitere Strukturen hinzufügen. An den Elementen der Struktur selbst müssen Sie jedoch nichts ändern.

Um dies zu verstehen, betrachten wir das folgende Beispiel: Die Struktur wird von einer Variablen referenziert. Dies ermöglicht die Verwendung eines einzigen Indikators, wie auch immer er aussehen mag. Was aber, wenn wir mehr als einen Indikator verwenden müssen? Was ist in diesem Fall zu tun? In diesem Fall werden wir einige Ergänzungen vornehmen müssen. Sie werden in Beispielen dargestellt. Um dieses einfachere System zu verstehen, sollten wir uns zunächst auf die Grundlagen konzentrieren.

Außerdem gibt es eine Variable, die als Puffer für die Indikatorwerte dient, eine Variable, die die Anzahl der Balken im Chart speichert, eine weitere für die Indikatorreferenz und eine Variable, die den für den Indikator verwendeten Zeitrahmen bestimmt. Und schließlich gibt es noch eine Variable, die den letzten Auslösestatus speichert. Diese statische Variable wird außerhalb des Klassenkörpers initialisiert, wie im folgenden Code gezeigt:

static C_Automaton::eTrigger C_Automaton::m_Memory = TRIGGER_NONE;

Beachten Sie, dass er mit einem neutralen Trigger initialisiert werden muss, d.h. es wurde keine Anfrage an das Triggersystem gestellt. Wir wollen nicht, dass es zu einer versehentlichen Auslösung kommt. Je nach Handelsmodell ist diese statische Variable jedoch nicht so nützlich, da das Modell immer bei dem Kreuzen von Werten auslöst. Um jedoch zu vermeiden, dass unmittelbar nach der Platzierung des EA auf dem Chart zufällige Auslöser auftreten, verwenden wir diese Variable, um sicherzustellen, dass beim Start oder beim Wechsel der Handelshand nichts Zufälliges passiert.

Der nächste Punkt, den es zu beachten gilt, ist die unten gezeigte private Funktion der Klasse:

inline eTrigger CheckTrigger(void)
                        {
                                int iRet;
                                        
                                if (((iRet = iBars(NULL, m_TF)) > m_nBars) && (m_Handle != INVALID_HANDLE))
                                {
                                };
                                return TRIGGER_NONE;
                        }

Standardmäßig gibt diese Funktion immer TRIGGER_NONE zurück, d. h. es handelt sich weder um einen Kauf noch um einen Verkauf. Die spezifische Berechnung für Ihr Handelsmodell wird in dieser Funktion implementiert. Weitere Berechnungen können also unterschiedlich ausfallen.

Unabhängig von der gewünschten Berechnungsart werden wir das System jedoch immer auf folgende Weise testen: Die Berechnung wird nur bei einem neuen Balken durchgeführt; wenn es keinen neuen Balken gibt, wird die Berechnung ignoriert. Außerdem muss das Handle auf etwas Gültiges zeigen, sonst wird nichts berechnet. Es ist wichtig, diese Regeln klar zu definieren, um Probleme während des EA-Betriebs zu vermeiden.

Die folgende Funktion ist der Klassenkonstruktor:

                C_Automaton(const ulong magic, double FinanceStop, double FinanceTake, uint Leverage,
                            bool IsDayTrade, double Trailing, const ENUM_TIMEFRAMES iPeriod,
                            const double OverBought = 70, const double OverSold = 30, const int iShift = 1)
                        :C_Manager(magic, FinanceStop, FinanceTake, Leverage, IsDayTrade, Trailing, true, 10),
                         m_TF(iPeriod),
                         m_Handle(INVALID_HANDLE)
                        {
                                m_Infos.Shift      = iShift;
                                m_Infos.OverBought = OverBought;
                                m_Infos.OverSold   = OverSold;
                                ArraySetAsSeries(m_Buff, true);
                                m_nBars = iBars(NULL, m_TF);
                        }

Es ist äußerst wichtig, diesen Konstruktor vollständig zu verstehen. Ich verstehe, dass der Code für diejenigen, die keine Erfahrung haben oder gerade erst anfangen, verwirrend sein kann. Das Verständnis dieses Codes ist jedoch entscheidend, um die Klasse C_Automaton optimal zu nutzen und einen vollautomatischen EA zu erstellen. Beginnen wir damit, zu verstehen, was dieser scheinbar verwirrende Text eigentlich bewirkt.

Da C_Automaton von C_Manager abgeleitet wird, müssen wir den C_Manager-Konstruktor initialisieren. Aus diesem Grund erhält sie Daten von der EA, die zur Initialisierung vollständig an die Klasse C_Manager übergeben werden.

Achten Sie aber auf zwei weitere Parameter. Bei Bedarf können sie an den EA zurückgegeben werden. Dies hängt jedoch von der Art des Handels ab, der in der Klasse C_Automaton erstellt wird. Ich erwähne diese Parameter hier, damit ihre Bedeutung klar ist. Diese Parameter können durch einen Blick auf C_Manager verstanden werden. Der Code, der den Klassenkonstruktor beschreibt, ist in früheren Artikeln zu finden, daher werde ich ihn hier nicht wiederholen.

Der EA informiert auch darüber, welche Chart-Periode für die Klasse C_Automaton zu verwenden ist. Dieser Parameter wird dafür verwendet.

Es ist wichtig, dass das Automatisierungssystem immer in einem bestimmten Zeitrahmen arbeitet, unabhängig davon, was die Aufsichtsperson sieht. Wenn Sie hier in der Automatisierungsklasse denselben Zeitrahmen verwenden, der für den Supervisor sichtbar ist, können wir den EA versehentlich zu unpassenden Zeiten auslösen lassen. Dies ist ein sehr häufiger Fehler in einigen EAs, bei denen der Programmierer nicht weiß, dass der Nutzer den Chart-Zeitrahmen während der EA-Arbeitszeit ändern kann. Dies verursacht immense Unannehmlichkeiten. Auf diese Weise garantieren wir jedoch, dass der EA immer mit demselben Zeitrahmen arbeitet, unabhängig davon, was für den Händler sichtbar ist.

An dieser Stelle haben wir einige Parameter mit Standardwerten. Dementsprechend können sie im EA-Code angegeben werden, müssen aber nicht.

Die Verwendung von Standardwerten hindert Sie nicht daran, im EA-Code einen anderen Wert anzugeben oder dem Händler sogar die Möglichkeit zu geben, beim Start des EA einen Wert zu definieren. Da diese Werte aber in den meisten Fällen gleich bleiben und in anderen Fällen nicht verwendet werden, definiere ich diese Parameter mit einem Standardwert, um eine Überladung des Konstruktors zu vermeiden. Dadurch wird der Code kompakter und lässt sich einfacher analysieren und verstehen. Beachten Sie, dass diese Werte in der internen Struktur zur weiteren Verwendung gespeichert werden.

Ein wichtiges Detail: Wenn Sie ein System verwenden, bei dem diese Werte vom Händler je nach Art des verwendeten Indikators geändert werden können, muss dieser Code möglicherweise geändert werden, um mehr Variablen unterzubringen. In diesem Fall kann er mit einem oder mehreren Indikatoren verwendet werden, solange sie alle dieselben Daten verwenden.

Schließlich initialisieren wir den Wert des Handles, sodass er auf irgendeinen Indikator zeigt. Dies ist wichtig, um Sicherheitslücken zu vermeiden, falls das Handle auf etwas Unbekanntes verweist. Außerdem passen wir die letzten Systemvariablen an. Dieser Konstruktor ist die Grundlage und wird je nach Art des Systems, das implementiert werden soll, mit einigen weiteren Codezeilen versehen. Dies wird jedoch in Code-Beispielen gezeigt werden.

Um den Basiscode der Klasse C_Automaton zu beenden, sehen wir uns den letzten Codeteil an:

inline virtual void Triggers(void) final
                        {
                                if (!CtrlTimeIsPassed()) ClosePosition(); else switch (CheckTrigger())
                                {
                                        case TRIGGER_BUY:
                                                if (m_Memory == TRIGGER_SELL) ClosePosition();
                                                if (m_Memory != TRIGGER_BUY) ToMarket(ORDER_TYPE_BUY);
                                                m_Memory = TRIGGER_BUY;
                                                break;
                                        case TRIGGER_SELL:
                                                if (m_Memory == TRIGGER_BUY) ClosePosition();
                                                if (m_Memory != TRIGGER_SELL) ToMarket(ORDER_TYPE_SELL);
                                                m_Memory = TRIGGER_SELL;
                                                break;
                                }
                        };

Das obige Verfahren ist kein 100%iger fertiger Code und kann je nach Handelssystem einige kleine Änderungen erfahren. Es zeigt im Wesentlichen, was bei jedem Aufruf des OnTime-Ereignisses passiert. Viele möchten dies vielleicht in die Ereignisbehandlung von OnTick verschieben, aber ich habe bereits erklärt, warum dies nicht getan werden sollte. Ich empfehle Ihnen, die vorherigen Artikel zu lesen, um die Gründe dafür zu verstehen.

Der Code weist die Klasse C_Manager an, immer mit Marktanforderungen zu arbeiten. Deshalb sage ich, dass der Code nicht zu 100 % fertig ist, denn je nach dem Modell, das Sie implementieren, kann das Auftragssystem unterschiedlich sein. Selbst die Art und Weise, wie sich die Handelsseite ändert, kann dazu führen, dass dieser Code anders aussieht.

Eine andere Sache ist, dass der obige Code dem EA nicht erlaubt, eine Position zu erhöhen, wenn neue Signale auftreten. Das liegt daran, dass wir das in einer Variablen speichern.

So wird verhindert, dass der EA die Position erhöht, wenn ein neues Einstiegssignal generiert wird. Aber jeder mit ein wenig Programmierkenntnissen wird in der Lage sein, diese Sperre, die ich absichtlich hinzugefügt habe, zu umgehen. Wenn jemand versucht, dies ohne entsprechende Kenntnisse zu tun, wird er mit Sicherheit ernsthafte Verluste auf dem Konto erleiden, da der EA Aufträge unkontrolliert ausführen kann und dabei das gesamte verfügbare Guthaben in Sekundenschnelle verliert. Ändern Sie diesen Code also nicht, wenn Sie nicht genau wissen, was Sie tun..

Aus diesem Grund werden wir diesen Code nicht näher erläutern. Bevor ich zu den Beispielen komme, möchte ich jedoch noch etwas erwähnen. Es ist die Erklärung dieses Verfahrens, die auf den ersten Blick seltsam und bedeutungslos erscheinen mag.

Versuchen wir, den Grund dafür zu verstehen. Das gesamte System ist auf ein Klassensystem ausgelegt. Dies macht den Code nicht nur zuverlässiger, sicherer und robuster, sondern ermöglicht auch seine Erweiterung im Laufe der Zeit, wodurch er komplexer wird als ursprünglich geplant. Dieser Anstieg der Komplexität ist jedoch nicht mit einem erheblichen Anstieg des Codes verbunden, da das Klassensystem es uns ermöglicht, die Dinge viel modularer zu gestalten und somit den Code zu reduzieren, während die Komplexität steigt.

Da C_Automaton nicht die endgültige Klasse ist, wird die Prozedurdeklaration in einem größeren System so wie sie ist durchgeführt. Wir sagen dem Compiler, dass er sicherstellen soll, dass diese bestimmte Prozedur in keiner Weise in einer anderen Klasse geändert werden kann. Dadurch wird sichergestellt, dass sie im gesamten System der vererbten Klassen eindeutig ist.

Dies ist sehr wichtig, wenn es um modularen und sehr gut strukturierten Code geht. Denn egal, wie sehr man sie strukturiert, früher oder später kann man den Fehler machen, eine geerbte Prozedur zu überschreiben. Wenn dies geschieht, ist unser gesamter Code gefährdet. Aber zum Glück bietet die MLQ5-Sprache die Werkzeuge, um diese Art von Problemen zu vermeiden.

Um zu verstehen, wie die Klasse C_Automaton bei der Automatisierung des EA helfen kann, sehen wir uns einige Code-Beispiele an, bei denen wir uns auf die Erklärung konzentrieren, wie ein Handelssystem implementiert wird. Bevor wir beginnen, gibt es einige Dinge zu klären:

  • Kein automatisiertes Handelssystem ist 100% sicher.
  • Es gibt kein System, das bei allen Operationen Gewinne garantiert.
  • Machen Sie keinen Fehler, wenn Sie sehen, dass das System zunächst funktioniert, wie in Video 01 zu sehen ist.
  • Verwenden oder automatisieren Sie nur das System, das Sie bereits kennen. Versuchen Sie nicht, mehrere Strategien zu kombinieren und sich einzubilden, dass Sie auf diese Weise bessere Ergebnisse erzielen werden. Einfachheit ist alles.
  • Die Verwendung der hier gezeigten Modelle erfolgt auf eigenes Risiko, da sie sowohl Gewinne als auch Verluste bringen können.

Zum besseren Verständnis der Anwendung des Codes wird jedes der Modelle von einem spezifischen EA begleitet, sodass Sie die Codes vergleichen und daraus lernen können.


Schlussfolgerung

Aufgrund des Umfangs des Themas werden in diesem Artikel jedoch nur drei Beispiele für die Automatisierung vorgestellt. Die entsprechenden Codes werden im nächsten Artikel erörtert, der möglicherweise der letzte in dieser Reihe sein wird. Verpassen Sie also nicht den nächsten Artikel. In diesem Artikel werden wir sehen, wie all diese Elemente perfekt zusammenpassen und den EA in einem vollautomatischen Modus in Aktion bringen, während er dem von Ihnen festgelegten Muster folgt.


Übersetzt aus dem Portugiesischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/pt/articles/11318

Erstellen eines EA, der automatisch funktioniert (Teil 15): Automatisierung (VII) Erstellen eines EA, der automatisch funktioniert (Teil 15): Automatisierung (VII)
Zum Abschluss dieser Artikelserie über Automatisierung werden wir das Thema des vorangegangenen Artikels weiter erörtern. Wir werden sehen, wie alles zusammenpassen wird, damit der EA wie ein Uhrwerk läuft.
Mehrschichtiges Perzeptron und Backpropagation-Algorithmus (Teil 3): Integration mit dem Strategy Tester - Überblick (I). Mehrschichtiges Perzeptron und Backpropagation-Algorithmus (Teil 3): Integration mit dem Strategy Tester - Überblick (I).
Das mehrschichtige Perzeptron ist eine Weiterentwicklung des einfachen Perzeptrons, das nichtlineare separierbare Probleme lösen kann. Zusammen mit dem Backpropagation-Algorithmus kann dieses neuronale Netz effektiv trainiert werden. In Teil 3 der Serie Multilayer Perceptron und Backpropagation werden wir sehen, wie man diese Technik in den Strategy Tester integriert. Diese Integration ermöglicht die Nutzung komplexer Datenanalysen, um bessere Entscheidungen zur Optimierung Ihrer Handelsstrategien zu treffen. In diesem Artikel werden wir die Vorteile und Probleme dieser Technik erörtern.
MQL5 Wizard-Techniken, die Sie kennen sollten (Teil 06): Fourier-Transformation MQL5 Wizard-Techniken, die Sie kennen sollten (Teil 06): Fourier-Transformation
Die von Joseph Fourier eingeführte Fourier-Transformation ist ein Mittel zur Zerlegung komplexer Wellen aus Datenpunkten in einfache Teilwellen. Diese Funktion könnte für Händler sehr nützlich sein, und dieser Artikel wirft einen Blick darauf.
Erstellen eines automatisch arbeitenden EA (Teil 13): Automatisierung (V) Erstellen eines automatisch arbeitenden EA (Teil 13): Automatisierung (V)
Wissen Sie, was ein Flussdiagramm ist? Können Sie es verwenden? Glauben Sie, dass Flussdiagramme etwas für Anfänger sind? Ich schlage vor, dass wir mit diesem neuen Artikel fortfahren und lernen, wie man mit Flussdiagrammen arbeitet.