English Русский 中文 Español 日本語 Português
preview
Wie man MetaTrader 5 mit PostgreSQL verbindet

Wie man MetaTrader 5 mit PostgreSQL verbindet

MetaTrader 5Integration | 1 Juni 2023, 13:55
199 0
Jocimar Lopes
Jocimar Lopes

Einführung

Die Landschaft der Softwareentwicklung hat sich in den letzten zehn Jahren stark verändert. Wir haben die Popularisierung des Cloud Computing erlebt, und Akronyme wie IASS, PASS und SAAS sind heute wichtige Instrumente, die bei jedem Softwareprojekt berücksichtigt werden müssen. Sowohl für den Endnutzer als auch für den Softwareentwickler wurde es einfacher.

Das MetaQuotes-Team war sich dieser Änderungen bewusst und seit 2014 haben wir einen nativen WebRequest für MetaTrader 5.

Einer der Bereiche, der sich am meisten verändert hat, war die Datenbankverwaltung. Lösungen, die früher komplex oder aus praktischer Sicht sogar „seltsam“ waren, wurden nicht nur machbar, sondern auch die bevorzugte Lösung für viele Anwendungsfälle. Dies war beim Datenbankzugriff über die REST-API der Fall.

Ein Vorschlag für den Datenbankzugriff über eine REST-API würde vor ein paar Jahren wie ein Over-Engineering aussehen. Eine schnelle Suche nach „verwaltete Datenbank mit Zugriff über Rest-API“ führt heute zu Dutzenden von Anbietern, die von einfachen Plänen für ein paar Dollar/Monat bis zu maßgeschneiderten Unternehmenslösungen reichen. Viele dieser Anbieter bieten großzügige kostenlose Tiers für Prototypen, Tests oder sogar für die Bereitstellung kleiner Produktions-Workloads.

Dieser Artikel analysiert fünf Standardalternativen zur Anbindung einer Postgres-Datenbank an MetaTrader 5, ihre Anforderungen, Vor- und Nachteile. Außerdem werden wir eine Entwicklungsumgebung einrichten, eine Postgres-Datenbank als Remote-Datenbank installieren, eine Verbindung zu ihr herstellen und Daten einfügen und abrufen, die von einem MQL5-Skript oder EA verwendet werden sollen.

Die Einrichtung der Entwicklungsumgebung und die entsprechenden Verfahren lassen sich leicht mit jedem RDBMS nachbilden, da die REST-API als Abstraktionsschicht zwischen dem DB-System und dem Client-Code steht.


MetaTrader 5 und Datenbanken

MetaTrader 5 verfügt bereits über die Funktionen, die Sie benötigen, um mit einer Datenbank zu arbeiten einschließlich der Funktionen, die Sie eventuell für die Verbindung mit einer Datenbank über ein Netzwerk benötigen.

Seit 2020 bietet die Plattform eine native Integration mit SQLite. Sie können die oben erwähnten Datenbankfunktionen verwenden, um vom Code aus mit ihr zu interagieren. Darüber hinaus können Sie mit Ihren Datenbanken über eine spezielle grafische Nutzeroberfläche in MetaEditor interagieren, die das Erstellen von Tabellen, das Ändern von Tabellen und die Durchführung von CRUD-Operationen ohne zusätzliche Software erleichtert.

Das war eine große Verbesserung für den Endnutzer und eine wichtige Ergänzung für das MQL5-Entwicklerarsenal.

Unter Dutzenden von verfügbaren RDBMS, viele davon mit Open-Source-Lizenzen, scheint SQLite eine kluge Entscheidung der MetaTrader 5-Entwickler gewesen zu sein. Obwohl es sich um eine komplette SQL-Datenbank mit mehrspaltigen Indizes, Triggern, Ansichten, Acid-Transaktionen, Volltextsuche, Aggregatfunktionen und vielem mehr handelt, ist sie leichtgewichtig, dateibasiert, skalierbar und erfordert keinerlei Wartung. Laut der eigenen Website „ist es wahrscheinlich, dass mehr als eine Billion (1e12) SQLite-Datenbanken im aktiven Einsatz sind“.

Ungeachtet seiner beeindruckenden Funktionen ist SQLite von seiner Konzeption her auf einen einzelnen Nutzer beschränkt und nicht für den gleichzeitigen Zugriff in Webanwendungen gedacht. Die große Anzahl von Forenbeiträgen und Artikeln auf der MQL5-Website über die Anbindung von MetaTrader 5 an MySQL zeigt, dass es eine Nachfrage nach einer robusteren Lösung für andere Anwendungsfälle gibt.

Dieser Artikel befasst sich mit der Einrichtung einer Entwicklungsumgebung für diese Anwendungsfälle mit Postgres.

Warum Postgres

Zunächst einmal habe ich mich für Postgres entschieden, weil die andere beliebte Open-Source-Alternative, MySQL, hier bereits ausführlich behandelt wurde.

Zweitens ist Postgres ein ausgereiftes, plattformübergreifendes Open-Source-Projekt, das sehr gut gepflegt wird und über eine konsistente Dokumentation verfügt. Es ist sehr beliebt, und Sie können eine Fülle von Beispielcode, Anleitungen und Tutorials im Internet finden. Ebenso gibt es eine Vielzahl von Cloud-Anbietern für alle Bedürfnisse und Budgets.

Postgres ist unternehmenstauglich und kann gleichzeitig von einem einzelnen Nutzer, der allein auf einem Heimcomputer arbeitet, leicht verwaltet werden.

Und natürlich habe ich mich für Postgres entschieden, weil ich ihm vertraue. Seit mehr als einem Jahrzehnt bin ich ein zufriedener Nutzer von Postgres in verschiedenen Projekten.

Und zu guter Letzt implementiere ich derzeit die Lösung, die ich hier vorstelle, für meine persönliche Handelsumgebung. Es handelt sich also um eine Art „Haut im Spiel“. Ich esse mein Hundefutter.


Vier Möglichkeiten, mit Postgres von MQL5 aus zu interagieren

Soweit ich sehen kann, gibt es vier Hauptansätze für den Aufruf von Postgres aus MQL5:

  1. eine spezielle MQL5-Bibliothek/Treiber
  2. eine .dll der C++-Client-Schnittstelle
  3. über .NET Npgsql-Treiber
  4. eine REST-API

Werfen wir einen Blick auf die Anforderungen, Vor- und Nachteile der einzelnen Angebote. Ich bin mir ziemlich sicher, dass die große Gemeinschaft erfahrener Entwickler aus der MQL5-Community einfache Lösungen für die Nachteile anbieten und auch auf die Nachteile hinweisen wird, die ich bei den Vorteilen nicht sehen konnte. Diese Rückmeldung aus der MQL5-Gemeinschaft wird erwartet, da sowohl der weniger experimentierfreudige Entwickler als auch der nicht entwicklungsfreudige Händler, der hierher kommt, von dieser diesbezüglichen Diskussion profitieren wird.


1. eine spezielle MQL5-Bibliothek/Treiber

Diese Bibliothek gibt es noch nicht. Es muss entwickelt werden und würde viele Stunden harter Arbeit von einem erfahrenen MQL5-Entwickler erfordern. Das wäre nicht billig. Wir müssen auch die Wartungskosten berücksichtigen. Postgres ist ausgereift, aber in keiner Weise statisch. Es handelt sich um ein aktives Projekt mit regelmäßigen Veröffentlichungen, und einige dieser Veröffentlichungen, wenn auch nicht viele, werden Aktualisierungen des Client-Codes erfordern.

Ein Beispiel: Die letzte Postgres-Version (15) verlangt derzeit, dass reguläre Nutzer einer Datenbank bestimmte Rechte im „öffentlichen Schema“ erhalten müssen. Diese Anforderung gab es in früheren Versionen nicht. Wahrscheinlich ist die Wartung in mehreren Codebasen da draußen erforderlich.

Der Vorteil, die Entwicklung eines speziellen MQL5-Treibers für Postgres in Auftrag zu geben, besteht darin, dass er, wenn er gemeinsam genutzt wird, für viele MQL5-Nutzer nützlich sein könnte. Der Nachteil liegt auf der Hand: die Kosten für Zeit und Geld.

Wo soll man anfangen, wenn man diesen Weg wählt?

Eine generische Suche nach MySQL-Artikeln auf dieser Website liefert einige nützliche Hinweise.

Die Open-Source-C++-Client-Bibliothek libpqxx

Die offizielle C-Client-Bibliothek für Postgres libpq


2. Eine .dll der C++-Client-Schnittstelle

Dies ist eine extern gepflegte offizielle C++-Bibliothek, libpqxx, die auf der intern gepflegten offiziellen C-Bibliothek, libpq, die mit der Postgres-Distribution ausgeliefert wird, aufgebaut ist.

Ich persönlich habe ihn nie verwendet und kann nur sagen, dass er schon lange da ist und gut gewartet zu sein scheint. Der Nachteil dieser Methode ist, dass der MQL5-Markt keine DLLs zulässt. Wenn dies für Ihr Projekt kein Problem darstellt und Sie zu Hause mit .dlls von MetaTrader arbeiten, könnte dies Ihre Lösung sein.

Wo soll man anfangen, wenn man diesen Weg wählt?

Die Open-Source-C++-Client-Bibliothek libpqxx


3. Über .NET Npgsql-Treiber

Seit 2018 bietet MetaTrader 5 native Unterstützung für .NET-Bibliotheken mit dem Import „intelligenter“ Funktionen. Mit der Freigabe von Platform Build 1930 können .NET-Bibliotheken verwendet werden, ohne dass spezielle Wrapper geschrieben werden müssen —  MetaEditor macht das von alleine. 

Um den .NET Npgsql-Treiber zu verwenden, müssen Sie lediglich die .dll selbst importieren. Es gibt einige Einschränkungen, die Sie in den offiziellen Versionshinweisen nachlesen können (https://www.mql5.com/en/forum/285632).

Wo soll man anfangen, wenn man diesen Weg wählt?

Der quelloffene Postgres-Treiber für .NET


4. Eine REST-API

Wenn Sie sich für „ohne .dll“ entscheiden, sollte dies die schnellere und kostengünstigere Methode sein. Die API kann in jeder beliebigen Sprache geschrieben werden, und Sie können innerhalb eines Tages oder sogar einiger Stunden einen funktionierenden Prototyp haben.

Außerdem bieten einige Cloud-Anbieter kostenlos eine integrierte REST-API für Postgres an. Alles, was Sie für den Anfang brauchen, ist eine gute Entwicklungsumgebung für Ihren MQL5-Code.

Durch die Verwendung dieser Methode kann Ihr MQL5-Code Ihre Postgres-Antworten als JSON konsumieren.

Wo soll man anfangen, wenn man diesen Weg wählt?

Hier! Lesen Sie einfach weiter, folgen Sie den nachstehenden Schritten, laden Sie den Beispielcode herunter und beginnen Sie mit der Speicherung und Abfrage Ihrer Geschäfte und Abschlüsse in einer Postgres-Datenbank.


Einrichten der Entwicklungsumgebung

Unabhängig davon, für welche Methode Sie sich entscheiden, benötigen Sie eine Entwicklungsumgebung auf einem Windows-Rechner mit einem laufenden Postgres-Server. Wie das Sprichwort sagt: Es gibt mehr als einen Weg, es zu tun. Ich erinnere mich an diese drei Wege, vom komplexesten und zeitaufwändigsten bis zum einfachsten:

  1. Kompilierung aus dem Quellcode
  2. Docker-Container
  3. msi-Installationsprogramm eines Drittanbieters

All dies sind gute Möglichkeiten, Postgres unter Windows zu nutzen, aber glauben Sie mir, eine Kompilierung aus dem Quellcode unter Windows sollte Ihre letzte Option sein, es sei denn, Sie sind bereit, Theorie und Praxis der intermittierenden Ausfallsicherheit in der Softwareentwicklung zu lernen.

Der Docker-Container ist eine sehr gute Option, eine robuste und flexible Installation, bei der Ihr Datenbankserver auf einem „entfernten“ Rechner und nicht auf „localhost“ läuft (siehe unten). Es ist ja auch ganz einfach. Sie brauchen nur Docker zu installieren und zwei bis drei Befehlszeilen und schon können Sie loslegen.

Abgesehen von den relativen Unannehmlichkeiten, die mit Software von Drittanbietern verbunden sind, ist das msi-Installationsprogramm von Drittanbietern eine gute Alternative, um die abenteuerliche Kompilierung aus dem Quellcode oder die Docker-Installation und das Container-Management zu vermeiden.

Aber ich würde keine Entwicklungsumgebung für einen Datenbankserver oder irgendeinen anderen Server als „localhost“ empfehlen, wenn es möglich ist, gegen einen Server zu entwickeln, der sich auf einem entfernten Rechner befindet. Das liegt daran, dass es immer eine gute Praxis ist, einen Server in einer entfernten Umgebung zu entwickeln, zu testen und zu debuggen und nicht in „localhost“, um Verbindungseinstellungen und Authentifizierungsprobleme so schnell wie möglich zu beheben.

Vorhang auf für WSL.

Was ist WSL

WSL steht für Windows Subsystem For Linux.

Falls Sie es verpasst haben: Seit 2016 können Sie eine Linux-Distribution auf einem Windows-Rechner als Subsystem ausführen. Keine Sorge! Hier gibt es keine Hacks. WSL wird von Microsoft entwickelt und ist in Windows integriert. Sie müssen sie nur aktivieren, wie wir weiter unten sehen werden.

Warum WSL

Warum installieren Sie Postgres nicht einfach auf einem anderen Windows-Rechner, eventuell einer virtuellen Maschine?

Denn Postgres ist ein natives Unix-System, das in *nix-Systemen erstellt und entwickelt wurde. Die Installation unter Linux ermöglicht eine einfache Installation, einfache Updates und einfache Wartung. Die gesamte offizielle Dokumentation ist auf ein Unix-System ausgerichtet. Die meisten Codebeispiele, Snippets und allgemeinen Hilfestellungen, die Sie im Internet finden, spiegeln diese Tatsache wider.

So wird es Ihnen leicht fallen, in einem Linux-System zu entwickeln. Und WSL wurde von Microsoft genau für diesen Zweck entwickelt.

WSL installieren

Voraussetzungen aus der Microsoft-Dokumentation:

„Sie müssen Windows 10 Version 2004 und höher (Build 19041 und höher) oder Windows 11 verwenden, um die folgenden Befehle zu verwenden. Wenn Sie frühere Versionen verwenden, lesen Sie bitte die Seite zur manuellen Installation.“

Wenn Ihr System diese Voraussetzung erfüllt, öffnen Sie einfach eine Power Shell als Administrator und geben Sie den folgenden Befehl ein, um WSL zu installieren/aktivieren:

wsl -install

wsl Installationsbefehl in Power Shell

Mit diesem Befehl wird Ubuntu auf der WSL installiert, da es die Standard-Distribution ist. 

Starten Sie Windows neu.

Dies sollte ein unkomplizierter Prozess sein. Sollte dies nicht der Fall sein, finden Sie in der oben verlinkten offiziellen MS-Dokumentation einen Abschnitt mit den häufigsten Installationsproblemen.

Nach dem Neustart sollten Sie etwa so etwas sehen. Legen Sie einen neuen UNIX-Nutzernamen und ein Passwort an.

wsl-Installation nach dem ersten Neustart


Jetzt, wo WSL/Ubuntu installiert ist und läuft, installieren wir Postgres darauf.

Installieren Sie Postgres auf der WSL

Geben Sie den folgenden Befehl ein.

sudo apt install postgresql postgresql-contrib

Mit diesem Befehl wird die letzte stabile Version des PostgreSQL-Pakets installiert, die in den Ubuntu-Repositories verfügbar ist. Es enthält den Server, den pgsql-Client, praktische Binärdateien und einige Dienstprogramme. Alles, was Sie für den Anfang brauchen.

Wenn Sie die neueste stabile Postgres-Version installieren wollen - die sich normalerweise von der letzten stabilen Version in den Ubuntu-Repositories unterscheidet - können Sie das offizielle Postgres-Repository in die Quellenliste Ihres Paketmanagers aufnehmen. Detailierte Instruktionen finden Sie in der offiziellen Postgres Dokumentation.

Wenn alles in Ordnung war, geben Sie den Befehl

psql --version

ein, es sollte die installierte Version Ihrer Postgres-Datenbank zurückgeben.


Starten Sie den Server

Geben Sie diesen Befehl ein, um den Server zu starten.

sudo service postgresql start

Standardmäßig werden bei einer neuen Postgres-Installation nur Verbindungen von „localhost“ akzeptiert. Das sollten wir ändern.

Suchen Sie die Postgres-Konfigurationsdatei.

sudo -u postgres psql -c "SHOW config_file"

Postgres Installation Anzeige der Config-Datei


Bearbeiten Sie die Konfigurationsdatei, um Verbindungen außerhalb von localhost zu akzeptieren. Ändern Sie die Zeile listen_addresses.

postgres-Konfiguration von listen_addresses


Suchen Sie die Konfigurationsdatei pg_hba.

sudo -u postgres psql -c "SHOW hba_file"

postgres-konfiguration hba-Datei anzeigen


Bearbeiten Sie die Datei pg_hba.conf, um die Authentifizierung per Passwort sowohl für IPv4 als auch für IPv6 zu ermöglichen.

postgres-konfiguration pg_hba Auth. durch Passwort


Greifen Sie nun auf das Dienstprogramm psql als der von der Installation erstellte Standardnutzer von Postgres zu. Er trägt den Namen „postgres“.

sudo -u postgres psql


Erstellen Sie einen regulären Datenbanknutzer mit dem Privileg CREATEDB. Bislang wurde bei der Installation nur der Nutzer 'postgres' angelegt.

Gewähren Sie mt5_user alle Berechtigungen für das Schema public. Dies ist nicht notwendig, wenn Ihre Postgres-Version unter 15 liegt.

CREATE USER mt5_user PASSWORD '123' CREATEDB;

GRANT ALL ON SCHEMA public TO mt5_user;

postgres Nutzererstellung mit allen Privilegien


Erstellen Sie eine Datenbank my_remote_db und gewähren Sie mt5_user alle Berechtigungen.

GRANT ALL PRIVILEGES ON DATABASE my_remote_db TO mt5_user;

psql Erstellen von db mit Gewährung aller Privilegien


Verbindung zu Postgres

Jetzt sollten Sie einen Datenbankserver haben, der auf einem entfernten Rechner mit einer anderen IP-Adresse als Ihrem lokalen Windows-Host läuft und bereit ist, Verbindungen über das Netzwerk zu akzeptieren. Wir können eine Verbindung über Socket oder HTTP herstellen. Da wir mit einer REST-API interagieren werden, verwenden wir in diesem Beispiel die letztere.

Sehen wir uns an, ob wir eine Verbindung zu my_remote_db als mt5_user mit Passwort 123 auf dem WSL-Host herstellen können.

Geben Sie diesen Befehl ein, um Ihren WSL-Hostnamen (IP) zu ermitteln.

hostname -I

Ubuntu Terminal Befehl hostname


Überprüfen Sie den Status des Postgres-Servers. Starten Sie ihn, wenn er ausgefallen ist. Mit diesem Befehl können Sie den Server starten, neu starten oder anhalten.

sudo service postgresql {status, start, stop}


Gehen Sie auf dem MetaTrader 5-Terminal auf Extras > Optionen > Tab Expert Advisors und nehmen Sie die WSL-Host-IP in die Liste der zulässigen IPs auf.

Menü der MT5-Terminal-Tools-Optionen

Das MetaTrader 5-Terminal akzeptiert nur HTTP- und HTTPS-Verbindungen über die Ports 80 bzw. 443. Nur die Ports 80 und 443. Sie sollten dieses Sicherheitsmerkmal berücksichtigen, wenn Sie Ihre API entwickeln. Normalerweise wird der Entwicklungsserver auf einem unprivilegierten Port wie 3000 oder 5000 abgehört, bevor er auf einen echten Server in der Produktion umzieht. Damit Sie also Anfragen an die IP-Adresse senden können, die Sie oben in Ihren Terminaleinstellungen angegeben haben, müssen Sie den am Port des Entwicklungsservers ankommenden Datenverkehr auf Port 80 für HTTP-Anfragen und/oder 443 für HTTPS-Anfragen umleiten.

Der Einfachheit halber finden Sie in der README-Datei der beigefügten Python-Anwendung eine Anleitung, wie Sie diese Umleitung auf WSL durchführen können.


Starten der Demo-App

Da es in diesem Artikel um MQL5 geht, werde ich nicht auf die Einzelheiten der API-Implementierung eingehen. Stattdessen habe ich eine Demo-Anwendung entwickelt, die Sie als Python-Paket herunterladen und installieren können, um die Interaktion Ihres MQL5-Codes mit der API zu testen.

Um die Demo-Anwendung zu starten, muss lediglich Python auf der WSL installiert sein. Sie sollte bereits vorhanden sein.

Es wird dringend empfohlen, eine virtuelle Python-Umgebung ('venv') zu erstellen, um die Anwendung zu installieren. Dadurch wird sichergestellt, dass die Python-Installation Ihres Systems nicht durcheinander gebracht wird. Nachdem Sie mit der App gespielt haben, können Sie die virtuelle Umgebung einfach löschen.

Sie können die virtuelle Umgebung mit diesem Befehl erstellen.

python3 -m venv 'venv'


Nachdem Sie also die Demo-Anwendung installiert haben, müssen Sie mit der Entwicklung Ihres MQL5-Codes beginnen:

  1. WSL starten
  2. Postgres-Server starten
  3. Starten der Demo-Anwendung
  4. IP von hostname aus der Ausgabe der Demo-Anwendung abrufen
  5. IP von hostname zu den erlaubten Adressen im Terminal hinzufügen

Sowohl die WSL als auch der Postgres-Server können so konfiguriert werden, dass sie beim Windows-Start gestartet werden.


Einfügen von Daten aus MQL5

Lassen Sie uns versuchen, einige Daten einzufügen. Zunächst unsere Kontoinformationen. Erstellen Sie auf Ihrem MT5-Terminal ein neues Skript und fügen Sie den folgenden Code ein.

//+------------------------------------------------------------------+
//|                                                post_acc_info.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <JAson.mqh> //--- include the JSON library
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- gathering the data - Account Info
   CJAVal data;
   CJAVal acc_info;
//--- doubles
   data["balance"] =          AccountInfoDouble(ACCOUNT_BALANCE);
   data["credit"] =           AccountInfoDouble(ACCOUNT_CREDIT);
   data["profit"] =           AccountInfoDouble(ACCOUNT_PROFIT);
   data["equity"] =           AccountInfoDouble(ACCOUNT_EQUITY);
   data["margin"] =           AccountInfoDouble(ACCOUNT_MARGIN);
   data["margin_free"] =      AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   data["margin_level"] =     AccountInfoDouble(ACCOUNT_MARGIN_LEVEL);
   data["margin_so_call"] =   AccountInfoDouble(ACCOUNT_MARGIN_SO_CALL);
   data["margin_so_so"] =     AccountInfoDouble(ACCOUNT_MARGIN_SO_SO);
//--- integers
   data["login"] =            AccountInfoInteger(ACCOUNT_LOGIN);
   data["leverage"] =         AccountInfoInteger(ACCOUNT_LEVERAGE);
   data["trade_allowed"] =    AccountInfoInteger(ACCOUNT_TRADE_ALLOWED);
   data["ea_allowed"] =       AccountInfoInteger(ACCOUNT_TRADE_EXPERT);
   data["trade_mode"] =       AccountInfoInteger(ACCOUNT_TRADE_MODE);
   data["margin_so_mode"] =   AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE);
//-- strings
   data["company"] =          AccountInfoString(ACCOUNT_COMPANY);
   data["currency"] =         AccountInfoString(ACCOUNT_CURRENCY);
   data["name"] =             AccountInfoString(ACCOUNT_NAME);
   data["server"] =           AccountInfoString(ACCOUNT_SERVER);
   
//--- fill in the acc_info array with Account Info data
   acc_info["acc_info"].Add(data);
   
//--- WebRequest arguments
   string method = "POST";
   string url = "http://172.22.18.235/accs";
   string headers = "Content-Type: application/json";
   int timeout = 500;
   char post[], result[];
   string result_headers;
   
//--- prepare JSON data to send
   string json = acc_info.Serialize();
   ArrayResize(post, json.Length(), 0);
   StringToCharArray(json, post, 0, StringLen(json), CP_UTF8);
   ResetLastError();
   
//--- send the request
   int res = WebRequest(method, url, headers, timeout, post, result, result_headers);
   if(res == -1)
     {
      Print("Error in WebRequest  =", GetLastError());
      MessageBox("Add " + url + " to allowed URLs on MT5 terminal", "Unknown URL", MB_ICONINFORMATION);     }
   else
     {
      Print("Starting post...");
      
      if(res == 201)// HTTP result code 201 (created)
        {
         Print("posted accs");
        }
     }
  }

Wie Sie am Anfang der Datei sehen können, verwenden wir eine Hilfsbibliothek, um unsere JSON-Daten zu serialisieren/deserialisieren. Sie wurde von einem Mitglied der MQL5-Gemeinschaft entwickelt und Sie können die Bibliothek im seinem Repository auf GitHub finden.

Fügen wir nun unsere Deals aus der MetaTrader 5 Historie ein. Erstellen Sie ein neues Skript und fügen Sie den folgenden Code ein.

//+------------------------------------------------------------------+
//|                                                   post_deals.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <JAson.mqh> //--- include the JSON library
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- gathering the data - Deals
   CJAVal data;
   CJAVal deals;
//--- request trade history
   HistorySelect(0, TimeCurrent());
   int deals_total = HistoryDealsTotal();
//--- iterate over all deals to get data
//--- of each deal from its ticket number
   for(int i = 0; i < deals_total; i++)
     {
      //-- integers
      ulong deal_ticket =   HistoryDealGetTicket(i);
      data["ticket"] =     (int) deal_ticket;
      data["order"] =      (int) HistoryDealGetInteger(deal_ticket, DEAL_ORDER);
      data["position"] =   (int) HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID);
      data["time"] =       (int) HistoryDealGetInteger(deal_ticket, DEAL_TIME);
      data["type"] =       (int) HistoryDealGetInteger(deal_ticket, DEAL_TYPE);
      data["entry"] =      (int) HistoryDealGetInteger(deal_ticket, DEAL_ENTRY);
      data["magic"] =      (int) HistoryDealGetInteger(deal_ticket, DEAL_MAGIC);
      data["reason"] =     (int) HistoryDealGetInteger(deal_ticket, DEAL_REASON);
      //--- strings
      data["symbol"] =     (string) HistoryDealGetString(deal_ticket, DEAL_SYMBOL);
      //--- doubles
      data["volume"] =     (double) HistoryDealGetDouble(deal_ticket, DEAL_VOLUME);
      data["price"] =      (double) HistoryDealGetDouble(deal_ticket, DEAL_PRICE);
      data["profit"] =     (double) HistoryDealGetDouble(deal_ticket, DEAL_PROFIT);
      data["swap"] =       (double) HistoryDealGetDouble(deal_ticket, DEAL_SWAP);
      data["comission"] =  (double) HistoryDealGetDouble(deal_ticket, DEAL_COMMISSION);
 //--- fill in the deals array with each deal data
      deals["deals"].Add(data);
     }
 //--- WebRequest arguments
   string method = "POST";
   string url = "http://172.22.18.235/deals";
   string headers = "Content-Type: application/json";
   int timeout = 500;
   char post[], result[];
   string result_headers;
   
 //--- prepare JSON data to send
   string json = deals.Serialize();
   ArrayResize(post, json.Length(), 0);
   StringToCharArray(json, post, 0, StringLen(json), CP_UTF8);
   ResetLastError();
//--- send the request
   int res = WebRequest(method, url, headers, timeout, post, result, result_headers);
   
   if(res == -1)
     {
      Print("Error in WebRequest  =", GetLastError());
      MessageBox("Add " + url + " to allowed URLs on MT5 terminal", "Unknown URL", MB_ICONINFORMATION);     }
   else
     {
      Print("Starting post...");
      
      if(res == 201)// HTTP result code 201 (created)
        {
         Print("posted deals");
        }
     }
  }


Abfrage von Daten aus MQL5

Lassen Sie uns nun unsere kürzlich eingefügten Daten abfragen. Erstellen Sie in Ihrem MetaTrader 5-Terminal ein neues Skript und fügen Sie den folgenden Code ein.

//+------------------------------------------------------------------+
//|                                                 get_endpoint.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <JAson.mqh> //--- include the JSON library
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- choose the testing endpoint
   string endpoint = "accs"; // or "deals"
//--- WebRequest arguments
   string method = "GET";
   string url = "http://172.22.18.235/" + endpoint;
   string cookie = NULL, headers;
   int timeout = 500;
   char post[], result[];
   ResetLastError();
//--- send the request
   int res = WebRequest(method, url, cookie, NULL, timeout, post, 0, result, headers);
   if(res == -1)
     {
      Print("Error in WebRequest  =", GetLastError());
      MessageBox("Add " + url + " to allowed URLs on MT5 terminal", "Unknown URL", MB_ICONINFORMATION);
     }
   else
     {
      Print("Starting get...");
      if(res == 200)// HTTP result code 200 (OK)
        {
         PrintFormat("Server headers: %s", headers);
         ResetLastError();
         // save the returned JSON in a file
         string terminal_data_path = TerminalInfoString(TERMINAL_DATA_PATH);
         string subfolder = "TutoPostgres";
         string filename = endpoint + "_fromserver.json";
         int filehandle = FileOpen(subfolder + "\\" + filename, FILE_WRITE | FILE_BIN);
         if(filehandle != INVALID_HANDLE)
           {
            FileWriteArray(filehandle, result, 0, ArraySize(result));
            FileClose(filehandle);
            Print(filename + " created at " + terminal_data_path + "\\" + subfolder);
           }
         else
            Print("File open failed with error ", GetLastError());
        }
      else
         PrintFormat("Request to '%s' failed with error code %d", url, res);
     }
  }

Wenn Sie den Endpunkt von „accs“ in „deals“ ändern, können Sie Ihre gerade eingefügten Geschäfte abfragen. Überprüfen Sie Ihren Pfad: <MT5-Terminalpfad>\Files\TutoPostgres. Wenn alles geklappt hat, sollten dort mindestens zwei Dateien vorhanden sein: accs_fromserver.json und deals_fromserver.json. 


Verwenden von JSON-Daten in Expert Advisors

Um die vom Server zurückgegebenen JSON-Daten zu verwenden, müssen sie deserialisiert werden. Die oben erwähnte Hilfsbibliothek kann dies tun.

Wenn Sie sich die JSON-Dateien angesehen haben, die nach der Abfrage der Datenbank mit dem obigen Beispielcode gespeichert wurden, haben Sie vielleicht eine JSON-Zeichenfolge wie diese gesehen:

[
  {
    "a_balance": "10005.93",
    "a_company": "MetaQuotes Software Corp.",
    "a_credit": "0.0",
    "a_currency": "USD",
    "a_ea_allowed": true,
    "a_equity": "10005.93",
    "a_id": 3,
    "a_leverage": 100,
    "a_login": 66744794,
    "a_margin": "0.0",
    "a_margin_free": "10005.93",
    "a_margin_level": "0.0",
    "a_margin_so_call": "50.0",
    "a_margin_so_mode": "0",
    "a_margin_so_so": "30.0",
    "a_name": "MetaTrader 5 Desktop Demo",
    "a_profit": "0.0",
    "a_server": "MetaQuotes-Demo",
    "a_trade_allowed": true,
    "a_trade_mode": "0"
  },
  {
(...)

Wir werden diese Schlüssel für den Zugriff auf die deserialisierten Daten verwenden. Die „0“ (Null) im Array-Index ist der Zugriff auf das erste zurückgegebene Konto. Wenn Sie mehr als ein Konto haben, gibt dieser Endpunkt („accs“) alle Konten zurück, und Sie können auf jedes von ihnen zugreifen, indem Sie über das Array mit diesem Index iterieren.

//+------------------------------------------------------------------+
//|                                                 consume_json.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <JAson.mqh> //--- include the JSON library
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- choose the testing endpoint
   string endpoint = "accs"; // or "deals"
//--- WebRequest arguments
   string method = "GET";
   string url = "http://172.22.18.235/" + endpoint;
   string cookie = NULL, headers;
   int timeout = 500;
   char post[], result[];
   ResetLastError();
//--- send the request
   int res = WebRequest(method, url, cookie, NULL, timeout, post, 0, result, headers);
   if(res == -1)
     {
      Print("Error in WebRequest  =", GetLastError());
      MessageBox("Add " + url + " to allowed URLs on MT5 terminal", "Unknown URL", MB_ICONINFORMATION);
     }
   else
     {
      Print("Starting get...");
      if(res == 200)// HTTP result code 200 (OK)
        {
         CJAVal data;
         data.Deserialize(result);
         //--- doubles
         double a_balance =         data[0]["a_balance"].ToDbl();
         double a_credit =          data[0]["a_credit"].ToDbl();
         double a_profit =          data[0]["a_profit"].ToDbl();
         double a_equity =          data[0]["a_equity"].ToDbl();
         double a_margin =          data[0]["a_margin"].ToDbl();
         double a_margin_free =     data[0]["a_margin_free"].ToDbl();
         double a_margin_level =    data[0]["a_margin_level"].ToDbl();
         double a_margin_so_call =  data[0]["a_margin_so_call"].ToDbl();
         double a_margin_so_so =    data[0]["a_margin_so_so"].ToDbl();
         //--- longs
         long a_login =             data[0]["a_login"].ToInt();
         long a_leverage =          data[0]["a_leverage"].ToInt();
         long a_trade_mode =        data[0]["a_trade_mode"].ToInt();
         long a_margin_so_mode =    data[0]["a_margin_so_mode"].ToInt();
         long a_id =                data[0]["a_id"].ToInt(); //--- database generated ID
         //--- strings
         string a_company =         data[0]["a_company"].ToStr();
         string a_currency =        data[0]["a_currency"].ToStr();
         string a_name =            data[0]["a_name"].ToStr();
         string a_server =          data[0]["a_server"].ToStr();
         //--- booleans
         bool a_ea_allowed =        data[0]["a_ea_allowed"].ToBool();
         bool a_trade_allowed =     data[0]["a_trade_allowed"].ToBool();
         //printf("Server headers: %s", headers);
         //--- doubles
         printf("Balance: %d", a_balance);
         printf("Credit: %d", a_credit);
         printf("Profit: %d", a_profit);
         printf("Equity: %d", a_equity);
         printf("Margin: %d", a_margin);
         printf("Margin Free: %d", a_margin_free);
         printf("Margin Level: %d", a_margin_level);
         printf("Margin Call Level: %d", a_margin_so_call);
         printf("Margin Stop Out Level: %d", a_margin_so_so);
         //--- longs
         printf("Login: %d", a_login);
         printf("Leverage: %d", a_leverage);
         printf("Trade Mode: %d", a_trade_mode);
         printf("Margin Stop Out Mode: %d", a_margin_so_mode);
         printf("Database ID: %d", a_id);
         //--- strings
         printf("Company: %s", a_company);
         printf("Currency: %s", a_currency);
         printf("Platform Name: %s", a_name);
         printf("Server: %s", a_server);
         //--- booleans
         printf("Expert Advisor Allowed: %d", a_ea_allowed);
         printf("Trade Allowed: %d", a_trade_allowed);
         Print("Done!");
        }
      else
         PrintFormat("Request to '%s' failed with error code %d", url, res);
     }
  }


SQLite als Postgres-Spiegel

Es ist auch möglich, die bestehende MQL5-Infrastruktur zu nutzen, indem die entfernten Daten als lokale SQLite-Datenbank verwendet werden. Um diese Funktion zu implementieren, müssen wir die Datenbanken synchronisieren. Diese Synchronisierung würde fast in Echtzeit erfolgen, mit nur wenigen Sekunden Verzögerung. Aber es würde die Leistung verbessern, Netzwerklatenz vermeiden und den Datenzugriff über die Standard-GUI von MetaEditor und die Verwendung von MQL5-Datenbankfunktionen in Ihrem MQL5-Code ermöglichen.

Wenn Sie diese Funktion für nützlich halten, lassen Sie es mich bitte wissen. Ich bin gerne bereit, ein ausführliches Tutorial mit Beispielcode für diese Synchronisation zwischen der entfernten Postgres- und der lokalen SQLite-Datenbank zu schreiben.


Schlussfolgerung

In diesen Anmerkungen haben wir einige derzeit verfügbare Methoden zur Verbindung einer MQL5-Code-Instanz mit einer Postgres-Datenbank untersucht. Wir haben uns für eine REST-API als praktikable und schnelle Alternative zur teureren dedizierten Treiberentwicklung oder der Verwendung von .dlls entschieden. Außerdem haben wir eine einfache Demo-Anwendung als Beispiel dafür entwickelt, wie man eine Entwicklungsumgebung für MQL5/Postgres auf Windows Subsystem For Linux einrichtet.

Jetzt können Sie mit der Entwicklung beginnen! Wählen Sie einen guten Cloud-Anbieter und nutzen Sie die gesamte Leistungsfähigkeit von Postgres-Analysen, Automatisierung, Webskalierbarkeit und Erweiterungen für maschinelles Lernen, um Ihren Handel voranzutreiben.

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

Experimente mit neuronalen Netzen (Teil 5): Normalisierung der Eingaben zur Weitergabe an ein neuronales Netz Experimente mit neuronalen Netzen (Teil 5): Normalisierung der Eingaben zur Weitergabe an ein neuronales Netz
Neuronale Netze sind ein ultimatives Instrument im Werkzeugkasten der Händler. Prüfen wir, ob diese Annahme zutrifft. MetaTrader 5 ist als autarkes Medium für den Einsatz neuronaler Netze im Handel konzipiert. Dazu gibt es eine einfache Erklärung.
Multibot in MetaTrader: Starten mehrerer Roboter von einem einzigen Chart aus Multibot in MetaTrader: Starten mehrerer Roboter von einem einzigen Chart aus
In diesem Artikel werde ich eine einfache Vorlage für die Erstellung eines universellen MetaTrader-Roboters besprechen, der auf mehreren Charts verwendet werden kann, während er nur mit einem Chart läuft, ohne dass jede Instanz des Roboters auf jedem einzelnen Chart konfiguriert werden muss.
Experimente mit neuronalen Netzen (Teil 6): Das Perzeptron als autarkes Instrument zur Preisprognose Experimente mit neuronalen Netzen (Teil 6): Das Perzeptron als autarkes Instrument zur Preisprognose
Der Artikel liefert ein Beispiel für die Verwendung eines Perzeptrons als autarkes Preisprognoseinstrument, indem er allgemeine Konzepte und den einfachsten vorgefertigten Expert Advisor vorstellt und anschließend die Ergebnisse seiner Optimierung zeigt.
Implementierung des Janus-Faktors in MQL5 Implementierung des Janus-Faktors in MQL5
Gary Anderson entwickelte eine Marktanalysemethode, die auf einer Theorie beruht, die er Janus-Faktor nannte. Die Theorie beschreibt eine Reihe von Indikatoren, mit denen sich Trends aufzeigen und Marktrisiken bewerten lassen. In diesem Artikel werden wir diese Werkzeuge in mql5 implementieren.