Marktsimulation (Teil 07): Sockets (I)
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:

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:

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:

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:

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:

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:
- Entwicklung eines Expert Advisors für den Handel von Grund auf (Teil 15): Zugang zu Daten im Internet (I)
- Entwicklung eines Expert Advisors für den Handel von Grund auf (Teil 16): Zugang zu Daten im Internet (II)
- Entwicklung eines Expert Advisors für den Handel von Grund auf (Teil 17): Zugang zu Daten im Internet (III)
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:

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
| 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
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
Biologisches Neuron zur Vorhersage von Finanzzeitreihen
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Marktsimulation (Teil 05): Erstellen der Klasse C_Orders (II)
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.