English Русский 中文 Español 日本語 Português
preview
Marktsimulation (Teil 07): Sockets (I)

Marktsimulation (Teil 07): Sockets (I)

MetaTrader 5Beispiele |
13 0
Daniel Jose
Daniel Jose

Einführung

Im vorangegangenen Artikel, Marktsimulation (Teil 06): Übertragen von Informationen von MetaTrader 5 nach Excel, habe ich erklärt, wie Sie mit einfachen Mitteln und reinem MQL5 Kursdaten von MetaTrader 5 nach Excel übertragen können. Das war natürlich nur ein sehr einfaches Beispiel, das so didaktisch wie möglich sein sollte. Vielleicht haben Sie jedoch bemerkt, dass die Kursaktualisierungen nicht in Echtzeit erfolgten. Das im vorigen Artikel vorgestellte Wissen soll jedoch noch etwas anderes zeigen, was wir tatsächlich tun müssen.

Da es aber mehrere Möglichkeiten gibt, das Gleiche zu erreichen, und für uns immer nur das Ergebnis zählt, wollte ich zeigen, dass es in der Tat eine einfache Möglichkeit gibt, Daten aus dem MetaTrader 5 in andere Programme, z. B. Excel, zu übertragen. Die Hauptidee ist jedoch nicht, Daten von MetaTrader 5 nach Excel zu übertragen, sondern umgekehrt, d.h. Daten von Excel oder einem anderen Programm nach MetaTrader 5 zu übertragen.

Es gibt mehrere Möglichkeiten, dies zu erreichen. Einige sind einfacher, andere aufwändiger. Einige können dies in Echtzeit tun, während andere eine leichte Verzögerung einführen. Aber was zählt, ist: Können wir den MetaTrader 5 oder eine andere Anwendung, die darin läuft, mit externen Daten steuern? Diese Art von Frage mag trivial erscheinen, aber sie eröffnet wichtige Möglichkeiten. Sie könnten zum Beispiel eine Studie oder eine Analyse mit einem externen Programm durchführen, das speziell für solche Aufgaben entwickelt wurde. Sie können Interessenpunkte in Form von Preisen oder Notierungen definieren und diese Daten an einer Stelle platzieren, an der eine Anwendung (ein Expert Advisor, ein Dienst, ein Skript oder sogar ein Indikator) sie nutzen kann. Dieser kann uns dann direkt auf dem Chart Signale liefern oder, im Falle eines Expert Advisors, bei der Entscheidungsfindung helfen.

An diesem Punkt werden nur Ihre Vorstellungskraft und Ihr Interesse die Möglichkeiten und den Umfang Ihrer Arbeit begrenzen. Aber bevor wir uns an die Entwicklung von etwas machen, das wir tatsächlich für das Replay/Simulator brauchen, möchte ich etwas anderes zeigen. Dazu müssen diese Konzepte, Ideen und Möglichkeiten vorgestellt werden, damit Sie wirklich verstehen können, was später entwickelt und umgesetzt wird, und damit Sie all dieses Wissen bestmöglich nutzen können.

Was ich in diesem Artikel zeigen werde, ist ein Schritt nach vorn zu demselben Thema, das ich zuvor behandelt habe. Denn wie ich bereits sagte, können wir mit der vorgestellten Methode keine Daten in Echtzeit senden. Das reicht zwar schon für unsere Bedürfnisse im Replay/Simulator aus, aber nicht für unsere Bedürfnisse, wenn wir Informationen in Echtzeit haben wollen.


Verstehen des Konzepts

Wie ich bereits im vorherigen Artikel erwähnt habe, garantiert die Verwendung von RTD oder DDE keine bidirektionale Kommunikation zwischen MetaTrader 5 und einem externen Programm. Aber das gleiche Konzept, das in RTD oder DDE verwendet wird, kann auf eine Weise angewendet werden, die uns das gibt, was wir wollen: bidirektionale Kommunikation. Um dies zu erreichen, müssen wir etwas anders vorgehen, als wir es bisher getan haben. Während dieser Entwicklungsphase habe ich alles in reinem MQL5 gehalten. Es gibt jedoch Fälle, in denen reines MQL5 nicht wirklich ausreicht – nicht wegen der Funktionen, sondern wegen der Funktionen, die externe Programme nicht ohne Hilfe ausführen können. Das Problem LÄUFT auf eine Sache hinaus: SOCKETS.

Sockets sind tief in der Informatik verankert. Wenn Sie nicht wissen, was ein Socket ist oder wofür sie verwendet wird, empfehle ich Ihnen, es nachzuschlagen, vor allem, wenn Sie mit bestimmten Arten von Lösungen arbeiten wollen. Die Verwendung von Sockets gibt uns ein enormes Maß an Freiheit. Ich werde hier nicht näher auf das Thema eingehen, denn es ist umfangreich und voller Möglichkeiten, die ein sorgfältiges Studium erfordern, wenn man wirklich mit Sockets arbeiten will. Aber ich werde eine kurze Erklärung geben, damit Sie, lieber Leser, sich nicht völlig verloren fühlen, damit Sie verstehen, was wir tun werden und was passiert.


TCP-Protokoll

Zunächst einmal müssen Sie wissen, dass es unzählige verschiedene Arten von Sockets gibt. Jedes dient einem anderen Zweck. Die gängigsten sind jedoch Stream- und DataGram-Sockets. Der Stream-Typ, der auch als Flow-Socket bezeichnet wird, wird in der Regel für zuverlässige bidirektionale Kommunikation verwendet. Das Wort „zuverlässig“ bezieht sich auf die Tatsache, dass es immer wieder getestet wird, um sicherzustellen, dass die Informationen ankommen. Stream Sockets verwenden das Transmission Control Protocol, allgemein bekannt als TCP.

Dieser Sockeltyp hat eine weitere Eigenschaft: Er ist so konzipiert, dass die Datenpakete immer in einer bestimmten Reihenfolge ankommen. Mit anderen Worten: Sie können Informationen wie eine sich entfaltende Liste übertragen, da die Pakete in der richtigen Reihenfolge ankommen. Damit ist klar, wo sie am häufigsten eingesetzt wird: z. B. bei der Fernsteuerung von Anwendungen, wo ein Datenverlust während der Übertragung inakzeptabel ist und wir die Garantie brauchen, dass die Informationen auch ankommen. Dies macht das Protokoll in der Praxis jedoch etwas langsamer. In der Regel ist die Struktur wie folgt:

Abbildung 01

Aber bei der Programmierung kommt es auf etwas anderes an. Es geht darum, wie dieses Protokoll ausgewählt und in den Code implementiert wird, den wir erstellen werden. Je nachdem, ob TCP unter Windows oder Linux verwendet wird, gibt es kleine strukturelle Unterschiede im Code. Obwohl solche Unterschiede bestehen, beeinträchtigen sie die Kommunikation selbst nicht. Das heißt, eine Windows-Anwendung kann mit einer Linux-Anwendung über TCP kommunizieren, und beide werden sich perfekt verstehen. Vorausgesetzt, die Kommunikationsregeln werden eingehalten. Dasselbe gilt für das nächste Protokoll, das wir im folgenden Abschnitt erörtern werden.


UDP-Protokoll

Nachdem wir den Stream-Typ behandelt haben, wollen wir nun den DataGram-Typ verstehen. Ein DataGram-Socket ist völlig anders als ein Stream/TCP-Socket. Der Grund dafür ist, dass der Datagramm-Socket für unidirektionale, unzuverlässige Kommunikation gedacht ist. Aber was bedeutet das? Wie kann Kommunikation unidirektional und unzuverlässig sein? Lassen Sie uns das aufschlüsseln.

Erstens verwendet dieser Socket das als UDP bekannte Protokoll. Bei diesem Protokoll handelt es sich nicht um eine echte Verbindung, sondern lediglich um eine Methode zur Datenübertragung. Um das zu verstehen, stellen Sie sich vor, Sie schreiben einen Brief und schicken ihn ab. Wenn Sie eine Nachricht abschicken, wissen Sie nicht, ob oder wann sie ihr Ziel erreichen wird.

Aber die Dinge werden noch komplizierter. Nachdem Sie den Brief abgeschickt haben, stellen Sie fest, dass Sie einige Details vergessen haben. Sie schreiben also einen weiteren Brief und schicken ihn ab. Dies kann mehrmals geschehen – jedes Schreiben wird separat verschickt.

Das Wichtigste: Wenn der Postdienst korrekt funktioniert und keiner der Briefe verloren geht, kann der Empfänger alle Briefe auf einmal erhalten, oder in der Reihenfolge, in der Sie sie abgeschickt haben, oder in einer völlig zufälligen Reihenfolge.

Überlegen Sie, was Sie als Empfänger tun müssten, um die Botschaft zu verstehen. Und wenn Sie als Absender eine Antwort erwarten würden, hätten Sie keine Garantie, dass der Empfänger die Briefe tatsächlich erhalten oder verstanden hat. Aus diesem Grund gilt das UDP-Protokoll als unidirektional und unzuverlässig. Aber auch wenn es sich so anhört, ist es doch sehr nützlich.

Es gibt Situationen, wie z. B. die Datenabfrage, in denen die Daten nicht geordnet sein müssen und auch nicht alle Daten benötigt werden. Wir können es uns leisten, einige zu verlieren, haben aber immer noch genug, um die Informationen zu verstehen.

Ein typisches Beispiel sind Video- oder Sprachanrufe, bei denen es auf Geschwindigkeit ankommt. Eine andere Anwendung wären ferngesteuerte Sonden oder Sensoren, bei denen es lediglich darum geht, einen bestimmten Zustand zu bestätigen. In solchen Fällen ist eine Empfangsbestätigung unnötig, solange genügend Daten für die Analyse eintreffen. Dieses Protokoll hat in der Regel die unten dargestellte Struktur:

Abbildung 02

Hoffentlich hat dies bereits Ihre Neugierde geweckt und Sie dazu veranlasst, sich eingehender mit dem Thema zu befassen. Sie ist in der Tat sehr umfangreich und interessant. Hier in der MQL5-Community finden Sie zahlreiche Hinweise auf das Thema, sowohl in Artikeln als auch in Forumsdiskussionen. Auf jeden Fall ist das Thema sehr umfangreich. Diese kurze Einführung soll Ihnen nur helfen zu verstehen, was wir als Nächstes tun werden.


Programmierung eines bescheidenen Systems

Hier müssen wir eine Klammer öffnen. Um zu demonstrieren, was getan wird, müssen wir einen sehr einfachen Code verwenden. Da es mit MQL5 nicht möglich ist, einen Server direkt in der Sprache zu erstellen, werden wir MQL5 verwenden, um die Client-Seite zu erstellen. Ja, wir werden ein Client-Server-Modell aufbauen. Die Serverseite wird durch externe Programmierung erstellt. In diesem Fall können Sie sie mit jeder Sprache oder Plattform erstellen, die Netzwerkserver unterstützt. Es gibt jedoch wichtige Details, auf die Sie achten müssen, wie z. B. den Port und die Art des Protokolls. Um die Dinge so weit wie möglich zu vereinfachen, werde ich Code verwenden, den Sie direkt im Quelltext studieren können. Mit anderen Worten: Wir werden öffentlich verfügbaren Code aus dem Internet verwenden. Den Servercode finden Sie auf der Microsoft-Website, die Sie über diesen Link erreichen: Server WinSock.

Am Ende des Artikels werde ich diesen Verweis wieder hinterlassen, damit Sie den Code Schritt für Schritt studieren können, zusammen mit vielen anderen Details im Zusammenhang mit Sockets. Dies gilt nicht nur für den Server, sondern auch für den Client, was ebenfalls auf der gleichen Seite erläutert wird.

WICHTIGER HINWEIS: Der Server, auf den ich mich beziehe, ist ein sehr einfaches Modell. Er empfängt eine Verbindung, fängt auf, was an ihn gesendet wird, und schließt die Verbindung sofort wieder, da er keine weitere empfangen kann. Sie gibt genau die Daten zurück, die der Kunde gesendet hat. Mit anderen Worten, es handelt sich um einen Echo-Server, der nur zu Demonstrationszwecken verwendet wird.

Wir werden jedoch für den Kunden etwas anders vorgehen. Wir werden den Client direkt in MQL5 erstellen und dabei den auf der Website verfügbaren C/C++-Client-Code überspringen. So können Sie verstehen, wie Kommunikation tatsächlich funktioniert. Denken Sie daran, dass Sie MetaTrader 5 auch in einen Server verwandeln können, aber dazu müssten Sie eine DLL verwenden. Ich möchte diese Art von Ressourcen im Moment nicht vorstellen. Zumindest noch nicht.

Fangen wir also an. Sie können den von mir angegebenen Code verwenden oder Ihren eigenen in einer beliebigen Sprache oder Plattform erstellen. Die Idee ist einfach, ein bescheidenes System zu bauen, das so einfach wie möglich ist, aber als Auslöser dafür dient, dass Sie verstehen, wie die Dinge funktionieren. Sobald der Server kompiliert ist und läuft, können wir mit dem MQL5-Teil fortfahren. Dazu öffnen Sie MetaEditor und erstellen den Client in reinem MQL5.


Ausführen der MetaTrader-Seite

Bevor wir eine Verbindung mit unserem lokalen Server herstellen, müssen wir wissen, wie man eine Verbindung herstellt. MetaTrader 5 verhindert standardmäßig, dass Sie sich mit einem anderen Server als dem Handelsserver verbinden. Dies ist eine Sicherheitsmaßnahme, die Sie akzeptieren und verstehen müssen. Es ist nicht angemessen, dass eine Plattform wie MetaTrader frei mit beliebigen Adressen verbunden werden kann. Daher muss ein kleiner Schritt getan werden, bevor MetaTrader eine solche Verbindung zulässt.

Um dies auf sehr einfache Weise zu erklären, werden wir etwas verwenden, das direkt in der MQL5-Dokumentation zu finden ist. Der folgende Code ist nicht von mir, sondern stammt aus der offiziellen Dokumentation und ist unter SocketCreate zu finden. Der Quellcode wird im Folgenden genau so dargestellt, wie er in der Dokumentation erscheint:

001. //+------------------------------------------------------------------+
002. //|                                                SocketExample.mq5 |
003. //|                        Copyright 2018, MetaQuotes Software Corp. |
004. //|                                             https://www.mql5.com |
005. //+------------------------------------------------------------------+
006. #property copyright   "Copyright 2018, MetaQuotes Software Corp."
007. #property link        "https://www.mql5.com"
008. #property version     "1.00"
009. #property description "Add Address to the list of allowed ones in the terminal settings to let the example work"
010. #property script_show_inputs
011.  
012. input string Address="www.mql5.com";
013. input int    Port   =80;
014. bool         ExtTLS =false;
015. //+------------------------------------------------------------------+
016. //| Send command to the server                                       |
017. //+------------------------------------------------------------------+
018. bool HTTPSend(int socket,string request)
019.   {
020.    char req[];
021.    int  len=StringToCharArray(request,req)-1;
022.    if(len<0)
023.       return(false);
024. //--- if secure TLS connection is used via the port 443
025.    if(ExtTLS)
026.       return(SocketTlsSend(socket,req,len)==len);
027. //--- if standard TCP connection is used
028.    return(SocketSend(socket,req,len)==len);
029.   }
030. //+------------------------------------------------------------------+
031. //| Read server response                                             |
032. //+------------------------------------------------------------------+
033. bool HTTPRecv(int socket,uint timeout)
034.   {
035.    char   rsp[];
036.    string result;
037.    uint   timeout_check=GetTickCount()+timeout;
038. //--- read data from sockets till they are still present but not longer than timeout
039.    do
040.      {
041.       uint len=SocketIsReadable(socket);
042.       if(len)
043.         {
044.          int rsp_len;
045.          //--- various reading commands depending on whether the connection is secure or not
046.          if(ExtTLS)
047.             rsp_len=SocketTlsRead(socket,rsp,len);
048.          else
049.             rsp_len=SocketRead(socket,rsp,len,timeout);
050.          //--- analyze the response
051.          if(rsp_len>0)
052.            {
053.             result+=CharArrayToString(rsp,0,rsp_len);
054.             //--- print only the response header
055.             int header_end=StringFind(result,"\r\n\r\n");
056.             if(header_end>0)
057.               {
058.                Print("HTTP answer header received:");
059.                Print(StringSubstr(result,0,header_end));
060.                return(true);
061.               }
062.            }
063.         }
064.      }
065.    while(GetTickCount()<timeout_check && !IsStopped());
066.    return(false);
067.   }
068. //+------------------------------------------------------------------+
069. //| Script program start function                                    |
070. //+------------------------------------------------------------------+
071. void OnStart()
072.   {
073.    int socket=SocketCreate();
074. //--- check the handle
075.    if(socket!=INVALID_HANDLE)
076.      {
077.       //--- connect if all is well
078.       if(SocketConnect(socket,Address,Port,1000))
079.         {
080.          Print("Established connection to ",Address,":",Port);
081.  
082.          string   subject,issuer,serial,thumbprint;
083.          datetime expiration;
084.          //--- if connection is secured by the certificate, display its data
085.          if(SocketTlsCertificate(socket,subject,issuer,serial,thumbprint,expiration))
086.            {
087.             Print("TLS certificate:");
088.             Print("   Owner:  ",subject);
089.             Print("   Issuer:  ",issuer);
090.             Print("   Number:     ",serial);
091.             Print("   Print: ",thumbprint);
092.             Print("   Expiration: ",expiration);
093.             ExtTLS=true;
094.            }
095.          //--- send GET request to the server
096.          if(HTTPSend(socket,"GET / HTTP/1.1\r\nHost: www.mql5.com\r\nUser-Agent: MT5\r\n\r\n"))
097.            {
098.             Print("GET request sent");
099.             //--- read the response
100.             if(!HTTPRecv(socket,1000))
101.                Print("Failed to get a response, error ",GetLastError());
102.            }
103.          else
104.             Print("Failed to send GET request, error ",GetLastError());
105.         }
106.       else
107.         {
108.          Print("Connection to ",Address,":",Port," failed, error ",GetLastError());
109.         }
110.       //--- close a socket after using
111.       SocketClose(socket);
112.      }
113.    else
114.       Print("Failed to create a socket, error ",GetLastError());
115.   }
116. //+------------------------------------------------------------------+

Quellcode aus der MQL5-Dokumentation

Dieser Code ist perfekt geeignet, um zu erklären, wie man mit Verbindungen im MetaTrader 5 arbeitet und diese anpasst. Denn es ist nicht nur sehr einfach, sondern bietet auch die Möglichkeit des Fernzugriffs. Mit anderen Worten, wir werden tatsächlich auf eine Webseite zugreifen. Ich glaube, dass viele Leser mit etwas Erfahrung in der Netzwerkprogrammierung diesen Code ohne Schwierigkeiten verstehen werden. Aber für diejenigen, die nichts über das Thema wissen, werde ich eine kurze Erklärung geben, denn wir werden später einige der hier gezeigten Konzepte verstehen müssen.

Dieser Code ist ein Skript und muss als solches kompiliert werden. Es ist nicht möglich, Sockets in Indikatoren zu verwenden. Lesen Sie die Dokumentation für weitere Einzelheiten. Schauen wir uns nun an, wie es funktioniert. In Zeile 12 geben wir den Namen der Website an, auf die zugegriffen werden soll. In Zeile 13 geben wir den zu verwendenden Anschluss an. Insbesondere ein Port, der auf HTTP-Anfragen antwortet. Mit anderen Worten: ein Webserver. Lesen Sie in der Dokumentation nach, was Sie von jeder Art von Anschluss erwarten können.

Nun, wenn der Code beginnt (in Zeile 71), wird als erstes ein Socket erstellt (Zeile 73). Bis zu diesem Punkt ist alles ganz einfach. Wir müssen jedoch überprüfen, ob der erstellte Socket gültig ist, was in Zeile 75 geschieht. In Zeile 78 wird versucht, eine Verbindung zu dem in den Zeilen 12 und 13 angegebenen Server und Port herzustellen. Wenn dies fehlschlägt, sehen Sie etwas ähnliches wie das folgende Bild:

Abbildung 03

Dies ist wahrscheinlich darauf zurückzuführen, dass MetaTrader 5 die Verbindung blockiert. Um die Verbindung zu aktivieren, drücken Sie die Tastenkombination STRG + O und fügen Sie der Regel eine Ausnahme hinzu, wie unten gezeigt:

Abbildung 04

Sobald Sie die oben gezeigte Änderung vorgenommen haben, können Sie das Skript erneut ausführen, und das Ergebnis wird ähnlich wie in der folgenden Abbildung aussehen:

Abbildung 05

Aber wie ist das passiert? Wie konnten wir die Informationen vom Webserver abrufen? Wäre dafür nicht ein WebRequest-Aufruf erforderlich? Eigentlich nicht unbedingt. Der WebRequest-Aufruf tut fast genau das, was wir gerade getan haben, aber auf einer etwas höheren Ebene. Denn WebRequest schafft eine Abstraktion um den darunter liegenden Socket. Daher ist das Ergebnis bei beiden Ansätzen das gleiche. Wir haben die WebRequest-Funktion in früheren Artikeln untersucht. Weitere Einzelheiten finden Sie unter:

Was in diesen drei Artikeln beschrieben wurde, kann auch direkt mit Sockets durchgeführt werden. Allerdings müssen Sie etwas mehr Code schreiben, um das gleiche Ergebnis zu erzielen. Aber kehren wir zu unserem System in diesem Artikel zurück. Nachdem Sie den im vorigen Abschnitt erwähnten Servercode kompiliert haben, müssen Sie ihn laufen lassen, bevor Sie das Skript ausführen, das ich gleich zeigen werde. Denken Sie daran, dass Sie Ihren eigenen Server in jeder beliebigen Sprache erstellen können. Die einzige Voraussetzung ist jetzt, dass die vom Server empfangenen Daten an den Client zurückgesendet werden, damit wir das Verhalten erhalten, das ich erklären werde.

Sehen wir uns also den MQL5-Code für unseren Kunden an. Unten können Sie ihn in voller Länge sehen.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. #property version   "1.00"
04. #property script_show_inputs 
05. //+------------------------------------------------------------------+ 
06. input string user00 = "127.0.0.1";          //Address
07. input int    user01 = 27015;                //Port
08. //+------------------------------------------------------------------+
09. bool ConnectionWrite(int socket, string szMsg, bool TLS = false)
10. {
11.     char buff[];
12.     int  len = StringToCharArray(szMsg, buff) - 1;
13. 
14.     if (len < 0) return false;
15.     Print("To Server:", szMsg);
16.     return (TLS ? SocketTlsSend(socket, buff, len) : SocketSend(socket, buff, len)) == len;
17. }
18. //+------------------------------------------------------------------+
19. string ConnectionRead(int socket, uint timeout)
20. {
21.     uint len;
22.     int  ret;
23.     char resp[];
24.     string info;
25.     uint timeout_check = GetTickCount() + timeout;
26.     
27.     info = "";
28.     do
29.     {
30.             len = SocketIsReadable(socket);
31.             ret = SocketRead(socket, resp, len, timeout);
32.             if (ret > 0)
33.                     info += CharArrayToString(resp, 0, ret);
34.     }while ((GetTickCount() < timeout_check) && (!_StopFlag));
35.     
36.     return info;
37. }
38. //+------------------------------------------------------------------+
39. void OnStart()
40. {
41.     int socket = SocketCreate();
42.     
43.     if (socket == INVALID_HANDLE)
44.     {
45.             Print("Unable to create socket. Error: ", GetLastError());
46.             return;
47.     }
48.     if (!SocketConnect(socket, user00, user01, 1000))
49.     {
50.             Print("Connection with the address [", user00,"] in port: ",user01, " failed. Error code: ", GetLastError());
51.             SocketClose(socket);
52.             return;
53.     }
54.     
55.     Print("Trying to send ", ConnectionWrite(socket, "Testing Server Echo...") ? "Ok..." : "Failed...");
56.     
57.     Print("From Server:", ConnectionRead(socket, 1000));
58. 
59.     SocketClose(socket);
60. }
61. //+------------------------------------------------------------------+

Demonstrationscode

Bevor wir uns ansehen, wie dieser Code im MetaTrader 5 läuft, sollten wir einige Details verstehen. Der erste wichtige Punkt ist Zeile sechs. In dieser Zeile steht, wo sich unser Server befindet. In diesem Beispiel geben wir an, dass es sich auf demselben Rechner wie MetaTrader 5 befindet. In Zeile sieben wird der Serverport angegeben. Dies ist sehr wichtig: Dieser Port muss mit dem im Servercode definierten Port übereinstimmen. Aus diesem Grund habe ich auf öffentlich zugänglichen Code verwiesen, der auf der Website klar erläutert wird. Im Zweifelsfall studieren Sie die Dokumentation auf dieser Website. Ich werde sie am Ende dieses Artikels noch einmal als Referenz aufnehmen.

Im Grunde sind alle Funktionen in diesem MQL5-Skript selbsterklärend. Und wenn Sie Fragen haben, lesen Sie einfach die Dokumentation, um zu verstehen, was im Einzelnen geschieht. Es gibt jedoch einen Teil, bei dem die Dinge nicht so klar sind und der eine Erklärung verdient.

Beachten Sie, dass wir in Zeile 28 eine Schleife einleiten. Sein Zweck ist es, zu lesen, was der Server an den Socket sendet. Aber warum eine Schleife verwenden? Würde es nicht ausreichen, einen Socket einmal zu lesen? Das mag merkwürdig erscheinen, aber es gibt einen Grund dafür. Wenn etwas an einen Socket gesendet wird, wissen wir nicht, wie es gesendet wird. Wir wissen nur, dass sie verschickt werden wird. Die Informationen können in einem einzigen Paket oder in mehreren kleinen Paketen ankommen, auch wenn die Nachricht relativ kurz ist.

Das ist der Grund, warum viele, die neu in die Socket-Programmierung einsteigen, Schwierigkeiten haben. Sie gehen davon aus, dass die Informationen in einem einzigen Block eintreffen werden. Sie kann aber auch in viele Blöcke oder Pakete aufgeteilt sein. Können wir das im Voraus wissen? In Wirklichkeit gibt es keine einfache Möglichkeit, das zu wissen. Alles, was wir erwarten können, ist, dass die gesendeten Daten empfangen werden, wenn wir TCP verwenden, wie bereits erklärt. In der Regel werden die Informationen jedoch in Form von Paketen veröffentlicht und empfangen.

Zum besseren Verständnis sehen Sie sich Zeile 55 an. Hier rufen wir Zeile neun auf, die die Informationen zurückgibt, die in den Socket gestellt werden sollen. In Zeile 15 definieren wir die Nachricht. In Zeile 16 senden wir sie. Wie der Server diese Nachricht empfängt und in wie viele Pakete sie aufgeteilt wird, liegt nicht mehr in unserer Hand, sondern wird vom System selbst geregelt.

Dann, in Zeile 57, lesen wir, was der Server veröffentlicht hat. Achten Sie darauf, dass wir nicht lesen, was wir gesendet haben, sondern was der Server veröffentlicht hat. Da es sich bei dem von uns verwendeten Server um einen Echo-Server handelt, wird dieselbe Nachricht, die wir gesendet haben, an uns zurückgesendet. Dies ist im Wesentlichen so, als würde man einen PING auf dem Server durchführen.

Aber so wie wir nicht wissen, wie die Nachricht übertragen wird, wissen wir auch nicht, wie der Server sie in Bezug auf die Anzahl der Pakete zurücksenden wird. Wenn Sie also die Schleife in Zeile 28 entfernen und nur den Aufruf in Zeile 31 ausführen und dann versuchen, die Serverantwort in Zeile 33 in eine Zeichenkette umzuwandeln, werden Sie wahrscheinlich feststellen, dass die Nachricht fragmentiert erscheint, als ob ein Teil fehlen würde. Zu anderen Zeiten wird sie jedoch vollständig ankommen, weil die Nachricht kurz ist. Und genau dieses Verhalten ist es, das viele Menschen nicht verstehen.

Ich weiß, das mag verwirrend und sogar ineffizient erscheinen. Es mag so aussehen, als ob es keinen Zweck hat. Aber ich möchte etwas betonen: Wenn Sie verstehen, wie diese beiden Codes funktionieren – sowohl der Server als auch der in MetaTrader 5 ausgeführte – werden Sie feststellen, dass wir eine Menge erreichen können.

Bevor Sie dieses Skript ausführen, müssen Sie MetaTrader 5 jedoch mitteilen, dass die verwendete Adresse zulässig sein soll. Daher muss derselbe Wert, der in Zeile sechs angegeben ist, in der Liste der zulässigen Adressen im MetaTrader 5 erscheinen. Sie sollten etwas wie das folgende Bild sehen:

Abbildung 06

Mit dieser Änderung können wir beide Programme ausführen. Um Ihnen zu zeigen, wie Sie dies tun können, insbesondere wenn Sie keine Erfahrung mit der Ausführung mehrerer Prozesse haben, habe ich das folgende Video eingefügt, in dem gezeigt wird, wie Sie beide Programme lokal testen. Ich möchte betonen, dass der Zweck des Videos nicht darin besteht, für ein bestimmtes Tool zu werben, sondern einfach denjenigen, die mit dem Prozess nicht vertraut sind, zu zeigen, wie man Programme in mehreren Arbeitssträngen ausführt und so die Entwicklung ohne größere Schwierigkeiten ermöglicht.




Abschließende Überlegungen

In diesem Artikel habe ich eine kurze Einführung in eines der komplexesten Konzepte gegeben, die Sie in MetaTrader 5 verwenden können: Sockets. Der Zweck dieses Artikels war es, die nackten Grundlagen der Verwendung von Sockets im MetaTrader 5 zu erklären, damit Sie zumindest einige notwendige und involvierte Konzepte verstehen können. Obwohl der Inhalt sehr grundlegend ist, ist er für jeden, der sich mit Sockets und ihren Anwendungen beschäftigen möchte, unerlässlich.

Da wir hier aber nur ein Echo an den Server geschickt haben, ist vielleicht nicht ganz klar, wie viel wir wirklich tun können. Um das zu erreichen, werden wir im nächsten Artikel etwas Aufwändigeres bauen. Dieses Socketkonzept wird die Qualität Ihres Replay/Simulator-Systems erheblich verbessern, da wir noch zusätzliche Funktionen, wie z.B. das Bestellsystem, implementieren müssen. Und ich ziehe ernsthaft in Erwägung, es auf eine fortschrittlichere Weise zu bauen. Aber damit Sie, lieber Leser, wirklich verstehen, was programmiert wird, müssen Sie diese kleinen Konzepte verstehen, die ich hier vorstelle.

Wenn es eine Sache gibt, die Sie dazu bringt, sich intensiv mit der Programmierung zu beschäftigen, dann ist es diese: Sockets. Wenn es um Sockets geht, kann man nie genug wissen. Und wenn Sie glauben, alles über sie herausgefunden zu haben, werden Sie unweigerlich feststellen, dass es noch mehr zu lernen gibt. Verpassen Sie also nicht den nächsten Artikel: Ich werde etwas sehr Interessantes und einfach zu implementierendes zu diesem Thema zeigen.


Link

Microsoft WinSock documentation

Liste der Port-Nummern

Datei Beschreibung
Experts\Expert Advisor.mq5
Demonstriert die Interaktion zwischen Chart Trade und dem Expert Advisor (für die Interaktion ist ein Mauszeiger erforderlich)
Indicators\Chart Trade.mq5 Erstellt das Fenster für die Konfiguration des zu versendenden Auftrags (Mouse Study ist für die Interaktion erforderlich)
Indicators\Market Replay.mq5 Erstellt Steuerelemente für die Interaktion mit dem Wiedergabe-/Simulationsdienst (Mausstudie ist für die Interaktion erforderlich)
Indicators\Mouse Study.mq5 Ermöglicht die Interaktion zwischen den grafischen Steuerelementen und dem Nutzer (erforderlich für den Betrieb des Replay-Simulators und des Live-Markthandels)
Servicios\Market Replay.mq5 Erstellt und pflegt den Marktwiedergabe- und Simulationsdienst (Hauptdatei des gesamten Systems)
VS C++ Server.cpp Erstellt und pflegt einen Socket-Server in C++ (Mini-Chat-Version)
Python code Server.py Erstellt und pflegt einen Python-Socket für die Kommunikation zwischen MetaTrader 5 und Excel
ScriptsCheckSocket.mq5 Überprüft die Verbindung zu einem externen Socket
Indicators\Mini Chat.mq5 Implementiert einen Mini-Chat als Indikator (erfordert einen Server)
Experts\Mini Chat.mq5 Implementiert einen Mini-Chat als Expert Advisor (erfordert einen Server)

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

Beigefügte Dateien |
Anexo.zip (550.91 KB)
Anexo.zip (560.03 KB)
Die Übertragung der Trading-Signale in einem universalen Expert Advisor. Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
In diesem Artikel wurden die verschiedenen Möglichkeiten beschrieben, um die Trading-Signale von einem Signalmodul des universalen EAs zum Steuermodul der Positionen und Orders zu übertragen. Es wurden die seriellen und parallelen Interfaces betrachtet.
Biologisches Neuron zur Vorhersage von Finanzzeitreihen Biologisches Neuron zur Vorhersage von Finanzzeitreihen
Wir werden ein biologisch korrektes System von Neuronen für die Vorhersage von Zeitreihen aufbauen. Die Einführung einer plasmaähnlichen Umgebung in die Architektur des neuronalen Netzes schafft eine Art „kollektive Intelligenz“, bei der jedes Neuron den Betrieb des Systems nicht nur durch direkte Verbindungen, sondern auch durch weitreichende elektromagnetische Wechselwirkungen beeinflusst. Mal sehen, wie sich das neuronale Gehirnmodellierungssystem auf dem Markt schlagen wird.
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.
Marktsimulation (Teil 05): Erstellen der Klasse C_Orders (II) Marktsimulation (Teil 05): Erstellen der Klasse C_Orders (II)
In diesem Artikel erkläre ich, wie Chart Trade zusammen mit dem Expert Advisor eine Anfrage zur Schließung aller offenen Positionen des Nutzers bearbeitet. Das mag einfach klingen, aber es gibt einige Komplikationen, mit denen Sie umgehen müssen.