English Русский
preview
Einführung in MQL5 (Teil 29): Beherrschung der API- und WebRequest-Funktion in MQL5 (III)

Einführung in MQL5 (Teil 29): Beherrschung der API- und WebRequest-Funktion in MQL5 (III)

MetaTrader 5Integration |
17 0
Israel Pelumi Abioye
Israel Pelumi Abioye

Einführung

Seien Sie gegrüßt und willkommen zurück zu Teil 29 der Serie Einführung in MQL5! Im vorigen Artikel haben wir die Elemente einer URL behandelt und entdeckt, wie man die API von MQL5 verwendet, um die neuesten Preise von externen Plattformen zu erhalten. Außerdem haben Sie gelernt, wie Sie die JSON-Antwort lesen und genau die Informationen abrufen können, die Sie benötigen.

In diesem Artikel gehen wir noch einen Schritt weiter, indem wir an einem nützlicheren Projekt arbeiten. Wir stellen eine Verbindung zu einer externen Plattform her und erhalten vollständige Kerzendaten, einschließlich der Uhrzeit, des Eröffnungs-, Höchst-, Tiefst- und Schlusskurses mehrerer Kerzen, und nicht nur den aktuellen Kurs. In diesem Artikel werden wir auch jedes einzelne Element aus diesen Daten extrahieren, sobald wir sie erhalten haben, und sie in verschiedenen Arrays speichern. Wir würden zum Beispiel alle offenen Preise in einem Array speichern, alle hohen Preise in einem anderen, und so weiter. Ihr Verständnis für die Verwaltung strukturierter JSON-Antworten, die Verarbeitung von Arrays in MQL5 und die effektive Strukturierung eingehender Marktdaten wird sich durch dieses Projekt verbessern.

 

Abrufen von Kerzendaten mit WebRequest

In der ersten Phase dieses Projekts wird die Funktion WebRequest zum Abrufen von Kerzendaten verwendet. Diesmal fragen wir nach vollständigen Kerzeninformationen und nicht nur nach dem aktuellen Preis, wie im letzten Artikel. Zeit, Eröffnungs-, Höchst-, Tiefst- und Schlusswerte sind darin enthalten.

In diesem Artikel werden wir eine externe Plattform nach den letzten fünf Kerzen eines jeden Tages fragen. Nach Erhalt der Daten werden wir diese anschließend aufschlüsseln und jede Preiskategorie in verschiedenen Arrays speichern, einschließlich aller offenen Preise, aller Höchstpreise usw.

Die Methode ist der erste Parameter in der WebRequest-Funktion. Die Methode muss auf GET gesetzt werden, da wir nur versuchen, Daten vom Server anzufordern und keine Daten zu übertragen oder zu aktualisieren. Dies zeigt dem Server, dass wir nur Informationen wollen.

Beispiel:
string method = "GET";

Im vorigen Artikel habe ich über die verschiedenen Bestandteile einer URL gesprochen. Dies sind das Protokoll, die Domäne, der Pfad und die Abfragezeichenfolge. Wenn Sie die Komponenten verstehen, wissen Sie genau, wohin die Anfrage geht und welche Ressource der Server zurückschicken soll.

Beispiel:

string method = "GET";
string url = "https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d&limit=5";

Alle Anweisungen für den Binance-Server sind in der URL enthalten. Das Protokoll, das immer zuerst erscheint und eine sichere Verbindung kennzeichnet, ist https://. Als Nächstes kommt die Domain api.binance.com, durch die dem MetaTrader der genauen Server mitgeteilt, mit dem er sich verbinden soll. Die URL /api/v3/klines, die hinter der Domain steht, teilt dem Server mit, dass wir nach Kerzendaten suchen.

Die Zeichenfolge der Abfrage ist alles, was nach dem Pfad kommt. Am Anfang der Zeichenfolge einer Abfrage steht immer ein Fragezeichen, um anzuzeigen, dass weitere Anweisungen gesendet werden. Das Handelspaar, für das wir Daten suchen, wird durch die erste Anweisung angegeben, symbol=BTCUSDT. Wir verwenden das Fragezeichen-Symbol, um einen Befehl hinzuzufügen. Zum Beispiel weist limit=5 den Server an, die letzten fünf Kerzen zurückzugeben, während interval=1d angibt, dass wir tägliche Kerzen wollen.

Analogie:

Stellen Sie sich vor, Sie gehen in einen großen Bürokomplex, um eine bestimmte Information zu erhalten. Eine sichere und verschlüsselte Verbindung wird durch die erste Komponente, https://, angezeigt, die der Hauptstraße ähnelt, über die man zum Gebäude gelangt. Das Gebäude selbst, der primäre Server, auf dem Binance alle seine Datendienste speichert, ist api.binance.com, das als Nächstes kommt.

Die Reise beginnt, sobald Sie das Gebäude betreten. Stellen Sie sich vor, Sie müssten durch eine Reihe von Räumen gehen, um die gewünschte Abteilung zu erreichen. Der Raum /api, der als Drehscheibe für alle API-Dienste dient, ist Ihr Ausgangspunkt. Sie können auf den Teil der API in Version 3 zugreifen, indem Sie durch die mit /v3 gekennzeichnete Tür in diesem Raum gehen. Die Abteilung, die speziell Kerzendaten speichert, befindet sich hinter der Tür /klines. Mit jedem Schritt kommen Sie den von Ihnen gewünschten Daten näher.

Der Abfragetext beginnt mit einem Fragezeichen, sobald er den richtigen Raum erreicht. Dies ist das erste Mal, dass Sie dem Server Anweisungen geben. Sie beginnen mit der Eingabe von symbol=BTCUSDT, was bedeutet, dass Sie nach Bitcoin-Daten in Relation zum US-Dollar suchen.

Das Zeichen „&“ wird verwendet, um jeden Befehl von anderen zu trennen. Nach dem ersten Befehl zur Angabe des Symbols wurde das Zeichen beispielsweise für weitere Befehle verwendet. Wenn wir &interval=1d verwenden, bedeutet das, dass wir die Tageskerze haben wollen. Wir haben auch &limit=5 verwendet, was bedeutet, dass wir die letzten 5 Kerzen haben wollen.

Wenn Sie die Abfragezeichenfolge richtig anordnen, kann der Server die genauen Daten erkennen, die Sie anfordern. Es ist wichtig zu wissen, dass die von den verschiedenen Plattformen verwendeten Formate variieren, daher ist es wichtig, die jeweiligen Dokumentationen zu lesen. Wir können nun die anderen Argumente für die WebRequest-Funktion festlegen, wie z. B. die Kopfzeilen, die Zeitüberschreitung, das Datenfeld, das Ergebnisfeld und den Text der Ergebniskopfzeilen. Wir können die WebRequest-Funktion verwenden, um unsere Anfrage zu senden und die Kerzendaten direkt von der Binance-API zu erhalten, sobald sie eingerichtet sind.

Beispiel:

string method = "GET";
string url = "https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1d&limit=5";
string headers = "";
int time_out = 5000;
char   data[];
char   result[];
string result_headers;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   WebRequest(method, url, headers, time_out, data, result, result_headers);
   string server_result = CharArrayToString(result);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }

Es funktioniert ähnlich wie das Versenden eines Briefes an ein Unternehmen und das Warten auf eine Antwort, wenn das Programm eine Anfrage an den Server sendet. Der Inhalt des Umschlags, wie z. B. die Adresse, die Art der Anfrage und alle Informationen, auf die geantwortet werden soll, werden als Methode, URL, Header, Timeout und Daten bezeichnet. Der Umschlag wird dem Server zugestellt, sobald er vorbereitet ist.

Stellen Sie sich vor, Sie betreten ein großes Bürogebäude, in dem eine zentrale Poststelle die gesamte Eingangspost entgegennimmt. Alles ist in Postsäcke gestopft, unleserlich und vermischt. Bevor jemand verstehen kann, was gesendet wurde, müssen diese Briefe sortiert werden. Der erste Schritt ist vergleichbar mit dem Erhalt eines versiegelten Postsacks eines Kuriers. Sie halten jetzt den Postsack in der Hand, können aber immer noch nicht lesen, was darin steht. Es handelt sich lediglich um einen unstrukturierten Container voller Rohmaterialien.

Es ist so, als würde man den Postsack auf dem Tisch ausleeren und die Briefe so aufstellen, dass man sie lesen kann. Aus der unübersichtlichen und unverständlichen Masse wird eine klare, übersichtliche Information, wenn die Elemente richtig angeordnet sind. Jetzt, wo jeder Buchstabe einen Sinn ergibt, können Sie damit beginnen, seinen Inhalt zu nutzen. Hier gilt das gleiche Konzept. Als Erstes erhalten Sie eine unbearbeitete Antwort, die in einem wenig hilfreichen Format vorliegt. Danach wandeln Sie sie in ein klares, lesbares Format um, damit Sie endlich verstehen können, was der Server gesendet hat.

Ausgabe:

Abbildung 1. Ergebnis

Ergebnis:

[

  [

1763337600000, "94261.45000000", "96043.00000000", "91220.00000000", "92215.14000000", "39218.59806000", 1763423999999, "3674562070.23860600", 8134322, "18690.19245000", "1750979467.78626070", "0"

  ],

  [

1763424000000, "92215.14000000", "93836.01000000", "89253.78000000", "92960.83000000", "39835.14769000", 1763510399999, "3641033186.30045840", 8786593, "20130.95957000", "1841176605.14182350", "0"

  ],

  [

1763510400000, "92960.83000000", "92980.22000000", "88608.00000000", "91554.96000000", "32286.63760000", 1763596799999, "2925773651.25595790"

Wir waren nicht in der Lage, die gesamte Server-Antwort aufgrund des MetaTrader 5 Expert Logs zu drucken, aber die Software kann trotzdem die kompletten Daten lesen.

 

Verstehen des Formats der zurückgesendeten Kerzendaten

Nachdem wir die Kerzendaten erhalten haben, besteht der nächste Schritt darin, das vom Server verwendete JSON-Muster zu verstehen. Dies ist von großer Bedeutung, da verschiedene Systeme Daten auf unterschiedliche Weise übermitteln. Sie werden nicht wissen, wie Sie die richtigen Werte erhalten, wenn Sie nicht zuerst das Muster studieren. Es ist immer eine gute Idee, sich die Struktur der Antwort anzusehen, bevor man eine Extraktionslogik entwickelt.

Wir können das Muster, das Binance verwendet, deutlich in dem kleinen Ausschnitt der Antwort sehen, den MetaTrader 5 ausdrucken konnte. Jede Kerze wird in einem Array dargestellt, und jeder Wert in diesem Array hat eine bestimmte Bedeutung. Das Muster ist im folgenden Beispiel zu sehen:

[

  [

    1763337600000, "94261.45000000", "96043.00000000", "91220.00000000", "92215.14000000", "39218.59806000",

    1763423999999, "3674562070.23860600", 8134322, "18690.19245000", "1750979467.78626070", "0"

  ],

  [

    1763424000000, "92215.14000000", "93836.01000000", "89253.78000000", "92960.83000000", "39835.14769000",

    1763510399999, "3641033186.30045840", 8786593, "20130.95957000", "1841176605.14182350", "0"

  ],

  [

    1763510400000, "92960.83000000", "92980.22000000", "88608.00000000", "91554.96000000", "32286.63760000",

    1763596799999, "2925773651.25595790"

Jedes innere Feld steht für eine volle Kerze und ist in der gleichen Reihenfolge angeordnet. Die Eröffnungszeit der Kerze steht an erster Stelle, dann folgen der Eröffnungskurs, der Höchstkurs, der Tiefstkurs, der Schlusskurs und das Volumen. Danach sehen Sie weitere Zahlen wie den Zeitpunkt des Handelsschlusses, das Volumen der notierten Vermögenswerte, die Anzahl der Abschlüsse und vieles mehr. MetaTrader 5 konnte nicht die gesamte Antwort veröffentlichen, da er eine Zeichenbegrenzung hat, aber der Teil, der gedruckt wurde, reicht aus, um das Format zu verstehen.

Format:

[

  [array 1],

  [array 2],

  [array 3],

  [array 4],

  [array 5]

]

Kommas trennen diese inneren Felder, von denen jedes eine einzelne, vollständige Kerze darstellt. Jedes Array enthält die tatsächlichen Daten für jede Kerze, die nach einer bestimmten, von Binance verwendeten Reihenfolge sortiert sind.

Eines der Arrays sieht zum Beispiel wie folgt aus:

[

  1763337600000, "94261.45000000", "96043.00000000",

  "91220.00000000", "92215.14000000", "39218.59806000",

  1763423999999, "3674562070.23860600", 8134322,

  "18690.19245000", "1750979467.78626070", "0"

]

Eine komplette Kerze wird durch dieses gesamte Array dargestellt. Die erste Zahl steht für die Eröffnungszeit der Kerze in Millisekunden, die zweite für den Eröffnungskurs, gefolgt vom Höchstkurs, Tiefstkurs und Schlusskurs. In der Zukunft wird die Kerze bei 1763423999999 schließen. Das Volumen der Börsennotierung wird durch die nachfolgende große Zahl „3674562070.23860600“ und die Anzahl der Handelsgeschäfte durch 8134322 angezeigt. Der Kunde kauft ein Basis-Volumen des Assets von „18690.19245000“ und der Kunde kauft Kurs-Volumen des Assets von „1750979467.78626070“. Schließlich ist „0“ ein nicht verwendetes Feld, das sich auf die Kompatibilität bezieht.

Das Verständnis des Musters macht es einfach, die genauen Werte zu extrahieren, die Sie benötigen, einschließlich Eröffnungs-, Höchst-, Tiefst- und Schlusskursen, und jeden einzelnen in einem eigenen Array zu speichern.


Trennen von Kerzenwerten in einzelne Arrays

Der nächste Schritt besteht darin, diese Werte in verschiedene Arrays aufzuteilen, da wir nun wissen, wie die Antwort des Servers aussieht und dass die Daten für jede Kerze in einer bestimmten Reihenfolge angeordnet sind. Dies macht es einfacher, die Eröffnungszeit, den Eröffnungskurs, den Höchstkurs, den Tiefstkurs, den Schlusskurs und das Volumen später in unserem Indikator oder Expert Advisor zu analysieren und zu verwenden, da wir sie separat speichern können.

Wir können den Index 0 als die jüngste Kerze, den Index 1 als die davor liegende Kerze und die übrigen Kerzen als demselben Muster folgend betrachten, da jedes innere Array die vollständigen Daten für eine einzelne Kerze enthält. Dank dieser Struktur ist es einfach, auf jede Kerze einzeln zuzugreifen und genau die Werte abzurufen, die wir benötigen.

Der erste Schritt bei der Konvertierung der rohen Server-Antwort in verschiedene Arrays ist die Auswahl eines Zeichens, das es uns ermöglicht, zwischen verschiedenen vollständigen Kerzen zu unterscheiden. Da Kommas auch innerhalb der einzelnen Kerzenwerte vorkommen, würde der Versuch, die Kerzen mit Hilfe des Kommas zu teilen, nie gelingen. Das bedeutet, dass sich alles auflöst und es unmöglich sein wird, die richtigen Werte wieder zusammenzusetzen. Wir benötigen ein Zeichen, das nicht in den Werten selbst vorkommt, sondern nur am Ende jedes Kerzendatensatzes.

Ergebnis:

[

  [

    1763337600000, "94261.45000000", "96043.00000000", "91220.00000000", "92215.14000000", "39218.59806000",

    1763423999999, "3674562070.23860600", 8134322, "18690.19245000", "1750979467.78626070", "0"

  ],

  [

    1763424000000, "92215.14000000", "93836.01000000", "89253.78000000", "92960.83000000", "39835.14769000",

    1763510399999, "3641033186.30045840", 8786593, "20130.95957000", "1841176605.14182350", "0"

  ],

  [

    1763510400000, "92960.83000000", "92980.22000000", "88608.00000000", "91554.96000000", "32286.63760000",

    1763596799999, "2925773651.25595790"

Wir können das Komma nicht verwenden, um die Elemente des Arrays zu trennen, weil wir alle täglichen Daten für jeden Tag zusammenfassen wollen. Viele der Zahlen auf jeder Kerze, einschließlich der Eröffnungszeit, des Eröffnungs-, Höchst-, Tiefst- und Schlusskurses sowie des Volumens, sind durch Kommas getrennt. Die Funktion würde jeden Wert innerhalb der Kerze trennen, anstatt die Kerze als eine Einheit zu betrachten, wenn wir versuchen würden, die Kerzen mit Kommas zu isolieren. Zu wissen, welche Zahlen zu welcher Kerze gehören, wäre daher äußerst schwierig.

Die Daten wären verstreut, und die einzelnen Kerzenwerte würden durch die Verwendung von Kommas als Trennzeichen effektiv durcheinander gebracht. Es würde schwierig und fehleranfällig werden, die korrekte Nummernfolge jeder Kerze wieder zusammenzusetzen. Das Ziel, die Kerzendaten für die Analyse zu organisieren, würde verfehlt, da die Integrität jeder Kerze als separate Datensammlung verloren ginge.

Um diese Schwierigkeit zu lösen, müssen wir ein Zeichen verwenden, das nicht zu den tatsächlichen Zahlen der Kerze gehört. Für jede Kerze sollte dieses Zeichen nur einmal vorkommen, idealerweise gegen Ende der Kerzendatenerfassung. Wir achten darauf, dass sich jede Kerze deutlich von den anderen unterscheidet, ohne dass die Werte, für die sie steht, durch die Wahl eines solchen Zeichens beeinträchtigt werden.

Da sie immer am Ende jedes Kerzenblocks erscheint, ist die Schlussklammer für diese Funktion ideal. Wir können jede Kerze in ein eigenes Feld aufteilen, indem wir die schließende Klammer als Trennzeichen verwenden. Diese Methode ermöglicht es, die Struktur der Kerzendaten beizubehalten und erleichtert den Zugriff, die Verarbeitung und die Analyse jeder einzelnen Kerze, ohne dass die Gefahr besteht, dass die Daten durch Kommas durcheinander gebracht werden.

Beispiel:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   WebRequest(method, url, headers, time_out, data, result, result_headers);
   string server_result = CharArrayToString(result);
// Print(server_result);

   string candle_data[];
   int array_count = StringSplit(server_result,']', candle_data);
   
   Print(array_count);

//---
   return(INIT_SUCCEEDED);
  }

Erläuterung:

Wir haben zunächst ein dynamisches Array mit Zeichen, deklariert mit dem Namen candle_data, damit wir jede Kerze unabhängig voneinander behalten können, nachdem wir die große Binance-API-Antwort in kleinere Teile zerlegt haben.

Als Nächstes haben wir MQL5 angewiesen, die Zeichenkette server_result immer dann abzuschneiden, wenn es auf das Zeichen ']' stößt. Da jede Kerze im zurückgegebenen Datenmuster mit einem ']' endet, haben wir beschlossen, dieses Zeichen zu verwenden. Es ist das einzige eindeutige Zeichen, das konsequent das Ende eines jeden Kerzenblocks anzeigt. Kommas erscheinen innerhalb der Kerzenwerte selbst, z. B. bei der Trennung von Eröffnungs-, Höchst-, Tiefst- und Schlusskursen; daher können wir sie nicht als Trennzeichen verwenden. ']' ist jedoch die sicherste Option, da sie nur nach jeder Kerzen-Array erscheint.

Für die Funktion StringSplit werden drei Parameter benötigt. Die zu teilende Zeichenkette, in diesem Fall server_result, ist der erste Parameter. Der zweite Parameter ist das Zeichen ']', das zur Aufteilung der Zeichenkette verwendet werden soll. Der dritte Parameter ist unser candle_data-Array, in dem die geteilten Stücke gespeichert werden. Die Funktion gibt die Gesamtzahl der Stücke zurück, die nach der Aufteilung des Textes identifiziert wurden, und wir speichern diese Menge in array_count.

Betrachten Sie einen einfachen Beispielstring wie „MQL5, ALGO, TRADING“, um zu verstehen, wie die Funktion zählt. Die Funktion erkennt zwei Kommas, wenn wir sie mit dem Kommazeichen trennen, aber die Zahl, die sie liefert, ist drei. Dies ist darauf zurückzuführen, dass StringSplit stets davon ausgeht, dass auf jedes Trennzeichen ein Element folgt. Sie zählt also auch dann, wenn der letzte Teil leer ist. Unsere Kerzendaten werden nach der gleichen Logik getrennt. Jedes Mal, wenn die Funktion auf ein ']' stößt, zählt sie die nächste Kerze, nachdem sie diese als Ende der vorherigen Kerze betrachtet hat.

Ausgabe:

Abbildung 2. Split-Zählung

In diesem Fall gibt die Funktion StringSplit einen Wert von 7 zurück. Ein Blick auf die Anzahl der ']'-Zeichen in der Serverantwort hilft uns, den Grund dafür zu verstehen. Da jede der fünf Kerzen, für die wir Daten angefordert haben, mit einem ']' endet, haben wir bereits fünf schließende Klammern. Ein '['-Zeichen erscheint am Anfang der gesamten Antwort, bevor die erste Kerze beginnt, und ein weiteres ']'-Zeichen befindet sich ganz am Ende der gesamten Struktur. Dies bedeutet, dass die Antwort insgesamt sechs schließende Klammern hat.

Da StringSplit immer davon ausgeht, dass auf das Trennzeichen ein weiteres Textelement folgt, wird nach dem letzten ']' ein zusätzliches Element erstellt, da der Text immer dann geteilt wird, wenn er auf ein solches trifft. Daher gibt die Methode 7 zurück, obwohl die Antwort 6 schließende eckige Klammern hat, was bedeutet, dass sie 6 Splits plus ein zusätzliches leeres Segment am Ende gezählt hat. Das erklärt, warum array_count 7 anzeigt, obwohl wir nur nach 5 gefragt haben.

Der nächste Schritt besteht darin, jede Komponente des Arrays einzeln auszudrucken, nachdem die Serverantwort mit der StringSplit-Methode erfolgreich in verschiedene Teile aufgeteilt wurde. Auf diese Weise können wir überprüfen, ob die Aufteilung wie beabsichtigt funktioniert hat, und nachvollziehen, was jeder Teil beinhaltet. Wir können feststellen, welche Teile des Textes sich auf jede Kerze beziehen und welche nur übrig gebliebene leere Abschnitte sind, die während des Aufteilungsverfahrens entstanden sind, indem wir jeden Bestandteil separat betrachten.

Beispiel:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   WebRequest(method, url, headers, time_out, data, result, result_headers);
   string server_result = CharArrayToString(result);
// Print(server_result);

   string candle_data[];
   int array_count = StringSplit(server_result,']', candle_data);
 
   Print(candle_data[0]);

//---
   return(INIT_SUCCEEDED);
  }

candle_data[0]:

[[1763424000000,

  "92215.14000000",

  "93836.01000000",

  "89253.78000000",

  "92960.83000000",

  "39835.14769000",

  1763510399999,

  "3641033186.30045840",

  8786593,

  "20130.95957000",

  "1841176605.14182350",

  "0"

candle_data[1]:

,[

  1763510400000,

  "92960.83000000",

  "92980.22000000",

  "88608.00000000",

  "91554.96000000",

  "32286.63760000",

  1763596799999,

  "2925773651.25595790",

  6822174,

  "15060.08451000",

  "1365200809.17455710",

  "0"

candle_data[2]:

[

  1763596800000,

  "91554.96000000",

  "93160.00000000",

  "86100.00000000",

  "86637.23000000",

  "39733.19073000",

  1763683199999,

  "3548950335.09842180",

  7841395,

  "18283.84047000",

  "1634256490.95743210",

  "0"


Extrahieren von Zeit- und OHLC-Werten aus den Daten der ersten Kerze

Nach der Aufteilung der Serverantwort gibt es mehrere Einträge im Array, von denen jeder einen Teil der ursprünglichen Daten darstellt. An dieser Stelle ist es entscheidend, welches Element zu welcher Kerze gehört. Eröffnungszeit, Eröffnungskurs, Höchstkurs, Tiefstkurs und Schlusskurs gehören zu den besonderen Werten, die in jeder Kerze zu finden sind, und diese Daten sind vorhersehbar angeordnet. Es wäre schwierig zu bestimmen, welche Zahl welchem Merkmal der Kerze entspricht, ohne die Inhaltsstoffe genau zu spezifizieren.

Der erste Schritt im Identifizierungsprozess besteht darin, sich das Muster des ersten Elements des Arrays anzusehen. Anhand der Struktur dieses Elements, das häufig die jüngste Kerze widerspiegelt, lässt sich erkennen, wie die verschiedenen Werte angeordnet sind. Durch die Kenntnis der Reihenfolge können wir jede Zahl dem entsprechenden Kerzenmerkmal zuordnen, was eine genaue Interpretation der Daten gewährleistet. Nachdem wir das Muster für die erste Kerze verstanden haben, können wir die gleiche Argumentation auch für die anderen Komponenten anwenden. Alle folgenden Elemente des Arrays haben die gleichen Werte, da die Serverantwort für jede Kerze eine einheitliche Struktur hat. Diese Einheitlichkeit garantiert eine korrekte Zuordnung der Daten jeder Kerze und erleichtert die Automatisierung des Identifizierungsverfahrens.

Schließlich muss jede Komponente identifiziert werden, um mit der Verarbeitung und Analyse fortzufahren. Wir können Berechnungen durchführen, zusammengehörige Werte zu Vergleichszwecken kombinieren oder die Zeichenkettendarstellungen in Zahlen umwandeln, nachdem jeder Wert genau seiner entsprechenden Kerze zugeordnet wurde. Diese Phase ist für die Arbeit mit API-Antworten in MQL5 unerlässlich, da sie als Grundlage für alle weiteren Operationen mit den Kerzendaten dient.

candle_data[0]:

[[

  1763424000000,       // opening time

  "92215.14000000",    // open price

  "93836.01000000",    // high price

  "89253.78000000",    // low price

  "92960.83000000",    // close price

  "39835.14769000",    // volume

  1763510399999,       // closing time

  "3641033186.30045840", // quote asset volume

  8786593,             // number of trades

  "20130.95957000",    // taker buy base asset volume

  "1841176605.14182350", // taker buy quote asset volume

  "0"                  // placeholder

Nur der Eröffnungszeitpunkt und die OHLC-Werte können leicht aus dem Index 0 der Kerzendaten extrahiert werden, indem einfach die unerwünschten Zeichen entfernt und die Zeichenkette durch Kommata getrennt wird.

Beispiel:
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   WebRequest(method, url, headers, time_out, data, result, result_headers);
   string server_result = CharArrayToString(result);
// Print(server_result);

   string candle_data[];
   int array_count = StringSplit(server_result,']', candle_data);

   string day1_data = candle_data[0];
   StringReplace(day1_data,"[[","");
   StringReplace(day1_data,"\"","");

   Print(day1_data);

//---
   return(INIT_SUCCEEDED);
  }

Erläuterung:

Um die Informationen aus dem ersten Element des Kerzen-Datenarrays zu speichern, erstellen wir zunächst eine String-Variable. Dies erleichtert die Arbeit an dieser einen Kerze, ohne die übrigen Daten zu beeinträchtigen. Bevor wir die nützlichen Werte extrahieren können, müssen wir den in dieser Variablen enthaltenen Wert bereinigen, der noch unerwünschte Zeichen wie doppelte Klammern und Anführungszeichen enthält.

Die Methode StringReplace wird verwendet, um diese irrelevanten Zeichen zu entfernen. Damit diese Funktion funktioniert, werden drei Parameter benötigt. Der erste Parameter ist der Text, den Sie bereinigen möchten. Der zweite Parameter ist genau das Zeichen oder die Zeichengruppe, die Sie eliminieren möchten. Der dritte Parameter gibt an, womit Sie ihn ersetzen möchten. Die irrelevanten Zeichen werden nur entfernt, wenn der Ersetzungsparameter eine leere Zeichenfolge ist. Wir entfernen also die Anführungszeichen und doppelten Klammern aus dem Text, indem wir diese Funktion verwenden. Die Kerzendaten sind leichter zu verarbeiten und können nach dieser Bereinigungsphase in verschiedene Abschnitte unterteilt werden, z. B. in die Eröffnungszeit, den Eröffnungskurs, den Höchstkurs, den Tiefstkurs und den Schlusskurs.

Analogie:

Stellen Sie sich vor, Sie besuchen eine Bibliothek und nehmen ein uraltes Buch mit mehreren zusammengeklebten Seiten heraus. Sie müssen die Schichten, die den eigentlichen Inhalt verdecken, vorsichtig abziehen, bevor Sie die erste Seite deutlich sehen können.  Das Schreiben von string day1_data = candle_data[0]; ist vergleichbar mit der Auswahl der ersten Seite aus einem großen, mehrseitigen Buch. Das große Buch ist die vollständige Serverantwort von der API, mit einer Seite für jede Kerze. Wir extrahieren nur die erste Seite, damit wir sie unabhängig bearbeiten können, indem wir candle_data[0] wählen.

StringReplace(day1_data, "[[", ""); funktioniert ähnlich wie die Beseitigung eines fremden Wrappers, der oben auf der Seite angebracht ist. In alten Büchern kleben gelegentlich Dinge, Etiketten oder Klebebandreste auf der ersten Seite. Solange Sie diese nicht entfernen, kann die Seite nicht richtig gelesen werden. Ähnlich wie bei diesem unerwünschten Band sind die Zeichen [[ in den Daten]. Wir entfernen sie sorgfältig, da sie nicht zu den Informationen gehören, die wir benötigen.

Danach ist StringReplace(day1_data,", ""); vergleichbar mit dem Abwischen all der kleinen Staubpartikel oder Flecken, die auf dem Papier verstreut sind. Wenn wir die Zahlen richtig behandeln wollen, sind diese doppelten Anführungszeichen, die die Werte umgeben, nutzlos. Sie werden entfernt, sodass die Seite klar und einfach zu lesen ist. Zum Schluss halten wir die bereinigte Seite in ein helles Licht, um sie mit Print(day1_data); zu untersuchen. Wir vergewissern uns, dass der Staub entfernt wurde, der Umschlag abgenommen wurde und ein lesbarer Text übrig geblieben ist, den wir nun verstehen und für die weitere Verarbeitung nutzen können.

Ausgabe:

1763510400000,

92960.83000000,

92980.22000000,

88608.00000000,

91554.96000000,

32286.63760000,

1763596799999,

2925773651.25595790,

6822174,

15060.08451000,

1365200809.17455710,

0

Die Rohdaten der Kerze wurden korrekt wiederhergestellt, sind aber immer noch zu einer einzigen, langen Zeichenkette zusammengefügt. Wir können sie nicht als einen einzigen Textblock beibehalten, da wir mit jedem Wert unabhängig arbeiten müssen, einschließlich der Eröffnungszeit, des Eröffnungs-, Höchst-, Tiefst- und Schlusskurses. Diese bereinigte Zeichenkette muss dann geteilt und in ein Array umgewandelt werden, damit auf jede Komponente separat zugegriffen werden kann und sie in unseren Berechnungen verwendet werden kann.

Beispiel:
WebRequest(method, url, headers, time_out, data, result, result_headers);
string server_result = CharArrayToString(result);
// Print(server_result);

string candle_data[];
int array_count = StringSplit(server_result,']', candle_data);

string day1_data = candle_data[0];
StringReplace(day1_data,"[[","");
StringReplace(day1_data,"\"","");

string day1_data_array[];
StringSplit(day1_data,',',day1_data_array);
ArrayPrint(day1_data_array);

Ausgabe:

Abbildung 3. Tag 1

Erläuterung:

Wir begannen damit, eine dynamische Array-Variable zu deklarieren, um eine lange Zeichenkette zu speichern, nachdem wir die unnötigen Zeichen entfernt hatten. Die Zeichenkette muss ein Array sein, da ihr Inhalt in verschiedene Elemente umgewandelt wird. Da die Zeichenketten durch Kommas voneinander getrennt werden, ist es hilfreich, sie in einzelne Elemente aufzuteilen.

Stellen Sie sich die Kerzendaten wie eine lange Eisenbahnstrecke mit zahlreichen miteinander verbundenen Waggons vor: Uhrzeit, Eröffnung, Höchststand, Tiefststand, Schlussstand usw. Sie können nur mit einem Coach arbeiten, wenn Sie alle Coaches voneinander trennen, weil sie alle miteinander verbunden sind. Die erste Zeile – string day1_data_array[]; – ist vergleichbar mit der Einrichtung eines großen, leeren Parkplatzes, auf dem jeder Reisebus nach seiner Trennung separat positioniert wird.

Die zweite Zeile – StringSplit(day1_data, ',', day1_data_array); – ähnelt einem Gadget, das den Zug an jedem Komma unterbricht. Der Zug wird an der Kommastelle unterbrochen. Jeder Wagen, der für einen Wert wie Eröffnungszeit, Eröffnungskurs, Höchst-, Tiefst- oder Schlusskurs steht, erhält nach der Aufteilung einen eigenen Platz auf dem Parkplatz. Alle Informationen sind jetzt leicht zugänglich und getrennt. Die letzte Zeile, ArrayPrint(day1_data_array);, ist so ähnlich, als würde man vor einem Parkplatz stehen und eine Liste aller Busse erstellen, um sich zu vergewissern, dass sie richtig getrennt und angeordnet sind.


Extrahieren von Zeit- und OHLC-Werten aus den Daten der zweiten Kerze

Nach der ersten Kerze ist die zweite Kerze die nächste in der Reihe. Das Verfahren ist immer noch dasselbe wie bei der ersten Kerze, um die Genauigkeit zu gewährleisten und die gleiche Struktur beizubehalten. Wir verringern die Wahrscheinlichkeit, dass Werte verwechselt werden, und ermöglichen eine präzise Datenanalyse und -speicherung, indem wir jede Kerze unabhängig verarbeiten.

Bevor Sie versuchen, die Daten für die zweite Kerze aufzuteilen, ist es wichtig, das Rohmuster im Detail zu untersuchen. Durch den Ausdruck der Rohantwort können wir alle irrelevanten Zeichen identifizieren, die den Aufteilungsprozess behindern können, einschließlich Kommas, Klammern oder Anführungszeichen. Durch diesen Schritt kann verhindert werden, dass die Extraktion numerischer Werte durch versehentliches Hinzufügen unerwünschter Zeichen zum Array beeinträchtigt wird.

Wir können überprüfen, ob die Serverantwort eine konsistente Struktur aufweist, indem wir das genaue Format der Rohdaten für die zweite Kerze verstehen. Ebenso können wir sicher sein, dass die Reihenfolge der Werte – Eröffnungszeit, Eröffnungs-, Höchst-, Tiefst- und Schlusskurs – konstant bleibt, indem wir sie mit der ersten Kerze vergleichen. Dank dieser Konsistenz werden wir auch dasselbe Bereinigungs- und Aufteilungsverfahren verwenden, ohne dass wir Anpassungen für Variationen im Datenformat vornehmen müssen.

Beispiel:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   WebRequest(method, url, headers, time_out, data, result, result_headers);
   string server_result = CharArrayToString(result);
// Print(server_result);

   string candle_data[];
   int array_count = StringSplit(server_result,']', candle_data);

//DAY 1
   string day1_data = candle_data[0];
   StringReplace(day1_data,"[[","");
   StringReplace(day1_data,"\"","");

   string day1_data_array[];
   StringSplit(day1_data,',',day1_data_array);

//DAY 2
   Print(candle_data[1]);

//---
   return(INIT_SUCCEEDED);
  }

Ausgabe:

, [

1763596800000, // Opening time

"91554.96000000", // Open price

"93160.00000000", // High price

"86100.00000000", // Low price

"86637.23000000", // Close price

"39733.19073000",  

1763683199999,

"3548950335.09842180",

7841395,

"18283.84047000",

"1634256490.95743210",

"0"

Nach der Überprüfung des Formats stellen wir fest, dass bestimmte Zeichen entfernt werden müssen, darunter das Komma, gefolgt von einer einleitenden eckigen Klammer, und die doppelten Anführungszeichen. Wir könnten ein String-Array deklarieren, um die Daten für den zweiten Tag zu speichern, nachdem wir die unnötigen Zeichen entfernt haben.

Beispiel:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   WebRequest(method, url, headers, time_out, data, result, result_headers);
   string server_result = CharArrayToString(result);
// Print(server_result);

   string candle_data[];
   int array_count = StringSplit(server_result,']', candle_data);

//DAY 1
   string day1_data = candle_data[0];
   StringReplace(day1_data,"[[","");
   StringReplace(day1_data,"\"","");

   string day1_data_array[];
   StringSplit(day1_data,',',day1_data_array);

//DAY 2
   string day2_data = candle_data[1];
   StringReplace(day2_data,",[","");
   StringReplace(day2_data,"\"","");
   Print(day2_data);

   string day2_data_array[];
   StringSplit(day2_data,',',day2_data_array);
//---
   return(INIT_SUCCEEDED);
  }

Ausgabe:

1763596800000,

91554.96000000,

93160.00000000,

86100.00000000,

86637.23000000,

39733.19073000,

1763683199999,

3548950335.09842180,

7841395,

18283.84047000,

1634256490.95743210,

0

An der Ausgabe können Sie erkennen, dass alle zusätzlichen Zeichen herausgenommen wurden. Danach haben wir die Methode StringSplit mit einem Komma als Trennzeichen verwendet, um die Daten in unabhängige Teile eines einzigen Arrays aufzuteilen. Dadurch war es einfach, jeden Wert einzeln zu bearbeiten.

 

Extrahieren von Zeit- und OHLC-Werten aus den Daten der dritten Kerze

Wir sortieren die Daten für die dritte Kerze auf die gleiche Weise wie für die ersten beiden. Wir werden ihn zunächst ausdrucken, das Format verstehen und alle unnötigen Zeichen entfernen. Nachdem wir die überflüssigen Zeichen entfernt haben, deklarieren wir ein String-Array, das die Daten für die dritte Kerze enthält. Die Daten werden dann mit der Funktion StringSplit und einem Komma als Trennzeichen in einzelne Elemente unterteilt. Wie bei den vorangegangenen Kerzen können wir auf diese Weise auf jede Variable unabhängig zugreifen, einschließlich Eröffnungszeit, Eröffnungs-, Höchst-, Tiefst- und Schlusskurs. Alle Kerzendaten werden auf diese Weise zuverlässig geordnet und für die Weiterverarbeitung vorbereitet.

Print(candle_data[2]);

Ausgabe:

,[

1763683200000,

"86637.22000000",

"87498.94000000",

"80600.00000000",

"85129.43000000",

"72256.12679000",

1763769599999,

"6061348756.34156410",

11826480,

"34071.85828000",

"2859133223.22405230",

"0"
Beispiel:
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   WebRequest(method, url, headers, time_out, data, result, result_headers);
   string server_result = CharArrayToString(result);
// Print(server_result);

   string candle_data[];
   int array_count = StringSplit(server_result,']', candle_data);

//DAY 1
   string day1_data = candle_data[0];
   StringReplace(day1_data,"[[","");
   StringReplace(day1_data,"\"","");

   string day1_data_array[];
   StringSplit(day1_data,',',day1_data_array);

//DAY 2
   string day2_data = candle_data[1];
   StringReplace(day2_data,",[","");
   StringReplace(day2_data,"\"","");

   string day2_data_array[];
   StringSplit(day2_data,',',day2_data_array);

//DAY 3
   string day3_data = candle_data[2];
   StringReplace(day3_data,",[","");
   StringReplace(day3_data,"\"","");

   string day3_data_array[];
   StringSplit(day3_data,',',day3_data_array);

//---
   return(INIT_SUCCEEDED);
  }

Durch das einheitliche Kerzenformat können wir Anführungszeichen und führende Zeichen aus den Zahlen leicht entfernen. Die bereinigten Werte können dann geteilt und in einem Array zur einfacheren numerischen Verarbeitung gespeichert werden.

Beispiel:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

   WebRequest(method, url, headers, time_out, data, result, result_headers);
   string server_result = CharArrayToString(result);
// Print(server_result);

   string candle_data[];
   int array_count = StringSplit(server_result,']', candle_data);

//DAY 1
   string day1_data = candle_data[0];
   StringReplace(day1_data,"[[","");
   StringReplace(day1_data,"\"","");

   string day1_data_array[];
   StringSplit(day1_data,',',day1_data_array);

//DAY 2
   string day2_data = candle_data[1];
   StringReplace(day2_data,",[","");
   StringReplace(day2_data,"\"","");

   string day2_data_array[];
   StringSplit(day2_data,',',day2_data_array);

//DAY 3

   string day3_data = candle_data[2];
   StringReplace(day3_data,",[","");
   StringReplace(day3_data,"\"","");

   string day3_data_array[];
   StringSplit(day3_data,',',day3_data_array);

//DAY 4

   string day4_data = candle_data[3];
   StringReplace(day4_data,",[","");
   StringReplace(day4_data,"\"","");

   string day4_data_array[];
   StringSplit(day4_data,',',day4_data_array);

//DAY 5

   string day5_data = candle_data[4];
   StringReplace(day5_data,",[","");
   StringReplace(day5_data,"\"","");

   string day5_data_array[];
   StringSplit(day5_data,',',day5_data_array);

//---
   return(INIT_SUCCEEDED);
  }

Um Sie nicht zu überfordern, machen wir jetzt eine Pause in diesem Artikel. Im nächsten Artikel werden wir vergleichbare Daten aus verschiedenen Tageskerzen zu einem einzigen Array kombinieren. So werden z. B. alle Eröffnungszeiten in einem einzigen Array zusammengefasst, und die Höchst-, Tiefst- und Schlusskurse werden entsprechend angepasst. Die Arbeit mit den Kerzendaten wird dadurch einfacher zu handhaben und besser strukturiert.


Schlussfolgerung

Dieser Artikel hat Ihnen gezeigt, wie Sie die WebRequest-Funktion von MQL5 verwenden, um Kerzendaten von einer externen Plattform-API zu erhalten und wie Sie diese Daten organisieren können. Wir haben uns angesehen, wie man die Daten in separate Arrays für jede Kerze aufteilt, irrelevante Zeichen entfernt und die Serverantwort analysiert, um das Muster zu erkennen.

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

Von der Grundstufe bis zur Mittelstufe: Struct (VI) Von der Grundstufe bis zur Mittelstufe: Struct (VI)
In diesem Artikel werden wir untersuchen, wie man die Implementierung einer gemeinsamen strukturellen Codebasis angehen kann. Ziel ist es, den Programmieraufwand zu verringern und das volle Potenzial der Programmiersprache selbst – in diesem Fall MQL5 – zu nutzen.
Von der Grundstufe bis zur Mittelstufe: Struktur (V) Von der Grundstufe bis zur Mittelstufe: Struktur (V)
In diesem Artikel werden wir untersuchen, wie man strukturellen Code überladen kann. Ich weiß, dass es anfangs schwierig sein kann, das zu verstehen, vor allem, wenn man es zum ersten Mal sieht. Es ist sehr wichtig, dass Sie diese Konzepte erfassen und gut verstehen, bevor Sie versuchen, sich in komplexere und umfangreichere Themen zu vertiefen.
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.
Einführung in MQL5 (Teil 28): Beherrschung der API- und WebRequest-Funktion in MQL5 (II) Einführung in MQL5 (Teil 28): Beherrschung der API- und WebRequest-Funktion in MQL5 (II)
In diesem Artikel erfahren Sie, wie Sie mit Hilfe von APIs und der Funktion WebRequest in MQL5 Preisdaten von externen Plattformen abrufen und extrahieren können. Sie lernen, wie URLs strukturiert sind, wie API-Antworten formatiert werden, wie man Serverdaten in lesbare Strings umwandelt und wie man bestimmte Werte aus JSON-Antworten identifiziert und extrahiert.