English 日本語
preview
Advanced Variables and Data Types in MQL5

Advanced Variables and Data Types in MQL5

MetaTrader 5Handel | 20 Mai 2024, 13:08
96 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Einführung

MQL5 ist die Programmiersprache des MetaTrader 5, der als die beliebteste Handelsplattform gilt. Sie ist sehr reich an Werkzeugen und Konzepten, mit denen jedes beliebige Handelssystem von einfach bis komplex erstellt werden kann. Unser Ziel als Entwickler ist es zu verstehen, wie wir diese Werkzeuge und Konzepte nutzen können, um unser Entwicklungsziel zu erreichen.

Wir haben bereits die Grundlagen der einfachen Variablen und Datentypen in MQL5 in unserem Artikel „Erfahren Sie, warum und wie Sie Ihr algorithmisches Handelssystem entwerfen“ und erfuhren mehr darüber, wie wir MQL5 verwenden können, um Handelssoftware zu codieren, Variablen in Bezug auf die Definition, ihre Typen und wie wir sie verwenden können. Wir haben auch einfache Datentypen wie Integer, Float, Double, String und Bool kennengelernt. Wir haben auch über Eingabevariablen gesprochen und darüber, wie sie verwendet werden können, um dem Nutzer die Möglichkeit zu geben, seine Einstellungen in der Software vorzunehmen.

In einem anderen Artikel, „Lernen Sie, wie man mit Datum und Uhrzeit in MQL5 umzugehen“, haben wir im Detail über den Datetime-Datentyp gelernt, weil wir gelernt haben, wie man diesen wichtigen Datentyp verwendet, die fast jede Software, vor allem Handels-Software verwendet.

In diesem Artikel werden wir mehr über Variablen und Datentypen in MQL5 erfahren und wie sie bei der Erstellung oder dem Aufbau von MQL5-Handelssoftware nützlich sein können. Wir werden mehr über einige fortgeschrittene Konzepte von Variablen und Datentypen erfahren und diese anhand der folgenden Themen behandeln:

  • Konstanten: Sie sind Bezeichner, deren Werte unverändert bleiben.
  • Arrays: Sie sind jede Art von Variablen mit mehreren Werten. 
  • Enumerationen: Sie sind ganzzahlige Listen von Konstanten mit ganzzahligen Werten.
  • Strukturen: Es handelt sich um eine Reihe von zusammenhängenden Variablen unterschiedlichen Typs.
  • Typecasting: Dies ist der Prozess der Umwandlung eines Wertes in einen anderen.
  • Lokale Variablen: Sie sind lokal deklarierte Variablen innerhalb von Funktionen.
  • Globale Variablen: Sie sind global deklarierte Variablen außerhalb von Funktionen.
  • Statische Variablen: Es handelt sich um deklarierte lokale Variablen, die ihre Werte im Speicher beibehalten.
  • Vordefinierte Variablen: Sie wurden vom Ersteller der Programmiersprache vordefiniert.

Wir werden versuchen, jedes Thema im Detail zu erklären, um zu verstehen, wie wir es verwenden können, und so viele Beispiele wie möglich zu sehen, um unser Verständnis zu vertiefen und in der Lage zu sein, alle genannten Konzepte effektiv zu verwenden. Programmieren ist eine Wissenschaft, bei der die Praxis sehr wichtig ist. Daher ist es sehr wichtig, dass Sie versuchen, das Gelernte anzuwenden und zu verstehen, wie Sie jedes Konzept als Teil Ihres Gesamtcodes verwenden können, um ein effektives Handelssystem zu erstellen.


Konstanten

In diesem Teil werden wir tief in das Konzept der Konstanten in der Programmierung und in MQL5 eintauchen, um zu verstehen, warum wir diese Art von Variablen verwenden müssen. Eine konstante Variable wird auch als schreibgeschützte oder benannte Konstante bezeichnet. Sie kann nicht geändert werden oder wir können ihr nach der ersten Initialisierung keinen neuen Wert zuweisen, und wenn der Code versucht, dies zu tun, wird er einen Fehler produzieren. Das Konzept der Konstante wird von den meisten Programmiersprachen unterstützt und auch MQL5 unterstützt dieses Konzept. Wir haben zwei Methoden, um die Konstante in unserer Software zu definieren:

  • Globale Konstanten
  • Mit dem Bezeichner const

Globale Konstanten:

Diese globale Konstante kann mit der Präprozessor-Direktive #define am Anfang unserer Software global definiert werden, dann geben wir den Bezeichner an und danach weisen wir den Wert der Konstante zu. Der konstante Wert kann ein beliebiger Datentyp sein, z. B. eine Zeichenkette, und das Folgende müssen wir in unserer Software codieren:

#define Identifier_Name constant_value

Wie wir im Code ober sehen können, haben wir die #define Präprozessor-Direktive, die angibt, dass wir eine konstante Deklaration haben, und wir können ein Beispiel wie das folgende sehen, um mehr über diese Methode zu verstehen:

Im globalen Bereich verwenden wir zunächst die Präprozessoranweisung #define, um zu deklarieren, dass wir eine Konstante haben, der Bezeichner ist PLATFORM_NAME und der konstante Wert des Bezeichners ist der String-Datentyp „MetaTrader 5“.

#define PLATFORM_NAME "MetaTrader 5"

In der benötigten Funktion können wir sagen, dass wir in OnStart() zum Beispiel den Bezeichner ausgeben werden

void OnStart()
  {
   Print("The trading platform name is: ", PLATFORM_NAME);
  }

Nach dem Kompilieren und Ausführen der Software finden wir das Ergebnis als Meldung auf der Registerkarte „Experte“, wie im folgenden Screenshot dargestellt

Beispiel einer Konstanten

Der konstante Wert von MetaTrader 5 kann, wie bereits erwähnt, nicht geändert werden.

Der Bezeichner const:

Nach dieser Methode können wir die Konstante deklarieren, indem wir den Spezifizierer „const“ vor der Variablen und ihrem Datentyp verwenden. Dieser Spezifizierer erklärt, dass es sich um eine Konstante handelt, die nicht geändert werden kann.

const int varName = assignedVal

Es folgt ein einfaches Beispiel für die Deklaration einer Konstante mit dieser Methode

const int val = 1;

Wenn wir den Wert dieser Variablen ausdrucken müssten

Print("constant val is: ", val);

Das Ergebnis ist dasselbe wie das folgende:

Beispiel 2 einer Konstanten

Wenn wir versuchen, die Variable „val“ zu aktualisieren, werden wir, wie bereits erwähnt, die folgende Fehlermeldung erhalten, da es sich um eine Konstante handelt, die nicht aktualisiert werden kann.

Fehler einer Konstanten

Um den Unterschied zwischen einer normalen Variablen und einer Konstanten zu verdeutlichen, können wir das folgende Beispiel verwenden, bei dem wir zwei Werte haben, von denen einer eine Konstante und der andere eine normale Variable ist.

   const int val = 1;
   int val2 = 2;
   
   Print("constant val is: ", val);
   Print("val 2 is: ", val2);
Das Ergebnis ist dasselbe wie auf dem folgenden Screenshot, wenn Sie diese Software ausführen

diffExam

Versuchen wir nun, val2 mit einem anderen Wert, nämlich 4, zu aktualisieren, und zwar mit diesem Code

val2 = 4;

Wenn Sie dann diese beiden Werte erneut ausdrucken, ist das Ergebnis dasselbe wie im folgenden Beispiel:

diffExam2

Wie wir sehen können, wird der Wert von val2 mit dem Wert 4 anstelle des Wertes 2 aktualisiert.

Arrays

In diesem Teil werden wir ein grundlegendes Konzept in jeder Programmiersprache verstehen, nämlich das Array. Das Array ist eine Variable, in der wir viele Werte eines beliebigen Datentyps speichern können. Wir können uns das Array als eine Liste mit Indizes und entsprechenden Werten vorstellen, wenn wir auf einen bestimmten Wert zugreifen müssen, können wir dies durch Indizierung tun.

Die Indizierung von Arrays beginnt bei Null, sodass der maximale Index dem Ergebnis einer Verringerung der Größe des Arrays um einen Wert entspricht. Wenn wir ein Array haben, das fünf Werte hat, dann können wir feststellen, dass seine Indizes (0, 1, 2, 3, 4) sind und der maximale Wert, wie wir sehen können, ist 4, was das Ergebnis von (5-1) ist.

Wenn wir auf den Wert eines bestimmten Indexes zugreifen müssen, verweisen wir auf ihn mit seinem Index, der in eckigen Klammern [] angegeben ist, und das ist es, was wir mit Zugriff durch Indizierung meinen, wie wir bereits erwähnt haben.

Wir haben auch ein statisches Array und ein dynamisches Array, und der Unterschied zwischen den beiden in Bezug auf die Größe des Arrays ist, dass das statische Array ein Array mit einer festen Größe ist und nicht in der Größe verändert werden kann, während das dynamische Array keine feste Größe hat und kann verwendet werden, wenn wir die Größe des Arrays ändern müssen.

Deklaration eines statischen Arrays

Wenn wir ein neues statisches Array deklarieren wollen, können wir dies anhand des folgenden Beispiels tun

int newArray[5];

newArray[0] = 1;
newArray[1] = 2;
newArray[2] = 3;
newArray[3] = 4;
newArray[4] = 5;

Print("newArray - Index 0 - Value: ", newArray[0]);
Print("newArray - Index 1 - Value: ", newArray[1]);
Print("newArray - Index 2 - Value: ", newArray[2]);
Print("newArray - Index 3 - Value: ", newArray[3]);
Print("newArray - Index 4 - Value: ", newArray[4]);

Nach der Ausführung dieser Software sehen wir das gleiche Ergebnis wie auf dem folgenden Screenshot

staticArrayDeclaration

Wir können dasselbe Ergebnis erzielen, wenn wir das Array mit dem folgenden abgekürzten Code deklarieren, indem wir dem Array Werte innerhalb der Klammern {} zuweisen und sie mit einem Komma (,) trennen.

   int newArray[5] = {1, 2, 3, 4, 5};

   Print("newArray - Index 0 - Value: ", newArray[0]);
   Print("newArray - Index 1 - Value: ", newArray[1]);
   Print("newArray - Index 2 - Value: ", newArray[2]);
   Print("newArray - Index 3 - Value: ", newArray[3]);
   Print("newArray - Index 4 - Value: ", newArray[4]);

 Wenn wir den vorherigen Code ausführen, erhalten wir das gleiche Ergebnis wie die gedruckten Meldungen.

Deklaration eines dynamischen Arrays

Wie bereits erwähnt, ist das dynamische Array ein Array ohne feste Größe und kann in seiner Größe verändert werden. Was wir hier wissen müssen, ist, dass diese Art von Array für das Speichern von Daten wie Preis und Indikator-Wert verwendet wird, da diese Daten dynamisch sind.

Wie wir ein neues, dynamisches Array deklarieren, zeigt der folgende Code:

   double myDynArray[];
   ArrayResize(myDynArray,3);

   myDynArray[0] = 1.5;
   myDynArray[1] = 2.5;
   myDynArray[2] = 3.5;
   
   Print("Dynamic Array 0: ",myDynArray[0]);
   Print("Dynamic Array 1: ",myDynArray[1]);
   Print("Dynamic Array 2: ",myDynArray[2]);

Wie wir im Code oben sehen können, haben wir das Array mit einer leeren eckigen Klammer deklariert. Dann haben wir die Funktion ArrayResize verwendet, um die Größe des Arrays zu ändern, und wir können das Ergebnis sehen, wenn wir die Software ausführen, wie im folgenden Screenshot gezeigt

dynamicArrayDeclaration

Wie in der vorherigen Abbildung zu sehen ist, werden für jeden Index und den entsprechenden Wert drei Meldungen gedruckt. Wir haben jetzt die eindimensionalen Arrays identifiziert, aber wir können auch mehrdimensionale Arrays wie zwei, drei oder vier verwenden, aber am häufigsten verwenden wir zwei oder drei.

Mehrdimensionale Arrays

Mehrdimensionale Arrays können als verschachtelte Arrays oder Arrays in Arrays betrachtet werden. Als Beispiel können wir sagen, dass wir zwei Arrays haben und jedes hat 2 Elemente, wie diese Art von Array im folgenden Code:

Deklaration von zweidimensionalen Arrays mit viel Einzelelementen

double newMultiArray[2][2];

Zuweisung von Werten oder Elementen an das erste Array mit dem Index 0

newMultiArray[0][0] = 1.5;
newMultiArray[0][1] = 2.5;

 Zuweisung von Werten oder Elementen des zweiten Arrays mit dem Index 1

newMultiArray[1][0] = 3.5;
newMultiArray[1][1] = 4.5;

Drucken der Werte von zwei Arrays und ihrer Elemente oder Werte

   Print("Array1 - Index 0 - Value: ", newMultiArray[0][0]);
   Print("Array1 - Index 1 - Value: ", newMultiArray[0][1]);
   Print("Array2 - Index 0 - Value: ", newMultiArray[1][0]);
   Print("Array2 - Index 1 - Value: ", newMultiArray[1][1]);

Nach der Ausführung dieser Software sehen wir die gleiche Ausgabe wie im folgenden Screenshot

multiDymArrays

Wie im vorherigen Screenshot zu sehen ist, haben wir Array 1 mit zwei Werten 1,5 und 2,5 und Array 2 mit zwei Werten 3,5 und 4,5.

An dieser Stelle sollte auch erwähnt werden, dass bei der Deklaration von mehrdimensionalen Arrays nur die erste Dimension leer bleiben kann, wie im folgenden Beispiel

double newMultiArray[][2];

Dann können wir sie mit Hilfe einer Variablen übergeben, die der folgenden entspricht

int array1 = 2;
ArrayResize(newMultiArray, array1);

Nachdem wir diese Software kompiliert und ausgeführt haben, werden wir das gleiche Ergebnis wie zuvor finden.


Enumerationen

In diesem Teil werden wir die Enumeration besprechen. Wir können uns Enumerationen als Datensätze oder Listen von Konstanten oder Elementen vorstellen, die zur Beschreibung verwandter Konzepte verwendet werden können, und es gibt integrierte Enumerationen und nutzerdefinierte Enumerationen. Integrierte Enumerationen sind in MQL5 vordefiniert und wir können sie in unserem Programm aufrufen und verwenden, aber nutzerdefinierte Enumerationen sind eigene Enumerationen, die unseren Bedürfnissen entsprechen.

Integrierte Enumeration finden wir in der Dokumentation oder Referenz von MQL5, zum Beispiel ENUM_DAY_OF_WEEK. Aber wenn wir einen Blick auf die nutzerdefinierten Enums werfen, können wir feststellen, dass wir einstellen können, was wir brauchen, um sie später in unserer erstellten Software zu verwenden.

Im Folgenden wird beschrieben, wie wir diese Enumerationen in unserer Software verwenden können. Zunächst verwenden wir das Schlüsselwort enum, um eine Enumeration, den Namen des Enumerationstyps und eine durch Kommas getrennte Liste von zugehörigen Datentypwerten zu definieren.

enum name of enumerable type 
  { 
   value 1,
   value 2,
   value 3
  };

Sehen wir uns ein Beispiel an, um unser benanntes workingDays enum zu erstellen, wobei workingDays ein Typ ist, für den ich später Variablen deklarieren werde

   enum workingDays
     {
      Monday,
      Tuesday,
      Wednesday,
      Thursday,
      Friday,
     };

Jetzt müssen wir eine neue verwandte Variable vom Typ workingDays deklarieren, den Wert von today unter den in der Liste definierten zuweisen und diese Variable drucken

     workingDays toDay;
     toDay = Wednesday;
     
     Print(toDay);

Die Meldung (2) für den Mittwoch als Arbeitstag finden wir in der Liste, die von 0 für Montag bis 4 für Freitag reicht, wie in der folgenden Abbildung gezeigt.

Enumerationen

Wir können auch eine andere Startnummer bestimmen, die anstelle von (0) zugewiesen wird, indem wir dem Wert die Nummer zuweisen, mit der wir beginnen müssen, z. B. indem wir angeben, dass Montag = 1 ist.


Strukturen

Es kann sein, dass wir eine Reihe verschiedener Datentypen für verwandte Variablen deklarieren müssen. In diesem Fall wird die Struktur dies effektiv tun, da sie dazu verwendet werden kann, dasselbe zu tun, wie wir in diesem Teil sehen werden. Die Mitglieder dieser Struktur können von jedem Datentyp sein, anders als bei einer Enumeration, deren Mitglieder nur vom gleichen Typ sein können. Es gibt vordefinierte Strukturen in der MQL5, wie MqlTick zum Beispiel, aber wir können auch unsere eigenen erstellen.

Angenommen, wir müssen eine Struktur für tradeInfo erstellen, dann sehen wir, dass wir das Symbol, den Preis, den Stop-Loss, den Take-Profit und den Zeitpunkt des Handels als Mitglieder haben, und sie haben unterschiedliche Datentypen, weil das Symbol eine Zeichenkette ist und der Preis, der Stop-Loss und der Take-Profit vom Typ „double“ sind. In diesem Fall müssen wir also Strukturen verwenden, um die gleiche Aufgabe wie unten beschrieben zu erfüllen:

Wir werden das Schlüsselwort struct verwenden, um unsere eigene Struktur zu deklarieren.

   struct tradeInfo
     {
      string         symbol;
      double         price;
      double         stopLoss;
      double         takeProfit;
     };

Wir können dann ein neues Handelsobjekt vom Typ tradeInfo deklarieren und den Mitgliedern dieser Struktur Werte zuweisen, indem wir mit (.) nach dem Objektnamen auf sie zugreifen, wie folgt

   tradeInfo trade;

   trade.symbol = "EURUSD";
   trade.price = 1.07550;
   trade.stopLoss = 1.07500;
   trade.takeProfit = 1.07700;

Wir können Mitglieder mit ihren Werten wie folgt ausdrucken, um unsere Arbeit wie folgt zu sehen

   Print("Symbol Trade Info: ", trade.symbol);
   Print("Price Trade Info: ", trade.price);
   Print("SL Trade Info: ", trade.stopLoss);
   Print("TP Trade Info: ", trade.takeProfit);

Die Ausgabe der gedruckten Nachricht finden wir in der gleichen Weise wie im folgenden Bildschirmfoto

struct

Wie in der vorherigen Abbildung zu sehen ist, sind die zugewiesenen Werte dieselben, die wir benötigen, sodass wir mit ihnen spielen können, um unsere Ziele im selben Kontext zu erreichen.


Typecasting

In diesem Abschnitt werden wir uns dem Konzept des Typecasting zuwenden und erklären, was es bedeutet. Wenn wir den Wert einer Variablen von einem Datentyp in einen anderen umwandeln müssen, können wir diesen Vorgang als Typecasting bezeichnen, aber dieser Vorgang kann zu unerwarteten Ergebnissen führen.

Wie ist das möglich? Wenn wir einen Wert mit Zahlen von einer Variablen in eine andere umwandeln oder kopieren, kann es zu einem Datenverlust kommen, wenn dieser Vorgang zwischen verschiedenen Typen stattfindet.

Nachfolgend sind Beispiele aufgeführt, bei denen keine Daten oder nur ein Teil der Daten verloren gegangen sind:

Wenn wir einen Integer-Wert in einen Long-Wert kopieren, kommt es in diesem Fall nicht zu dieser Art von Datenverlust, weil das Casting von kleineren zu größeren Variablen erfolgt. Wenn wir einen Integer-Wert in einen Double-Wert kopieren, wird auch die ganze Zahl kopiert und die Dezimalen nach dem Dezimalpunkt sind Null, sodass nichts verloren geht. Wenn wir einen Double-Wert in eine Integer-Variable kopieren, also der umgekehrte Fall, geht der Wert nach dem Dezimalpunkt verloren oder wird abgeschnitten.

Schauen wir uns den Code anhand von Beispielen an, um ihn besser zu verstehen. Zunächst werden wir den Fall ohne Probleme betrachten:

   int price = 3 - 1;
   double newPrice = price + 1;
   
   Print ("The price is ", newPrice);

Wie wir sehen können, ist der Typ der Variablen (Preis) int, dann wandeln wir sie in eine Double-Variable um und drucken sie aus. Es wird davon ausgegangen, dass es keine Probleme oder Datenverluste geben wird, weil wir von einem kleineren auf einen größeren Typ umstellen. Das Ergebnis des Ausdrucks ist wie folgt:

typeCasting1

Aber wenn wir das Gegenteil tun, werden wir etwas anderes sehen:

   double price = 3.50 - 1;
   int newPrice = price + 1;
   
   Print ("The price is ", newPrice);

Wie wir sehen können, ist der Typ double und der Wert 3.50 für die Preisvariable, und wenn wir sie in eine neue int-Variable (newPrice) umwandeln, dann drucken wir sie. Die Daten nach dem Dezimalpunkt, die den Wert von (.50) haben, gehen also verloren, und das Ergebnis ist (3), was der folgenden gedruckten Meldung entspricht

typeCasting2

Es ist sehr wichtig, hier zu erwähnen, dass der Compiler uns warnt, wenn wir einen Wert eines größeren Typs in eine Variable eines kleineren Typs umwandeln, sodass wir entscheiden können, ob wir diese Meldung ignorieren oder nicht, je nach unserem Ziel oder der Empfindlichkeit der verlorenen Daten. Nachstehend finden Sie ein Beispiel für diese Warnung:

typeCasting2

Wir können die Warnung auch ignorieren, wenn sie nicht schädlich ist, oder wir können sie abrunden, indem wir (int) vor die Double-Variable setzen, um die Warnung des Compilers zu vermeiden.


Lokale Variablen

In diesem Teil werden wir einen Blick auf ein neues Konzept werfen, nämlich die lokale Variable. Nehmen wir an, dass wir in unserer Software globale und lokale Bereiche haben. Der globale Bereich ist, dass wir zugreifen können, wo auch immer der Ort in unserer Software und wir werden einen Blick auf das Konzept der globalen im nächsten Thema in Bezug auf die Variablen, aber die lokalen sind nur im Bereich, in dem sie deklariert wurden, zugänglich.

Zur weiteren Klarstellung: Wenn wir eine Funktion haben und innerhalb dieser Funktion Variablen haben, die nur auf der Ebene der Funktion deklariert sind, werden diese Variablen als lokale Variablen betrachtet. Sie können also zugänglich sein, wenn die Funktion ausgeführt wird, und sind dann nach Beendigung der Funktion nicht mehr zugänglich.

Nehmen wir ein Beispiel, um dies zu verdeutlichen:

void myFunc()
{
   int var = 5;
   Print(var);
}

Wie wir im Code oben sehen können, haben wir die Funktion myFunc und diese Funktion kann überall aufgerufen werden. Wenn wir diese Funktion aufrufen, finden wir eine lokale Variable namens var und diese Variable kann nur innerhalb der Funktion verwendet werden, nach dem Verlassen der Funktion ist sie nicht mehr zugänglich.

Wenn wir also diese Funktion aufrufen, können wir feststellen, dass die Ausgabe 5 ist, was dem Folgenden entspricht

localVar

Wenn wir versuchen würden, von außerhalb der Funktion auf die lokale Variable var zuzugreifen, würde der Compiler einen Fehler (nicht deklarierter Bezeichner) wie den folgenden produzieren:

localVarError

Das Gleiche gilt, wenn wir verschachtelte Ebenen oder Bereiche innerhalb der Funktion haben, jede deklarierte Variable wird nur in ihrem Bereich zugänglich sein.

Nehmen wir auch in diesem Fall ein Beispiel:

void myFunc()
  {
   int var = 5;
   if(var == 5)
     {
      int newVar = 6 ;
      Print(newVar);
     }

  }

Wie wir im vorherigen Beispiel sehen können, haben wir if verschachtelt, um den Wert von var mit 5 zu vergleichen, und wenn es wahr ist, deklarieren wir newVar mit einem Wert von 6 und drucken es aus. Die Ausgabe wird 6 sein, weil die Bedingung wie folgt erfüllt ist

localVar2

Diese newVar ist eine neue lokale Variable innerhalb des Geltungsbereichs (scope) des if-Operators und kann nicht außerhalb des Geltungsbereichs zugänglich sein, wie jede andere lokale Variable auch, und wenn wir es versuchen, wird der Compiler den Fehler einer nicht deklarierten Variable erzeugen. Es ist wichtig zu wissen, dass jede Deklaration für eine Variable mit demselben Namen wie die lokale Variable die vorherige überschreibt und in einem höheren Bereich eingegeben wird.

Das Konzept ist also sehr einfach: Jede lokale Variable ist auf ihrer Ebene oder in ihrem Bereich innerhalb der Funktion zugänglich. Aber was tun wir, wenn wir auf eine Variable irgendwo in unserer Software zugreifen müssen? Hier kommt die globale Variable ins Spiel, wie wir im nächsten Thema über globale Variablen sehen werden.


Globale Variablen

Im vorangegangenen Thema über lokale Variablen haben wir globale Variablen erwähnt, d. h. Variablen, die global deklariert sind, sodass wir im Gegensatz zu lokalen Variablen von überall in unserer Software auf sie zugreifen können. Wenn wir also globale Variablen deklarieren müssen, werden wir darauf achten, sie global oder im globalen Bereich der Software, außerhalb jeder Funktion, zu deklarieren, damit wir sie überall in der Software verwenden oder aufrufen können. Diese Arten von Variablen können verwendet werden, wenn eine Variable deklariert werden soll, die von vielen Funktionen mehrfach verwendet wird.

Globale Variablen werden am Anfang oder am Anfang der Software definiert, nach den Eingabevariablen. Im Gegensatz zu lokalen Variablen führt der Versuch, globale Variablen innerhalb des Blocks zu deklarieren, zu dem Kompilierungsfehler „Declaration of variable hides global declaration“ (Deklaration einer Variablen verdeckt die globale Deklaration), wie im folgenden Beispiel:

globalVar

Wir können globale Variablen an jedem Punkt der Software aktualisieren, wie im folgenden Beispiel, das zeigt, wie wir globale Variablen deklarieren und aktualisieren können:

int stopLoss = 100;

void OnStart()
  {
   Print("1st Value: ", stopLoss);
   addToSL();
  }

void addToSL()
  {
   stopLoss = stopLoss + 50;
   Print("Updated Value: ", stopLoss);
  }

Wie aus dem vorherigen Codeblock ersichtlich, haben wir die Variable stopLoss global am Anfang der Software deklariert, den zugewiesenen Wert gedruckt, die Funktion addToSL() aufgerufen, die 50 zum ersten zugewiesenen Wert addiert hat, und dann den aktualisierten Wert gedruckt. Nach dem Kompilieren und Ausführen dieser Software finden wir die folgenden Meldungen gedruckt:

globalVar2

Wie wir sehen können, ist der erste Anfangswert der Variablen 100, und wenn wir ihn durch Hinzufügen von 50 in der Funktion addToSL() aktualisieren, wird daraus 150.

Statische Variablen

In diesem Teil werden wir eine weitere Art von Variablen identifizieren, nämlich die statische Variable. Statische Variablen sind lokale Variablen, aber sie behalten ihre Werte im Speicher, auch wenn die Software den Bereich von ihnen verlassen hat, und sie können im Block von Funktionen oder lokalen Variablen erklärt werden.

Wir können dies tun, indem wir das Schlüsselwort static vor dem Variablennamen verwenden und seinen Wert zuweisen. Das folgende Beispiel soll dies verdeutlichen

void staticFunc()
{
   static int statVar = 5;
   statVar ++;
   Print(statVar);
}

Dann rufen wir die Funktion staticFunc() auf

staticFunc();

Hier behält die Variable ihren Wert (5) im Speicher und jedes Mal, wenn wir die Funktion aufrufen, wird die Ausgabe 6 sein, was (5+1) entspricht. Im Folgenden sehen Sie einen Screenshot der Ausgabe:

staticVar

Wie wir sehen können, wird der Wert 6 in der Registerkarte „Experten“ ausgedruckt.


Vordefinierte Variablen

Im Bereich der Programmierung kann es vorkommen, dass wir immer wieder viele Zeilen schreiben müssen, um etwas Gewöhnliches zu tun. In vielen Programmiersprachen gibt es also Variablen oder sogar Funktionen, die vordefiniert sind, was bedeutet, dass sie kodiert sind und wir sie einfach verwenden können, ohne den gesamten Code neu schreiben zu müssen. Hier kommt die Rolle der vordefinierten Variablen ins Spiel. Alles, was wir tun müssen, ist, uns zu erinnern oder zu wissen, welches das Schlüsselwort ist, um etwas zu tun und es zu verwenden.

MQL5 hat viele vordefinierte Variablen, auf deren Werte wir auf die gleiche Weise zugreifen können wie in den folgenden Beispielen:

  • _Symbol: bezieht sich auf das aktuelle Symbol des Charts.
  • _Point: bezieht sich auf den Punktwert des aktuellen Symbols, er beträgt 0,00001 bei fünf Dezimalen des aktuellen Symbols und 0,001 bei drei.
  • _Period: bezieht sich auf den aktuellen Zeitrahmen des Charts.
  • _Digits: gibt die Anzahl der Dezimalstellen der Preise des Chart-Symbols an. Ist sie z. B. 5 haben die Preise 5 Stellen hinter dem Komma.
  • _LastError: bezieht sich auf den Wert des letzten Fehlers.
  • _RandomSeed: bezieht sich auf den aktuellen Status des Generators von Pseudo-Zufalls-Ganzzahlen.
  • _AppliedTo: bezieht sich auf das Verfahren, mit dem ein Indikator seine Werte errechnet.

Diese und andere vordefinierte Variablen finden Sie in der Dokumentation unter dem Abschnitt Vordefinierte Variablen.


Schlussfolgerung

Dieser Artikel erforscht die Feinheiten von MQL5 und konzentriert sich dabei auf wesentliche Programmierkonzepte wie Datentypen, Variablen und andere Schlüsselelemente, die für die Entwicklung fortgeschrittener Software entscheidend sind. Die Beherrschung von MQL5 erfordert das Verständnis sowohl grundlegender als auch komplexer Aspekte, wobei die Übung die Grundlage für die Beherrschung bildet. Dieser Leitfaden soll Ihnen helfen, MQL5 für die Entwicklung von Handelsplattformen zu erlernen. Weitere Einblicke in die Programmierung oder Erstellung von Handelssystemen mit beliebten technischen Indikatoren wie gleitende Durchschnitte, RSI und anderen finden Sie in meinen Publikationen, die detaillierte Artikel und Tipps zur Strategieentwicklung enthalten.



Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/14186

Deep Learning GRU model with Python to ONNX  with EA, and GRU vs LSTM models Deep Learning GRU model with Python to ONNX with EA, and GRU vs LSTM models
We will guide you through the entire process of DL with python to make a GRU ONNX model, culminating in the creation of an Expert Advisor (EA) designed for trading, and subsequently comparing GRU model with LSTN model.
The Disagreement Problem: Diving Deeper into The Complexity Explainability in AI The Disagreement Problem: Diving Deeper into The Complexity Explainability in AI
Dive into the heart of Artificial Intelligence's enigma as we navigate the tumultuous waters of explainability. In a realm where models conceal their inner workings, our exploration unveils the "disagreement problem" that echoes through the corridors of machine learning.
Modified Grid-Hedge EA in MQL5 (Part III): Optimizing Simple Hedge Strategy (I) Modified Grid-Hedge EA in MQL5 (Part III): Optimizing Simple Hedge Strategy (I)
In this third part, we revisit the Simple Hedge and Simple Grid Expert Advisors (EAs) developed earlier. Our focus shifts to refining the Simple Hedge EA through mathematical analysis and a brute force approach, aiming for optimal strategy usage. This article delves deep into the mathematical optimization of the strategy, setting the stage for future exploration of coding-based optimization in later installments.
Популяционные алгоритмы оптимизации: Гибридный алгоритм оптимизации бактериального поиска с генетическим алгоритмом (Bacterial Foraging Optimization - Genetic Algorithm, BFO-GA) Популяционные алгоритмы оптимизации: Гибридный алгоритм оптимизации бактериального поиска с генетическим алгоритмом (Bacterial Foraging Optimization - Genetic Algorithm, BFO-GA)
В статье представлен новый подход к решению оптимизационных задач, путём объединения идей алгоритмов оптимизации бактериального поиска пищи (BFO) и приёмов, используемых в генетическом алгоритме (GA), в гибридный алгоритм BFO-GA. Он использует роение бактерий для глобального поиска оптимального решения и генетические операторы для уточнения локальных оптимумов. В отличие от оригинального BFO бактерии теперь могут мутировать и наследовать гены.