English Русский 中文 Español Deutsch Português
preview
MetaTrader 5をPostgreSQLに接続する方法

MetaTrader 5をPostgreSQLに接続する方法

MetaTrader 5統合 | 6 6月 2023, 09:37
306 0
Jocimar Lopes
Jocimar Lopes

はじめに

ソフトウェア開発の状況は過去10年間で大きく変わりました。クラウドコンピューティングの普及が見られ、IASS、PASS、SAASなどの頭字語は、現在、あらゆるソフトウェアプロジェクトで考慮する必要がある重要なツールとなっています。エンドユーザーとソフトウェア開発者の両方にとって作業が簡単になりました。

MetaQuotesチームはこれらの変更を認識しており、2014年からMetaTrader 5用のネイティブWebRequestを用意しました。

最も変化した領域の1つはデータベース管理です。実用的な観点から見ると、以前は複雑、または「奇妙」でさえあった解決策が、実行可能になっただけでなく、多くの使用例において推奨される解決策になりました。こREST APIを介したデータベースアクセスの場合がそうでした。

REST APIを介してデータベースにアクセスするという提案は、数年前であればオーバーエンジニアリングのように見えたでしょう。現在、「REST API経由でアクセスできるマネージドデータベース」を簡単に検索すると、月額数ドルの基本プランからカスタマイズされたエンタープライズ解決策に至るまで、多数のプロバイダが表示されます。これらのプロバイダの多くは、プロトタイピング、テスト、さらには小規模な実稼働ワークロードの展開のための豊富な無料枠を提供しています。

この記事では、PostgresデータベースをMetaTrader 5に接続するための5つの標準的な代替案、その要件、長所と短所を分析します。また、開発環境を設定し、Postgresデータベースをリモートデータベースとしてインストールして接続し、MQL5スクリプトまたはEAで使用するデータを挿入および取得します。

REST APIはDBシステムとクライアントコードの間の抽象化層として機能するため、この開発環境の設定とそれぞれの手順は、任意のRDBMSで簡単に複製できます。


MetaTrader 5とデータベース

MetaTrader 5には、データベースを操作するために必要な関数と、ネットワークを介してデータベースに接続するために必要な関数がすでに備わっています。

2020年以降、プラットフォームはSQLiteとのネイティブ統合を提供しています。上記のデータベース関数を使用して、コードからデータベースを操作できます。さらに、MetaEditorの専用GUIを介してデータベースを操作できるため、追加のソフトウェアを必要とせずに、テーブルの作成、テーブルの変更、CRUD操作の実行が簡単になります。

これはエンドユーザーエクスペリエンスにおける大きな改善であり、MQL5開発者の武器への重要な追加でした。

利用可能なRDBMSが数十あってその多くにオープンソースライセンスがありますが、SQLiteはMetaTrader 5開発者にとって賢明な選択だったようです。マルチカラムインデックス、トリガー、ビュー、ACIDトランザクション、全文検索、集計関数などを備えたフル機能のSQLデータベースであるにもかかわらず、軽量でファイルベースであり、スケーラブルであり、メンテナンスは不要です。同社のWebサイトによると、「おそらく1兆(1*e^12)を超えるSQLiteデータベースがアクティブに使用されているようです」。

その優れた機能に関係なく、SQLiteは設計上単一ユーザーに制限されており、Web展開での同時アクセスを目的としていません。MQL5Webサイトには、MetaTrader 5をMySQLに接続する方法に関する多数のフォーラム投稿や記事があり、他の使用例に対してより堅牢な解決策が求められていることがわかります。

この記事では、Postgresを使用したこれらの使用例向けの開発環境の設定に焦点を当てています。

Postgresを使用する理由

まず第一に、私がPostgresを選択したのは、もう1つの人気のあるオープンソースの代替手段であるMySQLについては、すでにここで詳しく説明されているからです。

第二に、Postgresは成熟したオープンソースプロジェクトであり、マルチプラットフォームであり、一貫したドキュメントがあり、非常によく保守されています。人気もあり、Web上で大量のサンプルコード、ガイド、チュートリアルを見つけることができます。あらゆるニーズと予算に合わせて利用できるクラウドプロバイダも多数あります。

Postgresはエンタープライズグレードであると同時に、ホームマシンで単独で作業する単独のユーザーでも簡単に管理できます。

そしてもちろん、私がPostgresを選択したのは、Postgresを信頼しているからです。10年以上にわたり、私はさまざまなプロジェクトでPostgresを満足して使用しています。

そして最後になりましたが、私は現在、ここで共有する解決策を個人の取引環境に実装しています。つまり、これは一種の「個人的な関与」なのです。自分が実装したものをを自分で使っているわけです。


MQL5からPostgresを操作する4つの方法

私の知る限り、MQL5からPostgresを呼び出すには主に4つの方法があります。

  1. 専用のMQL5ライブラリ/ドライバー
  2. C++クライアントインターフェイスからの.dll
  3. .NETNpgsqlドライバー経由
  4. REST API

それぞれの要件、メリット、デメリットを見てみましょう。「MQL5コミュニティ」の経験豊富な開発者の大規模なコミュニティが、私が長所では見つけることができなかった短所を指摘するだけでなく、短所に対する簡単な解決策を提供してくれると確信しています。経験の少ない開発者と、ここに来る開発者ではないトレーダーの両方が、この関連する議論から恩恵を受けられるように、MQL5コミュニティからのこのフィードバックは大歓迎です。


1.専用のMQL5ライブラリ/ドライバー

このライブラリはまだ存在しません。開発する必要がありますが、上級MQL5開発者による何時間ものハードワークが必要になります。それは決して安くはありません。維持費も考慮する必要があります。Postgresは成熟していますが、決して静的ではありません。Postgresは定期的にリリースされるアクティブなプロジェクトであり、これらのリリースのいくつかでは、多くはないにしても、クライアントコードの更新が必要になります。

たとえば、この記事の執筆時点では、Postgresの最後のバージョン(15)では、データベースの通常のユーザーに「パブリックスキーマ」でのいくつかの権限を付与する必要があります。この要件は以前のバージョンには存在しませんでした。おそらく、いくつかのコードベースでメンテナンスが必要となります。

Postgres専用のMQL5ドライバーの開発を委託する利点は、それが共有されれば、多くのMQL5ユーザーにとって役立つ可能性があることです。欠点は明らかで、時間とお金のコストがかかることです。

この方法を選択した場合の開始点:

このサイトでMySQL記事を一般検索すると、いくつかの有用なリファレンスが返されます。

オープンソースC++クライアントライブラリ

Postgresの公式Cクライアントライブラリlibpq


2. C++クライアントインターフェイスからの.dll

これは、外部で保守されている公式C++ライブラリlibpqxxで、Postgresディストリビューションに同梱され、内部で保守されている公式Cライブラリlibpqの上に構築されています。

個人的には、一度も使用したことがありませんが、言えることは、長い間そこにあり、よく維持されているようだということだけです。この方法の欠点は、MQL5マーケットではDLLが許可されていないことです。これがプロジェクトにとって問題でなくて自宅でMetaTraderの.dllを使用して作業している場合、これが解決策になる可能性があります。

この方法を選択した場合の開始点:

オープンソースのC++クライアントライブラリ 


3..NET Npgsqlドライバー経由

2018年以降、MetaTrader 5では、「スマート」関数インポートによる.NETライブラリのネイティブサポートが追加されました。プラットフォームビルド1930のリリースにより、特別なラッパーを作成しなくても.NETライブラリを使用できるようになり、MetaEditorがそれを自動的に実行します。 

.NETNpgsqlドライバーを使用するために必要なのは、.dll自体をインポートすることだけです。いくつかの制限事項については、公式リリースノート(https://www.mql5.com/ja/forum/285632)で確認できます。

この方法を選択した場合の開始点:

.NET用のオープンソースPostgresドライバー


4. REST API

「.dllなし」のパスを選択した場合、これがより高速で安価な方法になります。APIは任意の言語で作成でき、1日または数時間で動作するプロトタイプを作成できます。

それに加えて、一部のクラウドプロバイダはPostgres用の組み込みREST APIを無料で提供しています。開始するために必要なのは、MQL5コードのための適切な開発環境だけです。

このメソッドを使用すると、MQL5コードはPostgres応答をJSONとして使用できます。

この方法を選択した場合の開始点:

この記事です。読み続けて、以下の手順に従い、サンプルコードをダウンロードして、Postgresデータベースへの取引や取引の保存とクエリを開始してください。


開発環境の設定

どちらの方法を選択する場合でも、Postgresサーバが実行されているWindowsマシンの開発環境が必要になります。よく言われているように、それをおこなう方法は複数あります。最も複雑で時間がかかるものから最も単純なものまで、次の3つの方法を覚えています。

  1. ソースコードからのコンパイル
  2. Dockerコンテナ
  3. サードパーティのmsiインストーラー

それらはすべてWindows上でPostgresを実行するための良い方法ですが、ソフトウェア開発における断続的な回復力の理論と実践を学びたい場合を除いて、Windows上でソースコードからコンパイルすることは最後の選択肢です。

Dockerコンテナは非常に優れたオプションであり、データベースサーバが「ローカルホスト」ではなく「リモート」マシンで実行される堅牢かつ柔軟なインストールです(以下を参照)。結局のところ、それは簡単です。Dockerをインストールし、2~3つのコマンドラインをインストールするだけで準備は完了です。

「サードパーティ」ソフトウェアの相対的な不便さを除けば、サードパーティのmsiインストーラーは、ソースからの冒険的なコンパイルやDockerのインストールとコンテナーの管理を避けるための優れた代替手段です。

ただし、リモートマシンにあるサーバに対して開発できる場合は、データベースサーバやその他の種類のサーバの開発環境を「ローカルホスト」として使用することはお勧めしません。これは、接続設定と認証の問題をできるだけ早くトラブルシューティングするために、「ローカルホスト」ではなくリモート環境でサーバを開発、テスト、デバッグすることが常に推奨されるためです。

WSLに入ります。

WSLとは

WSLはWindows Subsystem For Linuxの略です。

見逃した方のために付け加えておきますと、2016年以降、Windowsマシン上でLinuxディストリビューションをサブシステムとして実行できるようになりました。ご心配なく。ハッキングはありません。WSLはMicrosoftによって開発され、Windowsに組み込まれています。以下で説明するように、これを有効にするだけです。

WSLを選ぶ理由

なぜ単にPostgresを別のWindowsマシン(最終的には仮想マシン)にインストールしないのでしょうか。

PostgresはUnixネイティブシステムであり、*nixシステムで作成および開発されているためです。Linuxにインストールすると、インストール、アップデート、メンテナンスが簡単になります。すべての公式ドキュメントはUnixシステムを対象としています。そして、Web上にあるサンプルコード、スニペット、および一般的なヘルプのほとんどは、この事実を反映しています。

したがって、Linuxシステムでの開発が容易になります。そして、WSLはまさにこの目的のためにMicrosoftによって開発されました。

WSLのインストール

Microsoftドキュメントの前提条件:

「以下のコマンドを使用するには、Windows10バージョン2004以降(ビルド19041以降)またはWindows11を実行している必要があります。以前のバージョンを使用している場合は、手動インストールページを参照してください。」

システムがこの前提条件を満たしている場合は、管理者としてPowerShellを開き、以下のコマンドを入力してWSLをインストール/有効にします。

wsl –install

PowerShellでのwslinstallコマンド

このコマンドは、Ubuntuがデフォルトのディストリビューションであるため、WSLにUbuntuをインストールします。 

Windowsを再起動します。

これは簡単なプロセスであるはずです。そうでない場合は、上にリンクされているMS公式ドキュメントに、最も一般的なインストールの問題に関するセクションが記載されています。

再起動後、このようなものが表示されるはずです。次に、新しいUNIXユーザー名とパスワードを作成します。

最初の再起動後のwslインストール


WSL/Ubuntuがインストールされて実行されているので、それにPostgresをインストールしましょう。

WSLにPostgresをインストールする

以下のコマンドを入力します。

sudo apt install postgresql postgresql-contrib

このコマンドは、Ubuntuリポジトリで利用可能なPostgreSQLパッケージの最後の安定バージョンをインストールします。これには、サーバ、pgsqlクライアント、便利なバイナリ、およびいくつかのユーティリティが含まれています。始めるために必要なものはすべて揃っています。

最新の安定したPostgresバージョン(通常Ubuntuリポジトリの最後の安定したバージョンとは異なります)インストールする場合は、パッケージマネージャーのソースリストに公式Postgresリポジトリを含めることができます。詳細な手順はPostgresの公式ドキュメントにあります。

何も問題がなければ、次のコマンドを入力します。

psql --version

Postgresデータベースのインストールされているバージョンを返す必要があります。


サーバを起動する

このコマンドを入力してサーバを起動します。

sudo service postgresql start

デフォルトでは、新しいPostgresインストールは「localhost」からの接続のみを受け入れます。それを変えてみましょう。

Postgres構成ファイルを見つけます。

sudo -u postgres psql -c "SHOW config_file"

postgresインストールshowconfigファイル


localhost外部の接続を受け入れるように構成ファイルを編集します。 listen_addresses行を変更します。

postgres構成listen_addresses


pg_hba構成ファイルを見つけます。

sudo -u postgres psql -c "SHOW hba_file"

postgres構成showhbaファイル


pg_hba.confファイルを編集して、IPv4とIPv6の両方でパスワードによる認証を許可します。

postgres構成pg_hbaパスワードによる認証


ここで、インストールによって作成されたデフォルトのPostgresユーザーとしてpsqlユーティリティにアクセスします。これは「postgres」という名前です。

sudo-upostgrespsql


CREATEDB権限を持つデータベースの通常ユーザーを作成します。これまで、インストールによって作成されたユーザーは「postgres」のみでした。

スキーマpublicに対するすべての権限をmt5_userに付与します。Postgresのバージョンが15未満の場合、これは必要ありません。

CREATE USER mt5_user PASSWORD '123' CREATEDB;

GRANT ALL ON SCHEMA public TO mt5_user;

postgres create user grant all privileges


データベースmy_remote_dbを作成し、そのデータベースに対するすべての権限をmt5_userに付与します。

データベースmy_remote_dbに対するすべての権限をmt5_userに付与します。

psql create db grant all privileges


Postgresに接続する

これまでに、Windowsローカルホストとは異なるIPを持つデータベースサーバがリモートマシンで実行され、ネットワーク経由の接続を受け入れる準備ができているはずです。ソケットまたはHTTP経由で接続できます。REST APIと対話することになるため、この例では後者を使用します。

WSLホストでパスワード123を使用してmt5_userとしてmy_remote_dbに接続できるかどうかを確認してみましょう。

このコマンドを入力して、WSLホスト名(IP)を取得します。

hostname -I

ubuntuターミナルコマンドhostname


Postgresサーバのステータスを確認します。ダウンしている場合は開始します。このコマンドを使用して、サーバを起動、再起動、または停止できます。

sudo service postgresql {status, start, stop}


MetaTrader5ターミナルで、[ツール]>[オプション]>[エキスパートアドバイザー]タブに移動し、許可されているもののリストにWSLホストIPを含めます。

MT5ターミナルツールオプションメニュー

MetaTrader5ターミナルは、それぞれポート80と443でのみHTTP接続とHTTPS接続を受け入れます。ポート80と443のみです。APIを開発している場合は、このセキュリティ機能を考慮する必要があります。通常、実稼働環境の実サーバに移行する前に、開発サーバは3000や5000などの非特権ポートでリッスンします。したがって、上記のターミナル設定で宣言したIPにリクエストを送信できるようにするには、開発サーバポートに到着するトラフィックをHTTPリクエストの場合はポート80、HTTPSリクエストの場合はポート443にリダイレクトする必要があります。

物事を簡単にするために、WSLでこのリダイレクトを実行する方法については、添付のPythonアプリのREADMEに記載されています。


デモアプリを起動する

この記事はMQL5に関する記事なので、API実装の詳細については説明しません。代わりに、MQL5コードとAPIのやり取りをテストするために、Pythonパッケージとしてダウンロードしてインストールできるデモアプリを作成しました。

デモアプリを開始するには、WSLにPythonがインストールされている必要があります。すでにそこにあるはずです。

アプリをインストールするには、Python仮想環境(「venv」)を作成することを強くお勧めします。これにより、システムのPythonインストールが台無しになることがなくなります。アプリで遊んだ後は、仮想環境を削除するだけです。

このコマンドで仮想環境を作成できます。

python3 -m venv 'venv'


したがって、デモアプリをインストールした後、MQL5コードの開発を開始するには、次のことをおこないます。

  1. WSLを開始する
  2. Postgresサーバを起動する
  3. デモアプリを起動する
  4. デモアプリの出力からホスト名IPを取得する
  5. ターミナルで許可されたアドレスにホスト名IPを追加する

WSLとPostgresサーバは両方とも、Windowsの起動時に開始するように構成できます。


MQL5からデータを挿入する

データを挿入してみましょう。まず、アカウント情報です。MT5ターミナルで新しいスクリプトを作成し、次のコードを追加します。

//+------------------------------------------------------------------+
//|                                                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");
        }
     }
  }

ファイルの先頭からわかるように、JSONデータをシリアル化/逆シリアル化するためにヘルパーライブラリを使用しています。これはMQL5コミュニティのメンバーによって開発されており、ライブラリはそのGitHubリポジトリで見つけることができます。

次に、MetaTrader 5履歴から取引を挿入しましょう。新しいスクリプトを作成し、次のコードを追加します。

//+------------------------------------------------------------------+
//|                                                   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");
        }
     }
  }


MQL5からデータをクエリする

次に、最近挿入されたデータをクエリしてみましょう。MetaTrader 5ターミナルで新しいスクリプトを作成し、次のコードを追加します。

//+------------------------------------------------------------------+
//|                                                 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);
     }
  }

エンドポイントを「accs」から「deals」に変更すると、挿入したばかりの取引をクエリできます。<MT5ターミナルパス>\Files\TutoPostgresを確認してください。すべてがうまくいけば、そこには少なくとも2つのファイル、accs_fromserver.jsonとdeal_fromserver.jsonが存在するはずです。 


EAでJSONデータを使用する

サーバから返されたJSONデータを使用するには、それを逆シリアル化する必要があります。前述のヘルパーライブラリはそれをおこなうことができます。

上記のコード例でデータベースにクエリを実行した後に保存されたJSONファイルを見ると、次のようなJSON文字列が表示されているかもしれません。

[
  {
    "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"
  },
  {
(...)

このキーを使用して、逆シリアル化されたデータにアクセスします。配列インデックス「0」は、返された最初のアカウントにアクセスしています。複数のアカウントがある場合、このエンドポイント(「accs」)はすべてのアカウントを返し、このインデックスによって配列を反復処理して各アカウントにアクセスできます。

//+------------------------------------------------------------------+
//|                                                 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);
     }
  }


PostgresミラーとしてのSQLite

リモートデータをローカルSQLiteデータベースとして使用することで、既存のMQL5インフラストラクチャを活用することもできます。この機能を実装するには、データベースを同期する必要があります。この同期はほぼリアルタイムでおこなわれ、遅延は数秒しかありません。ただし、これによりパフォーマンスが向上し、ネットワーク遅延が回避され、標準のMetaEditor GUIを介したデータアクセスやMQL5コードでのMQL5データベース関数の使用が可能になります。

この機能が便利だと思われる場合は、お知らせください。リモートPostgresとローカルSQLiteデータベース間のこの同期については、サンプルコードを含む詳細なチュートリアルを喜んで書きます。


結論

これらのノートでは、MQL5コードインスタンスをPostgresデータベースに接続するために現在利用可能ないくつかの方法を確認しました。より高価な専用ドライバー開発や.dllの使用に代わる、実行可能かつ高速な代替手段としてREST APIを選択しました。また、Windows Subsystem For Linux上でMQL5/Postgresの開発環境を構築する方法の例として、基本的なデモアプリを開発しました。

これで開発を開始できます。優れたクラウドプロバイダを選択し、Postgres分析、自動化、Webスケーラビリティ、機械学習拡張機能をすべて活用して取引を強化します。

MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/12308

ニューラルネットワークの実験(第5回):ニューラルネットワークに渡すための入力の正規化 ニューラルネットワークの実験(第5回):ニューラルネットワークに渡すための入力の正規化
ニューラルネットワークはトレーダーのツールキットの究極のツールです。この仮定が正しいかどうかを確認してみましょう。MetaTrader 5は、取引でニューラルネットワークを使用するための自立した媒体としてアプローチされています。簡単な説明が記載されています。
MQL5の圏論(第6回):単射的引き戻しと全射的押し出し MQL5の圏論(第6回):単射的引き戻しと全射的押し出し
圏論は、数学の多様かつ拡大を続ける分野であり、最近になってMQL5コミュニティである程度取り上げられるようになりました。この連載では、その概念と原理のいくつかを探索して考察することで、トレーダーの戦略開発におけるこの注目すべき分野の利用を促進することを目的としたオープンなライブラリを確立することを目指しています。
MQL5でJanus factorを実装する MQL5でJanus factorを実装する
ゲイリー・アンダーソンは、「Janus factor」と名付けた理論に基づく市場分析法を開発しました。この理論は、トレンドを明らかにし、市場リスクを評価するために使用できる一連の指標を記述するものです。今回は、これらのツールをMQL5で実装してみます。
MQL5を使用してローソク足パターンを検出する方法 MQL5を使用してローソク足パターンを検出する方法
MQL5によって価格のローソク足パターンを自動的に検出する方法を学ぶ新しい記事です。