Alles, was Sie über die MQL5-Programmstruktur wissen müssen
Einführung
Jede Software in jeder Programmiersprache hat eine Struktur. Wenn wir diese Struktur verstanden haben, können wir unsere Software reibungslos erstellen oder entwickeln. Die Programme der MQL5-Sprache haben die gleiche Struktur wie jede andere Programmiersprache und sollen vom Entwickler verstanden werden, um die Ziele seines Projekts reibungslos und effektiv zu erreichen. In diesem Artikel werden wir Informationen in diesem Zusammenhang zur Verfügung stellen, um zu versuchen, den Inhalt so einfach wie möglich zu vermitteln. Wir lernen die Struktur eines jeden MQL5-Programms kennen, indem wir die folgenden Themen behandeln:
- Präprozessor
- Makro-Substitution (#define)
- Programm-Eigenschaften (#property)
- Einbinden von Dateien (#include)
- Funktionen importieren (#import)
- Bedingte Kompilierung (#ifdef, #ifndef, #else, #endif)
- Eingabe und globale Variablen
- Funktionen, Klassen
- Ereignisbehandlung
- MQL5 Programmbeispiele
- Schlussfolgerung
Nach den vorangegangenen Themen ist davon auszugehen, dass Sie die Struktur eines MQL5-Programms sehr gut verstehen und jede Software, die auf dieser Struktur basiert, reibungslos und effektiv erstellen oder entwickeln können.
Präprozessor
In diesem Teil werden wir den Präprozessor als Programmierkonzept im Detail kennenlernen. Der Präprozessor ist ein entscheidender Schritt im Kompilierungsprozess. Sie erfolgt vor der eigentlichen Kompilierung eines Programms. Während des Vorverarbeitungsschritts werden verschiedene Aktionen durchgeführt, wie z. B. das Einfügen von Dateien, die Bestimmung von Softwareeigenschaften, die Definition von Konstanten und der Import von Funktionen.
Alle Präprozessoranweisungen beginnen mit (#). Diese Direktiven werden nicht als sprachliche Anweisungen betrachtet. Daher sollten sie nicht mit einem Semikolon (;) abgeschlossen werden. Das Einfügen eines Semikolons am Ende einer Präprozessoranweisung kann je nach Art der Anweisung zu Fehlern führen.
Mit anderen Worten können wir sagen, dass der Präprozessor zur Vorbereitung des Programmquellcodes vor dem Kompilierungsprozess dient. Es gibt viele Arten von Präprozessor-Direktiven, die auf Parametern basieren, die wir im MQL5-Programm bestimmen müssen, wie die folgenden:
- Makro-Substitution (#define)
- Programm-Eigenschaften (#property)
- Einbinden von Dateien (#include)
- Funktionen importieren (#import)
- Bedingte Kompilierung (#ifdef, #ifndef, #else, #endif)
Makro-Substitution (#define):
Die Präprozessordirektive #define kann verwendet werden, um symbolische Konstanten zu erstellen oder um Konstanten zu definieren, die im Programm verwendet werden sollen. Falls Sie nicht wissen, was eine Konstante ist, handelt es sich dabei um einen Bezeichner mit einem Wert, der sich nicht ändert. Wir können auch sagen, dass die #define-Direktive verwendet werden kann, um Konstanten mnemonische Namen zuzuweisen, da wir einen Ersatzwert für einen bestimmten Bezeichner verwenden werden. Das erste Format dieser Präprozessor-Direktive entspricht dem folgenden:
#define identifier replacement-value
Wir haben also diese Codezeile in unserem Programm, was bedeutet, dass der Bezeichner durch einen Ersatzwert ersetzt wird, bevor das Programm kompiliert wird. Dieses Format ist die #define-Direktive ohne Parameter oder das parameterfreie Format und es gibt ein weiteres Format in MQL5, das parametrische Format mit maximal acht erlaubten Parametern, die mit der #define-Direktive verwendet werden können, wie im Folgenden beschrieben:
#define identifier (param1, param2,... param5)
Für die Kennung der Konstanten gelten dieselben Regeln wie für die Variablen:
- Der Wert kann ein beliebiger Typ wie Integer, Double oder String sein.
- Der Ausdruck kann aus mehreren Token bestehen und endet, wenn die Zeile beendet wird und kann nicht in die nächste Codezeile verschoben werden.
Ein Beispiel dafür ist das Folgende:
//Parameter-free format #define INTEGER 10 //int #define DOUBLE 10.50 //double #define STRING_VALUE "MetaQuotes Software Corp." //str #define INCOMPLETE_VALUE INTEGER+DOUBLE //Incomlete #define COMPLETE_VALUE (INTEGER+DOUBLE) //complete //Parametic format #define A 2+3 #define B 5-1 #define MUL(a, b) ((a)*(b)) double c=MUL(A,B); //function to print values void defValues() { Print("INTEGER Value, ",INTEGER); //result: INTEGER Value, 10 Print("DOUBLE Value, ",DOUBLE); //result: DOUBLE Value, 10.50 Print("STRING Value, ",STRING_VALUE); //result: STRING Value, MetaQuotes Software Corp. Print("INCOMPLETE Value, ",INCOMPLETE_VALUE*2); //result: INCOMPLETE Value, 31 Print("COMPLETE Value, ",COMPLETE_VALUE*2); //result: STRING Value, 41 Print("c= ",c); //result: c= 41 }
Es gibt auch die (#undef) Präprozessor-Direktive, die das, was vorher deklariert oder definiert wurde, rückgängig macht.
Programm-Eigenschaften (#property):
Wenn wir unsere Software erstellen, kann es sein, dass wir zusätzliche Parameter angeben müssen, was wir mit #property tun können. Diese Eigenschaften müssen in der mql5-Hauptdatei angegeben werden, nicht in der Include-Datei, und diejenigen, die in Include-Dateien angegeben sind, werden ignoriert. Wir können also sagen, dass die #property-Direktive zusätzliche Eigenschaften für das Programm angibt. Wenn Sie fragen, was wir in diesem Zusammenhang angeben müssen, können wir die Frage so beantworten, dass es viele Dinge gibt, wie zum Beispiel Indikator, Skript, beschreibende Informationen und Bibliothekseigenschaften. Genau wie andere Präprozessor-Direktiven werden die #property im oberen Teil des Quelltextes angegeben und bei der Ausführung im Programmfenster auf der allgemeinen Registerkarte angezeigt.
Im Folgenden finden Sie ein Beispiel für eine solche Präprozessoranweisung:
#property copyright "Copyright 2023, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property description "Property preprocessor"
Wir können diese Werte im Programmfenster wie in der folgenden Abbildung sehen:
Wie wir in der vorherigen Abbildung sehen können, haben wir unsere definierten Eigenschaften, wie wir sie in der allgemeinen Registerkarte benötigen, wenn wir den EA ausführen, und der Text von Copyright 2023, MetaQuotes Ltd. ist ein Hyperlink, wenn wir mit der Maus darüber fahren, können wir sehen, und wenn wir ihn drücken, wird er zu dem Link der Link-Eigenschaft führen.
Einbinden von Dateien (#include):
Wie üblich werden alle #include-Anweisungen am Anfang des Programms platziert. Es legt fest, dass eine eingebundene Datei in eine bestimmte Software eingebunden wird, was bedeutet, dass die eingebundene Datei ein Teil der Software wird und wir ihren Inhalt wie Variablen, Funktionen und Klassen verwenden können.
Es gibt zwei Formate für die Einbindung von Dateien mit der #include-Direktive:
#include <File_Name.mqh> #include "File_Name.mqh"
Der Unterschied zwischen diesen beiden Formaten ist der Ort, an dem der Compiler nach der einzubindenden Datei suchen soll. Bei der ersten Variante sucht der Compiler die Datei im Include-Ordner der MetaTrader 5-Installation oder in der Header-Datei der Standardbibliothek, bei der zweiten Variante sucht er die Datei im gleichen Verzeichnis wie die Programmdatei.
Funktionen importieren (#import):
Die #import-Direktive wird verwendet, um Funktionen aus kompilierten MQL5-Modulen (*.ex5-Dateien) und aus Betriebssystemmodulen (*.dll-Dateien) in die Software zu importieren. Die Funktion muss vollständig beschrieben sein und ihr Format muss dem folgenden entsprechen:
#import "File_Name" func1 define; func2 define; ... funcN define; #import
Bedingte Kompilierung (#ifdef, #ifndef, #else, #endif):
Die bedingte Kompilierung ermöglicht es uns, zusätzlich zur Kompilierung des Programms die Ausführung von Vorverarbeitungsanweisungen zu steuern. Sie ermöglicht es, die Kompilierung oder das Überspringen eines Teils des Programmcodes auf der Grundlage einer bestimmten Bedingung zu steuern, die eines der folgenden Formate sein kann:
#ifdef identifier //If the identifier has been defined, the code here will be compiled. #endif
#ifndef identifier // If the identifier is not defined, the code here will be compiled. #endif
Wie wir bereits erwähnt haben, werden Präprozessor-Direktiven nicht fortgesetzt, wenn wir in eine neue Zeile wechseln, aber hier kann diese Art von Direktive von einer beliebigen Anzahl von Zeilen gefolgt werden, indem #else und #endif verwendet werden. Wenn die Bedingung erfüllt ist, werden die Zeilen zwischen diesen beiden #else und #endif ignoriert. Ist die Bedingung jedoch nicht erfüllt, werden die Zeilen zwischen der Überprüfung und dem #else (oder #endif, wenn ersteres fehlt) ignoriert.
Sie können mehr über den Präprozessor in MQL5 in der MQL-Referenz erfahren.
Eingabe und globale Variablen
In diesem Teil werden wir andere Komponenten der Struktur des MQL5-Programms nach den Präprozessordirektiven identifizieren, nämlich Eingabe- und globale Variablen. Wir beginnen mit den Eingabevariablen, die die externe Variable definieren, nachdem wir den Eingabemodifikator geschrieben und den Datentyp angegeben haben. Wir haben also den Eingabemodifikator und die Werte der Eingabevariablen. Der Eingabemodifikator kann nicht innerhalb des mql5-Programms geändert werden, aber die Werte können nur vom Nutzer des Programms über das Fenster Eingaben oder die Registerkarte der Programmeigenschaften geändert werden. Wenn wir diese externen Variablen durch den Input Modifier definieren, werden sie immer reinitialisiert, bevor OnInIt() aufgerufen wird.
Im Folgenden wird das Format der Eingabevariablen beschrieben:
input int MA_Period=20; input int MA_Shift=0; input ENUM_MA_METHOD MA_Method=MODE_SMA;
Danach können wir das vom Nutzer zu bestimmende Eingabefenster wie in der folgenden Abbildung finden:
Wie wir sehen können, können wir die MA-Periode, die MA-Verschiebung und den MA-Typ definieren. Wir können auch bestimmen, wie die Eingabeparameter auf der Registerkarte Eingaben aussehen, indem wir einen Kommentar mit dem, was wir in dem Fenster sehen müssen, wie im folgenden für das gleiche vorherige Beispiel einfügen:
input int MA_Period=20; //Moving Average Period input int MA_Shift=0; //Moving Average Shift input ENUM_MA_METHOD MA_Method=MODE_SMA; //Moving Average Type
Auf der Registerkarte Eingaben finden wir die folgenden Parameter:
Wie wir sehen können, sehen die Parameter anders aus als auf dem vorherigen Bild. Sie können mehr über die Eingabevariablen in der MQL5-Referenz erfahren.
Globale Variablen müssen außerhalb der Ereignisbehandlung oder Funktionen auf der gleichen Ebene von Funktionen erstellt werden, und wenn wir ein Beispiel für diese globalen Variablen sehen wollen, können wir sehen, dass die gleichen wie die folgenden:
int Globalvar; // Global variable before or outside the event handler and functions int OnInit() { ... }
Wir können also sagen, dass der Geltungsbereich der globalen Variablen das gesamte Programm ist und dass sie von allen Funktionen im Programm aus zugänglich sind. Sie werden einmal initialisiert, wenn das Programm geladen wird und vor der OnInit-Ereignisbehandlung oder OnStart()-Ereignisbehandlung, über die wir später sprechen werden, aber hier erwähne ich sie, um die Position der globalen Variablen in der MQL5-Programmstruktur darzustellen.
Sie können mehr über Globale Variablen in der MQL5-Referenz erfahren.
Funktionen, Klassen
In diesem Teil werden wir über andere Komponenten der MQL5-Programmstruktur nach Präprozessoren, Eingabe und globalen Variablen sprechen, die Funktionen und Klassen sind. Es gibt einen früheren Artikel über Funktionen im Detail. In dem Artikel „Verstehen von Funktionen in MQL5 mit Anwendungen“ können Sie mehr zu diesem Thema nachlesen. Wenn Sie etwas über Klassen im Zusammenhang mit dem Verständnis der objektorientierten Programmierung (OOP) in MQL5 lesen möchten, können Sie auch meinen früheren Artikel „Verstehen der MQL5 Objektorientierte Programmierung (OOP)“ lesen. Ich hoffe, Sie finden sie nützlich.
Hier werden wir die Position dieser wichtigen Komponente in jeder Software erwähnen, genauso wie nutzerdefinierte Klassen, da wir sie überall in der Software definieren können und sie in Include-Dateien definiert werden können, die durch die Verwendung der #include-Direktive eingeschlossen werden können, genauso wie wir es im Präprozessor-Thema erwähnt haben. Sie können vor oder nach der Ereignisbehandlung und unter Eingabe- und globalen Variablen platziert werden.
Das Format der Funktionen ist wie folgt:
returnedDataType functionName(param1, param2) { bodyOfFunction }
Das Format der Klassen ist wie folgt:
class Cobject { int var1; // variable1 double var2; // variable1 void method1(); // Method or function1 };
Mehr über Funktionen und Klassen erfahren Sie in der MQL5-Referenz.
Ereignisbehandlung
In diesem Teil werden über die Ereignisbehandlung sprechen, die eine sehr wichtige Komponenten im mql5-Programm ist. Die Ereignisbehandlung ist eine ausführbare Funktion, wenn ein bestimmtes Ereignis eintritt, wie z.B. wenn ein neues Preisangebot empfangen wird, welches ein neues Tick-Ereignis darstellt. Wenn das im Expert Advisor auftritt, dann wird OnTick() im EA aufgerufen, da in deren Hauptteil die Ereignis bearbeitet werden kann.
Je nach Typ des MQL5-Programms gibt es verschiedene Ereignisbehandlungen:
Ereignisbehandlung | Beschreibung | Format |
---|---|---|
OnStart | Dies wird in Skripten einmalig verwendet, wenn es gestartet wird. |
int OnStart(void);
void OnStart(void); |
OnInit | Dies wird in EAs und Indikatorprogrammen verwendet. Sie wird jeweils beim Start des Programms aufgerufen. |
int OnInit(void);
void OnInit(void); |
OnDeinit | Sie kann in EAs und Indikatorenprogrammen verwendet werden. Sie wird aufgerufen, wenn das Programm de-initialisiert wird | void OnDeinit( const int reason // deinitialization reason code ); |
OnTick | Sie wird nur in EAs verwendet und immer dann aufgerufen, wenn ein neuer Preis (Tick) eintrifft. | void OnTick(void); |
OnCalculate | Sie kann nur in Indikatoren verwendet und wird immer dann aufgerufen, wenn ein neuer Preis (Tick) eintrifft. |
int OnCalculate( const int rates_total, // price[] array size const int prev_calculated, // number of handled bars at the previous call const int begin, // index number in the price[] array meaningful data starts from const double& price[] // array of values for calculation );
int OnCalculate( const int rates_total, // size of input time series const int prev_calculated, // number of handled bars at the previous call const datetime& time{}, // Time array const double& open[], // Open array const double& high[], // High array const double& low[], // Low array const double& close[], // Close array const long& tick_volume[], // Tick Volume array const long& volume[], // Real Volume array const int& spread[] // Spread array ); |
OnTimer | Sie kann in den EAs und Indikatoren verwendet werden, um, wenn deklariert, beim Auftreten des periodische Timer-Ereignis vom Handelsterminal aufgerufen zu werden. | void OnTimer(void); |
OnTrade | Sie kann nur in EAs verwendet werden. Sie wird, wenn deklariert, immer dann aufgerufen, wenn eine Handelsoperation auf einem Handelsserver durchgeführt wurde. | void OnTrade(void); |
OnTradeTransaktion | Sie kann nur in EAs verwendet werden. Sie wird, wenn deklariert, immer dann aufgerufen, wenn eine Handelsoperation auf einem Handelsserver durchgeführt wurde. | void OnTradeTransaction() const MqlTradeTransaction& trans, // trade transaction structure const MqlTradeRequest& request, // request structure const MqlTradeResult& result // response structure ); |
OnBookEvent | Sie kann in den EAs verwendet werden und wird, wenn deklariert, aufgerufen, wenn sich die Tiefe des Marktes ändert. | void OnBookEvent( const string& symbol // symbol ); |
OnChartEvent | Sie kann in den Indikatoren verwendet werden, um eine Funktion aufzurufen, wenn der Nutzer auf dem Chart etwas macht. | void OnChartEvent() const int id, // event ID const long& lparam, // long type event parameter const double& dparam, // double type event parameter const string& sparam // string type event parameter ); |
OnTester | Sie kann in den EAs verwendet werden, um eine Funktion aufzurufen, wenn das Testen eines Expert Advisors mit historischen Daten beendet ist. | double OnTester(void); |
OnTesterInit | Es kann in EAs verwendet werden, um eine Funktion mit dem Start der Optimierung im Strategietester vor dem ersten Optimierungsdurchlauf aufzurufen. |
int OnTesterInit(void);
void OnTesterInit(void); |
OnTesterDeinit | Es kann in den EAs verwendet werden, um eine Funktion nach dem Ende der Optimierung eines Expert Advisors im Strategietester aufzurufen. | void OnTesterDeinit(void); |
OnTesterPass | Sie kann in den EAs verwendet werden, um eine Funktion aufzurufen, wenn ein neuer Datenrahmen empfangen wird. | void OnTesterPass(void); |
Mehr über die Ereignisbehandlung erfahren Sie in der MQL5-Referenz.
MQL5 Programmbeispiel
In diesem Teil werden wir das Gelernte anwenden, um eine einfache Anwendung mit der richtigen MQL5-Struktur zu erstellen. Wir haben erwähnt, dass wir Komponenten der MQL5-Struktur je nach Art des Programms und der benötigten Aufgabe verwenden können, weil es keine Verpflichtungen gibt, einige dieser Komponenten zu verwenden, wie z.B. den #include-Präprozessor, weil es vielleicht keine Notwendigkeit gibt, eine externe Datei einzuschließen, genauso wie die #property, weil es eine Option ist, sie zu verwenden oder nicht, zusätzlich dazu kann es sein, dass Sie keine nutzerdefinierten Klassen oder Funktionen in Ihrem Programm erstellen müssen. Wie auch immer, Sie werden das verwenden, was für Ihr Programm notwendig ist. Im Folgenden finden Sie einige einfache Anwendungen, die alle benötigten Strukturkomponenten auf der Grundlage verschiedener Programmtypen darstellen.
Typ Script:
Es folgt ein einfaches Beispiel für ein MQL5-Skriptprogramm, das zwei vom Nutzer eingegebene Zahlen mit Hilfe von Eingaben berechnen und addieren kann und das Ergebnis mit Hilfe der Funktion Drucken in der Registerkarte Experte ausgibt. Was ich hier erwähnen muss, ist, dass wir hier in diesem Skriptprogramm eine #property hinzufügen werden, die es ermöglicht, Skripteingaben anzuzeigen, um Zahlen durch den Nutzer einzugeben.
//+------------------------------------------------------------------+ //| Script program example.mq5 | //| Copyright 2023, MetaQuotes Ltd.| //| https://www.mql5.com | //+------------------------------------------------------------------+ //property preprocessor #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #property script_show_inputs //inputs input int userEntryNum1; input int userEntryNum2; //global variable int result; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ //event handler void OnStart() { result=userEntryNum1+userEntryNum2; Print("Result: ", result); } //+------------------------------------------------------------------+
Wenn wir ein anderes EA- oder Indikatorprogramm erstellen wollen, müssen wir je nach Programmtyp eine unterschiedliche Ereignisbehandlung verwenden. Zum Beispiel kann ein EA-Programm eine Aktion ausführen, wenn es einen neuen Tick erhält, indem es die Ereignisbehandlung durch OnTick() verwendet.
Nachdem wir nun die Struktur des MQL5-Programms identifiziert haben, sehen wir, dass bestimmte Komponenten je nach Programmtyp und seinen Zielen oder Aufgaben variieren. Dieses Verständnis hilft uns, die Position der einzelnen Komponenten in der Software zu bestimmen.
Um dieses Wissen anzuwenden, können wir, wie bereits erwähnt, mit einem einfachen Skriptprogramm beginnen.
Schlussfolgerung
Nach dem, was wir durch Themen dieses Artikels besprochen haben, sollten Sie die Struktur eines MQL5-Programm verstanden haben und Sie sollten jetzt in der Lage sind, die Komponenten zu identifizieren, die Sie benötigen, um Ihre MQL5-Software zu schreiben:
- Der Präprozessor
- Makro-Substitution (#define)
- Programm-Eigenschaften (#property)
- Einbinden von Dateien (#include)
- Funktionen importieren (#import)
- Bedingte Kompilierung (#ifdef, #ifndef, #else, #endif)
- Eingabe und globale Variablen
- Funktionen und Klassen
- Ereignisbehandlung
- OnStart
- OnInit
- OnDeinit
- OnTick
- OnCalculate
- OnTimer
- OnTrade
- OnTradeTransaktion
- OnBookEvent
- OnChartEvent
- OnTester
- OnTesterInit
- OnTesterDeinit
- OnTesterPass
Ich hoffe, dass Ihnen dieser Artikel beim Aufbau Ihres MQL5-Programms geholfen hat. Für einen reibungslosen und effektiven Prozess ist es wichtig, den Kontext zu verstehen. Wenn Sie mehr über die Erstellung eines Handelssystems unter Verwendung beliebter technischer Indikatoren erfahren möchten, können Sie sich auf meine früheren Artikel zu diesem Thema beziehen.
Darüber hinaus habe ich über die Erstellung und Verwendung von nutzerdefinierten Indikatoren in jedem EA und andere wichtige Themen der MQL5-Programmierung, wie objektorientierte Programmierung (OOP) und Funktionen, geschrieben. Ich bin davon überzeugt, dass diese Artikel für Ihr Lernen und Ihre Handelsreise wertvoll sein werden.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/13021
- Freie Handelsapplikationen
- Freie Forex-VPS für 24 Stunden
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.