English Русский 中文 Español 日本語 Português 한국어 Français Italiano Türkçe
preview
Einen handelnden Expert Advisor von Grund auf neu entwickeln (Teil 16): Zugang zu Daten im Internet (II)

Einen handelnden Expert Advisor von Grund auf neu entwickeln (Teil 16): Zugang zu Daten im Internet (II)

MetaTrader 5Integration | 29 Juli 2022, 09:45
269 0
Daniel Jose
Daniel Jose

Einführung

Im vorherigen Artikel "Entwicklung eines Expert Advisors von Grund auf (Teil 15): Zugriff auf Daten im Web (I)", haben wir die gesamte Logik und die Ideen hinter den Methoden zur Nutzung der MetaTrader 5 Plattform für den Zugriff auf markierte Daten von spezialisierten Websites vorgestellt.

In diesem Artikel haben wir uns damit beschäftigt, wie man auf diese Websites zugreift und wie man dort Informationen findet und abruft, um sie in der Plattform zu verwenden. Aber das ist noch nicht alles, denn die bloße Erfassung von Daten ist nicht sehr sinnvoll. Der interessanteste Teil ist zu lernen, wie man diese Daten von der Plattform übernimmt und in einem Expert Advisor verwendet. Die Methode, dies zu tun, ist nicht so offensichtlich und daher schwer zu implementieren, ohne alle im MetaTrader 5 verfügbaren Funktionen zu kennen und zu verstehen.


Planung und Durchführung

Wenn Sie den vorhergehenden Artikel nicht gelesen und verstanden haben, empfehle ich Ihnen, dies zu tun und zu versuchen, alle dort vorgestellten Konzepte zu verstehen, denn hier werden wir das Thema fortsetzen - wir werden eine große Anzahl von Dingen untersuchen, eine Reihe von Problemen lösen und am Ende zu einer schönen Lösung kommen, da wir MetaTrader 5 auf eine Art und Weise verwenden werden, die noch nicht erforscht wurde. Ich sage dies, weil es schwierig war, Links zu finden, um einige der Funktionen der Plattform zu nutzen, aber hier werde ich versuchen zu erklären, wie man eine dieser Ressourcen nutzt.

Also, machen wir uns bereit und gehen an die Arbeit.


1. Zugang zu Internetdaten über einen Expert Advisor

Dies ist der interessanteste Teil, der in diesem System implementiert werden kann. Obwohl es eine einfache Sache ist, ist sie bei weitem die gefährlichste, wenn sie schlecht geplant ist. Gefährlich, weil der EA dann auf eine Antwort vom Server warten muss, und sei es auch nur für einen Moment.

Diese Logik ist in der nachstehenden Abbildung dargestellt:

Schauen wir uns an, wie der EA direkt mit dem Webserver interagiert, der die Informationen enthält, die wir erfassen wollen. Nachstehend sehen Sie ein vollständiges Codebeispiel, das genau so funktioniert.

#property copyright "Daniel Jose"
#property version "1.00"
//+------------------------------------------------------------------+
int OnInit()
{
        EventSetTimer(1);
        
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        Print(GetDataURL("https://tradingeconomics.com/stocks", 100, "<!doctype html>", 2, "INDU:IND", 172783, 173474, 0x0D));
}
//+------------------------------------------------------------------+
string GetDataURL(const string url, const int timeout, const string szTest, int iTest, const string szFind, int iPos, int iInfo, char cLimit)
{
        string  headers, szInfo = "";
        char    post[], charResultPage[];
        int     counter;
   
        if (WebRequest("GET", url, NULL, NULL, timeout, post, 0, charResultPage, headers) == -1return "Bad";
        for (int c0 = 0, c1 = StringLen(szTest); c0 < c1; c0++) if (szTest[c0] != charResultPage[iTest + c0]) return "Failed";
        for (int c0 = 0, c1 = StringLen(szFind); c0 < c1; c0++) if (szFind[c0] != charResultPage[iPos + c0]) return "Error";
        for (counter = 0; charResultPage[counter + iInfo] == 0x20; counter++);
        for (;charResultPage[counter + iInfo] != cLimit; counter++) szInfo += CharToString(charResultPage[counter + iInfo]);
        
        return szInfo;
}
//+------------------------------------------------------------------+

Wenn Sie genau hinsehen, können wir sehen, dass der Code genau der gleiche ist, der im vorherigen Artikel erstellt wurde, aber jetzt ist dieser Code Teil des EA und wurde für diesen angepasst, d.h. wenn etwas dort bereits funktioniert hat, wird es auch hier funktionieren. Der Unterschied besteht darin, dass der EA eine neue Bedingung enthält, was bedeutet, dass der Code jede Sekunde ausgeführt wird, d. h. der EA wird jede Sekunde eine Anfrage an den gewünschten Webserver stellen und auf eine Antwort warten. Dann stellt es die erfassten Daten bereit und kehrt zu anderen internen Funktionen zurück. Diese Schleife wird während der gesamten Lebensdauer des EA wiederholt. Das Ergebnis der Ausführung ist unten zu sehen.


Obwohl dies genau so gemacht wird, empfehle ich diese Praxis nicht, da der EA auch nur für ein paar Augenblicke auf die Antwort des Servers warten muss - dies kann das Handelssystem der Plattform und den EA selbst gefährden. Wenn Sie jedoch daran interessiert sind, die Methode zu erlernen, können Sie mit diesem System eine Menge lernen.

Aber wenn Sie einen lokalen Server haben, der die Informationen zwischen dem Internet und der Plattform weiterleitet, ist diese Methode vielleicht ausreichend. Wenn das System in diesem Fall eine Anfrage stellt, geschieht Folgendes: Der lokale Server hat noch keine Informationen und wird schnell antworten, was Ihnen die nächsten Schritte erspart.

Betrachten wir nun eine andere Möglichkeit, diese Art von Aufgabe auszuführen, die ein wenig sicherer ist. Da wir das MetaTrader 5-Threading-System verwenden werden, um zumindest eine gewisse Sicherheit zu erreichen und zu verhindern, dass der EA den Bedingungen des Remote-Webservers unterliegt, können wir einige Augenblicke warten, bis der Remote-Server antwortet. Wir werden zusätzliche Voraussetzungen dafür schaffen, dass die EA weiß, was passiert, indem wir Informationen aus dem Web sammeln können.


2. Schaffung eines Kommunikationskanals

Eine bessere und einfachere Möglichkeit, Daten online zu sammeln und in einem EA zu verwenden, ist ein Kanal. Das funktioniert zwar, ist aber in manchen Fällen für uns nicht sehr geeignet, da die Nutzung solcher Kanäle eingeschränkt ist. Aber zumindest wird der EA in der Lage sein, auf im Web gesammelte Informationen zuzugreifen, ohne auf eine Antwort von einem entfernten Server warten zu müssen.

Es wurde bereits erwähnt, dass der einfachste Weg zur Lösung des Problems das Daten-Routing ist: die Einrichtung eines lokalen Servers, der die Daten herunterlädt und sie der MetaTrader 5-Plattform zur Verfügung stellt. Dies erfordert jedoch ein gewisses Maß an Wissen und Rechenleistung und verkompliziert fast alle Fälle. Wir können jedoch die Funktionen von MetaTrader 5 nutzen, um einen sehr ähnlichen Kanal zu erstellen, was viel einfacher wäre als das Routing über einen lokalen Server.

Die folgende Abbildung zeigt, wie wir einen solchen Kanal fördern werden.

Sie wird mit Hilfe eines Objekts erstellt. Beachten Sie, dass der EA innerhalb des Objekts nach den Informationen sucht, die das Skript dort platziert hat. Um zu verstehen, wie dies tatsächlich funktioniert, sehen wir uns drei Codes an, die im Folgenden vollständig aufgeführt sind. Einer wird ein EA sein, der andere ein Header, der das Objekt enthält, und der dritte ein Skript.

#property copyright "Daniel Jose"
#property description "Testing Inner Channel"
#property version "1.00"
//+------------------------------------------------------------------+
#include <Inner Channel.mqh>
//+------------------------------------------------------------------+
int OnInit()
{
        
        EventSetTimer(1);
        
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        Print(GetInfoInnerChannel());
}
//+------------------------------------------------------------------+

Der folgende Code ist die Kopfzeile, die wir verwenden müssen. Bitte beachten Sie, dass das Objekt hier zur gemeinsamen Nutzung durch den EA und das Skript deklariert ist.

//+------------------------------------------------------------------+
//|                                          Canal Intra Process.mqh |
//|                                                      Daniel Jose |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#define def_NameObjectChannel   "Inner Channel Info WEB"
//+------------------------------------------------------------------+
void CreateInnerChannel(void)
{
        long id;
        
        ObjectCreate(id = ChartID(), def_NameObjectChannel, OBJ_LABEL, 0, 0, 0);
        ObjectSetInteger(id, def_NameObjectChannel, OBJPROP_COLOR, clrNONE);
}
//+------------------------------------------------------------------+
void RemoveInnerChannel(void)
{
        ObjectDelete(ChartID(), def_NameObjectChannel);
}
//+------------------------------------------------------------------+
inline void SetInfoInnerChannel(string szArg)
{
        ObjectSetString(ChartID(), def_NameObjectChannel, OBJPROP_TEXT, szArg);
}
//+------------------------------------------------------------------+
inline string GetInfoInnerChannel(void)
{
        return ObjectGetString(ChartID(), def_NameObjectChannel, OBJPROP_TEXT);
}
//+------------------------------------------------------------------+

Und schließlich gibt es noch ein Skript. Es ersetzt die Erstellung eines lokalen Servers und übernimmt die Aufgaben des Servers.

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
#include <Inner Channel.mqh>
//+------------------------------------------------------------------+
void OnStart()
{
        CreateInnerChannel();
        while (!IsStopped())
        {
                SetInfoInnerChannel(GetDataURL("https://tradingeconomics.com/stocks", 100, "<!doctype html>", 2, "INDU:IND", 172783, 173474, 0x0D));
                Sleep(200);
        }
        RemoveInnerChannel();
}
//+------------------------------------------------------------------+
string GetDataURL(const string url, const int timeout, const string szTest, int iTest, const string szFind, int iPos, int iInfo, char cLimit)
{
        string  headers, szInfo = "";
        char    post[], charResultPage[];
        int     counter;
   
        if (WebRequest("GET", url, NULL, NULL, timeout, post, 0, charResultPage, headers) == -1) return "Bad";
        for (int c0 = 0, c1 = StringLen(szTest); (!_StopFlag) && (c0 < c1); c0++) if (szTest[c0] != charResultPage[iTest + c0]) return "Failed";
        for (int c0 = 0, c1 = StringLen(szFind); (!_StopFlag) && (c0 < c1); c0++) if (szFind[c0] != charResultPage[iPos + c0]) return "Error";
        for (counter = 0; (!_StopFlag) && (charResultPage[counter + iInfo] == 0x20); counter++);
        for (;(!_StopFlag) && (charResultPage[counter + iInfo] != cLimit); counter++) szInfo += CharToString(charResultPage[counter + iInfo]);
        
        return (_StopFlag ? "" : szInfo);
}
//+------------------------------------------------------------------+

Hier haben wir ein Objekt, das der EA sehen kann und das vom Skript erstellt wird. Die Idee ist, dass der EA und das Skript im gleichen Chart koexistieren können, dann wird dieses Objekt der Kommunikationskanal zwischen dem EA und dem Skript sein. Der EA ist ein Client, das Skript ist ein Server und das Objekt ist ein Kommunikationskanal zwischen ihnen. Auf diese Weise erfasst das Skript die Werte auf dem entfernten Webserver und trägt den gewünschten Wert in das Objekt ein. Der EA wird von Zeit zu Zeit sehen, welchen Wert das Objekt hat (wenn es existiert), denn wenn das Skript nicht läuft, sollte das Objekt nicht verfügbar sein. Jedenfalls verstößt der Zeitpunkt, zu dem der EA den Wert im Objekt betrachtet, in keiner Weise gegen das Skript. Wenn das Skript blockiert wird, weil es auf eine Antwort von einem entfernten Server wartet, wirkt sich dies nicht auf den EA aus, da er unabhängig von den Aktionen des Skripts weiterarbeitet.

Dies ist zwar eine gute Lösung, aber nicht perfekt: Das Problem liegt im Skript.

Um dies zu verstehen, sehen Sie sich das folgende Video an und achten Sie dabei auf jedes Detail.


Alles funktioniert bestens. Das war zu erwarten, da diese Art von Lösung in der Programmierung weit verbreitet ist, wenn es um die Entwicklung eines Client-Server-Programms geht, bei dem wir nicht wollen, dass der eine den anderen blockiert. Mit anderen Worten: Wir verwenden einen Kanal für die Kommunikation zwischen Prozessen. Wenn sie sich in der gleichen Umgebung befinden, wird der Kanal oft mit Hilfe von Speicher erstellt - ein isolierter Bereich wird speziell dafür zugewiesen, der jedoch gemeinsam genutzt wird und sowohl für den Client als auch für den Server sichtbar ist. Der Server fügt dort Daten hinzu, und der Client besucht denselben Bereich, um die vorhandenen Daten abzurufen. Das eine hängt also nicht vom anderen ab, obwohl beide miteinander verbunden sind.

Die Idee ist, das gleiche Prinzip anzuwenden. Aber die Art und Weise, wie das Skript funktioniert, bringt ein Problem mit sich. Wenn wir den Zeitrahmen wechseln, wird das Skript geschlossen, und selbst wenn wir eine Endlosschleife verwenden, wird es von MetaTrader 5 geschlossen. Da dies geschieht, müssten wir das Skript neu initialisieren und wieder in das Diagramm einfügen. Aber wenn wir ständig den Zeitrahmen wechseln müssen, wird das ein Problem sein, ganz zu schweigen von der Notwendigkeit, das Skript jedes Mal wieder auf dem Chart zu starten.

Außerdem kann es vorkommen, dass wir vergessen zu prüfen, ob das Skript auf dem Chart läuft oder nicht, und daher werden wir am Ende die falschen Informationen verwenden, da wir aufgrund der Art und Weise, wie der EA kodiert ist, nicht wissen können, ob das Skript auf dem Chart existiert. Dieses Problem kann gelöst werden, indem überprüft wird, ob sich ein Skript im Diagramm befindet oder nicht. Diese Aufgabe ist nicht schwer: Schreiben Sie einfach eine Überprüfung der letzten Skriptveröffentlichungszeit in das Objekt. Damit wäre das Problem gelöst.

Es ist jedoch möglich, eine viel bessere Lösung zu schaffen (zumindest in einigen Fällen), und um ehrlich zu sein, ist dies fast die ideale Lösung, und wir werden das gleiche Konzept wie oben vorgestellt verwenden, nur anstelle eines Skripts werden wir einen Dienst verwenden.


3. Einen Dienst erstellen

Dies ist eine extreme Lösung, aber da das Skript das Problem hat, bei jeder Änderung des Zeitrahmens abgebrochen zu werden, müssen wir eine andere Methode verwenden. Aber indem wir ein Problem lösen, schaffen wir ein anderes. In jedem Fall ist es gut zu wissen, welche Lösungen möglich sind und wie sie eingesetzt werden können. Das Wichtigste ist jedoch, die Grenzen jeder Lösung zu kennen und zu versuchen, einen Mittelweg zu finden, der die bestmögliche Lösung des Problems ermöglicht.

Beim Programmieren ist es so, dass wir, wenn wir versuchen, ein Problem zu lösen, ein neues schaffen.

Unser Ziel ist es, etwas Ähnliches wie das folgende Bild zu schaffen:

Dies mag zwar einfach erscheinen, doch die damit verbundenen Ressourcen werden in der Regel kaum erforscht. Ich werde also versuchen, auf die Einzelheiten einzugehen, um allen zu helfen, die mehr über die Arbeit mit diesen Ressourcen erfahren möchten.


3.1. Zugriff auf globale Variablen

Dieser Teil ist so wenig erforscht, dass ich zuerst sogar darüber nachgedacht habe, eine DLL zu erstellen, nur um diese Funktion zu unterstützen, aber nachdem ich in die MQL5-Dokumentation geschaut habe, habe ich sie gefunden. Das Problem ist, dass wir auf einen gemeinsamen Punkt zwischen dem Dienst und dem EA zugreifen oder einen solchen schaffen müssen. Wenn wir ein Skript verwendet haben, war dieser Punkt ein Objekt, aber wenn wir einen Dienst verwenden, können wir nicht dasselbe tun. Die Lösung wäre, eine externe Variable zu verwenden, aber als ich das versuchte, war die Leistung nicht wie erwartet. Weitere Einzelheiten finden Sie in der Dokumentation zu den externen Variablen. Sie erklärt, was zu tun ist.

Diese Idee war also nicht gut, also beschloss ich, die DLL zu verwenden. Ich wollte jedoch noch MetaTrader 5 und MQL5 lernen, also schaute ich in das Terminal und fand das, was Sie im Bild unten sehen können:

         

Das ist es, wonach wir gesucht haben: Wir haben eine Variable hinzugefügt, mit der wir überprüfen können, wie dieses Verfahren konfiguriert werden kann. Wir können jedoch nur double Werte verwenden. Man könnte meinen, dass dies das Problem ist (obwohl es eigentlich eine Einschränkung ist), aber es reicht aus, wenn wir kurze Nachrichten übermitteln wollen, was in unserem Fall der Fall ist. Der Double-Typ ist eigentlich eine kurze 8-Zeichen-Zeichenkette, sodass wir Werte oder kurze Nachrichten zwischen Programmen übertragen können.

Damit ist der erste Teil des Problems gelöst. MetaTrader 5 bietet Methoden, um einen Kanal zu erstellen, ohne eine DLL erstellen zu müssen, aber jetzt haben wir ein anderes Problem: Wie kann man auf diese Variablen über das Programm zugreifen? Ist es möglich, globale Variablen innerhalb des Programms zu erstellen — innerhalb eines Expert Advisors, eines Skripts, eines Indikators oder eines Dienstes? Oder sollten wir nur die im Terminal angegebenen Daten verwenden?

Diese Fragen sind sehr wichtig, wenn wir diese Lösung wirklich nutzen wollen. Wäre es nicht möglich, sie über Programme zu verwenden, müssten wir auf DLLs zurückgreifen. Aber es ist möglich. Weitere Informationen finden Sie unter Globale Variablen des Terminals.


3.2. Verwendung einer Terminalvariablen für den Informationsaustausch

Nachdem wir uns nun mit den Grundlagen beschäftigt haben, wollen wir etwas Einfaches erstellen, um zu testen und zu verstehen, wie der Prozess der Verwendung von Terminalvariablen in der Praxis funktionieren wird.

Zu diesem Zweck habe ich die folgenden Codes erstellt. Der Erste ist die Header-Datei:

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#define def_GlobalNameChannel   "InnerChannel"
//+------------------------------------------------------------------+

Hier legen wir einfach den Namen der globalen Terminalvariable fest, der für die beiden Prozesse, die auf dem grafischen Terminal laufen, gleich ist.

Nachfolgend finden Sie den Code, der den auszuführenden Dienst darstellt.

#property service
#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
#include <Inner Channel.mqh>
//+------------------------------------------------------------------+
void OnStart()
{
        double count = 0;
        while (!IsStopped())
        {
                if (!GlobalVariableCheck(def_GlobalNameChannel)) GlobalVariableTemp(def_GlobalNameChannel);
                GlobalVariableSet(def_GlobalNameChannel, count);
                count += 1.0;
                Sleep(1000);
        }
}
//+------------------------------------------------------------------+

Seine Funktionsweise ist einfach: Er prüft, ob die Variable bereits deklariert wurde und was GlobalVariableCheck macht. Wenn die Variable nicht existiert, wird sie vorübergehend von der Funktion GlobalVariableTemp erstellt und erhält dann einen Wert von der Funktion GlobalVariableSet. Mit anderen Worten: Wir testen, erstellen und schreiben Informationen, der Dienst fungiert als Server, genau wie ein Skript, nur dass wir noch nicht auf die Website zugreifen. Zunächst sollten wir verstehen, wie das System funktioniert.

Der nächste Schritt besteht darin, einen Client zu erstellen, der in unserem Fall ein Expert Advisor ist:

#property copyright "Daniel Jose"
#property description "Testing internal channel\nvia terminal global variable"
#property version "1.03"
//+------------------------------------------------------------------+
#include <Inner Channel.mqh>
//+------------------------------------------------------------------+
int OnInit()
{
        EventSetTimer(1);
        
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        double value;
        if (GlobalVariableCheck(def_GlobalNameChannel))
        {
                GlobalVariableGet(def_GlobalNameChannel, value);
                Print(value);           
        }
}
//+------------------------------------------------------------------+

Der Code ist einfach: Der EA prüft jede Sekunde, ob die Variable existiert. Wenn sie existiert, liest der EA den Wert mit GlobalVariableGet und gibt ihn im Terminal aus.

Schauen wir uns an, wie dieser Prozess umgesetzt werden kann. Zuerst führen wir den Dienst aus. Dies geschieht folgendermaßen:

Ein anderes Szenario ist jedoch möglich, wenn der Dienst angehalten wurde und wir ihn neu starten. In diesem Fall werden wir wie folgt vorgehen:

Danach überprüfen wir die Terminalvariablen und erhalten das folgende Ergebnis:

Beachten Sie, dass das System offensichtlich funktioniert, aber jetzt müssen wir den EA auf dem Chart platzieren, die Werte abrufen und somit die Verbindung über den Kanal bestätigen. Nachdem wir also den EA auf dem Chart platziert haben, erhalten wir das folgende Ergebnis:

Das ist alles, das System funktioniert so, wie wir es wollen. Wir haben ein Modell, das unten abgebildet ist. Es handelt sich um ein typisches Client-Server-Format, und das ist genau das, was wir erreichen wollen. Wir versuchen, genau dieses Format zu implementieren, weil es die bereits erwähnten Vorteile bietet.

Jetzt müssen wir nur noch ein System zum Lesen und Abrufen von Werten aus dem Web hinzufügen. Dann haben wir das endgültige Modell zum Testen. Dieser Teil ist ziemlich einfach: Nehmen wir den Code, den wir von Anfang an verwendet haben, und fügen ihn dem Dienst hinzu. Um den Test durchzuführen, müssen wir nur die Serverdatei ändern, um den Wert von der Website zu lesen und diesen Wert für den Client zu veröffentlichen. Der neue Code des Dienstes lautet wie folgt.

#property service
#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
#include <Inner Channel.mqh>
//+------------------------------------------------------------------+
void OnStart()
{
        string szRet;
        
        while (!IsStopped())
        {
                if (!GlobalVariableCheck(def_GlobalNameChannel)) GlobalVariableTemp(def_GlobalNameChannel);
                szRet = GetDataURL("https://tradingeconomics.com/stocks", 100, "<!doctype html>", 2, "INDU:IND", 172783, 173474, 0x0D);
                GlobalVariableSet(def_GlobalNameChannel, StringToDouble(szRet));
                Sleep(1000);
        }
}
//+------------------------------------------------------------------+
string GetDataURL(const string url, const int timeout, const string szTest, int iTest, const string szFind, int iPos, int iInfo, char cLimit)
{
        string  headers, szInfo = "";
        char    post[], charResultPage[];
        int     counter;
   
        if (WebRequest("GET", url, NULL, NULL, timeout, post, 0, charResultPage, headers) == -1) return "Bad";
        for (int c0 = 0, c1 = StringLen(szTest); c0 < c1; c0++) if (szTest[c0] != charResultPage[iTest + c0]) return "Failed";
        for (int c0 = 0, c1 = StringLen(szFind); c0 < c1; c0++) if (szFind[c0] != charResultPage[iPos + c0]) return "Error";
        for (counter = 0; charResultPage[counter + iInfo] == 0x20; counter++);
        for (;charResultPage[counter + iInfo] != cLimit; counter++) szInfo += CharToString(charResultPage[counter + iInfo]);
        
        return szInfo;
}
//+------------------------------------------------------------------+

Wir haben nun ein System, das wie in der folgenden Abbildung dargestellt funktioniert:

Jetzt ist es fertig, und wir erhalten folgende Ergebnisse. Auch die Änderung des Zeitrahmens stellt kein Problem mehr dar.



Schlussfolgerung

Heute haben wir mehrere MetaTrader 5-Funktionen besprochen, die bisher wenig erforscht wurden. Einer davon sind die Kommunikationskanäle. Allerdings nutzen wir diese Funktion noch nicht voll aus. Aber wir können noch weiter gehen — das werden wir im nächsten Artikel tun. Alles, was wir bisher in dieser Serie gesehen haben, zeigt uns, wie viel wir mit der MetaTrader 5 Plattform machen können. Entscheiden Sie sich einfach für einen Weg und machen Sie weiter, bis Sie die gewünschten Ergebnisse erzielen. Allerdings ist es nützlich, die Grenzen, Vorteile und Risiken zu kennen, die mit jedem der möglichen Wege verbunden sind.


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

Beigefügte Dateien |
Script_e_EA.zip (3.03 KB)
Serviso_e_EA.zip (2.39 KB)
Neuronale Netze leicht gemacht (Teil 16): Praktische Anwendung des Clustering Neuronale Netze leicht gemacht (Teil 16): Praktische Anwendung des Clustering
Im vorigen Artikel haben wir eine Klasse für das Clustering von Daten erstellt. In diesem Artikel möchte ich Varianten für die mögliche Anwendung der gewonnenen Ergebnisse bei der Lösung praktischer Handelsaufgaben vorstellen.
Lernen Sie, wie man ein Handelssystem mit der Standardabweichung entwirft Lernen Sie, wie man ein Handelssystem mit der Standardabweichung entwirft
Hier ist ein neuer Artikel in unserer Serie darüber, wie man ein Handelssystem mit den beliebtesten technischen Indikatoren in MetaTrader 5 Handelsplattform zu entwerfen. Lernen Sie, wie man ein Handelssystem mit Hilfe des Indikators der Standardabweichung entwickelt.
Das Preisbewegungsmodell und seine wichtigsten Bestimmungen (Teil 1): Die einfachste Modellversion und ihre Anwendungen Das Preisbewegungsmodell und seine wichtigsten Bestimmungen (Teil 1): Die einfachste Modellversion und ihre Anwendungen
Der Artikel liefert die Grundlagen für eine mathematisch rigorose Theorie der Preisbewegungen und des Funktionierens des Marktes. Bis heute gibt es keine mathematisch strenge Theorie der Preisbewegung. Stattdessen haben wir es mit erfahrungsbasierten Annahmen zu tun, die besagen, dass sich der Preis nach einem bestimmten Muster in eine bestimmte Richtung bewegt. Natürlich wurden diese Annahmen weder durch Statistiken noch durch die Theorie gestützt.
DoEasy. Steuerung (Teil 7): Steuerung der Text Label DoEasy. Steuerung (Teil 7): Steuerung der Text Label
In diesem Artikel werde ich die Klasse des WinForms Steuerungsobjekts der Text Label erstellen. Ein solches Objekt kann seinen Container an beliebiger Stelle positionieren, während seine eigene Funktionalität die Funktionalität des MS Visual Studio-Text Label kopiert. Wir werden in der Lage sein, Schriftparameter für einen angezeigten Text festzulegen.