English Русский 中文 Español Português
preview
市場シミュレーション(第7回):ソケット(I)

市場シミュレーション(第7回):ソケット(I)

MetaTrader 5 |
28 0
Daniel Jose
Daniel Jose

はじめに

前回の「市場シミュレーション(第6回):MetaTrader 5からExcelへの情報の転送」では、シンプルな手段と純粋なMQL5のみを用いて、MetaTrader 5からExcelへクオートデータを転送する方法を説明しました。もちろん、これはできるだけ教育的であることを目的とした非常に基本的な例に過ぎませんでした。ただし、その際に、クオートの更新がリアルタイムではおこなわれていなかったことに気付いた方もいるかもしれません。それでも、前回の記事で示した知識は、実際に今後必要となる別の重要な点を示すことを目的としていました。

とはいえ、同じ結果を得るための方法はいくつも存在し、私たちにとって本当に重要なのは常に結果です。そのため、MetaTrader 5からExcelのような外部プログラムへデータを転送する簡単な方法が確かに存在することを、改めて示したかったのです。ただし、本来の主な目的は、MetaTrader 5からExcelへデータを送ることではなく、その逆、つまりExcelやその他のプログラムからMetaTrader 5へデータを転送することにあります。

これを実現する方法はいくつもあります。非常にシンプルなものもあれば、より複雑なものもあります。リアルタイムで処理できる方法もあれば、わずかな遅延が発生する方法もあります。しかし重要なのは、外部データを使ってMetaTrader 5、あるいはその内部で動作する何らかのアプリケーションを制御できるかどうかという点です。この問いは一見すると些細なものに見えるかもしれませんが、実際には非常に重要な可能性を秘めています。たとえば、特定の分析や研究に特化した外部プログラムを用いて検証をおこなうことができます。価格やクオートに基づく注目ポイントを定義し、そのデータを、アプリケーション(エキスパートアドバイザー(EA)、サービス、スクリプト、あるいはインジケーター)が利用できる場所に配置することも可能です。これにより、チャート上に直接シグナルを表示したり、EAの場合には意思決定を支援したりすることができます。

ここから先、何ができるか、どこまで発展させられるかは、あなたの想像力と関心の度合い次第です。しかし、実際にリプレイ/シミュレーターに必要なものを開発する前に、もう一つ別の重要な点をお見せしたいと思います。そのためには、これらの概念や考え方、そして可能性を事前に提示しておく必要があります。そうすることで、後に開発・実装される内容を正しく理解し、これらの知識を最大限に活用できるようになるからです。

本記事で紹介する内容は、前回扱ったテーマをさらに一歩進めたものです。先ほど述べたように、以前に示した方法ではデータをリアルタイムで送信することができませんでした。リプレイ/シミュレーターにおいてはそれでも十分ですが、リアルタイムで情報を取得したい場合には、この方法では要件を満たせないのです。


概念の理解

前回の記事でも述べたように、RTDやDDEを使用しても、MetaTrader 5と外部プログラムとの間で双方向通信が保証されるわけではありません。しかし、RTDやDDEで用いられている考え方そのものは、私たちが求めている双方向通信を実現できる形で応用することが可能です。そのためには、これまでおこなってきた方法とは少し異なるアプローチを取る必要があります。これまでの開発段階では、すべて純粋なMQL5のみを用いてきましたが、純粋なMQL5だけでは本当に十分ではない場合も存在します。それは、MQL5にできないことが原因ではなく、外部プログラムが補助なしでは実行できないことがあるためです。その問題は、最終的に1つの要素に行き着きます。それがソケットです

ソケットはコンピューティングの世界に深く根付いた仕組みです。もしソケットとは何か、あるいは何のために使われるのかをご存じでない場合、特に特定の種類のソリューションを扱う予定があるのであれば、ぜひ調べてみることをお勧めします。ソケットを使用することで、非常に高い自由度が得られます。本記事では、このテーマを深く掘り下げることはしません。なぜなら、ソケットは非常に広範で、多くの可能性を持ち、本格的に扱うには慎重な学習が必要だからです。ただし、これから何をおこなうのか、そして何が起きているのかを理解できるように、簡単な説明はおこないます。


TCPプロトコル

まず理解しておくべきことは、ソケットには非常に多くの種類があり、それぞれ異なる目的を持っているという点です。その中でも最も一般的なのが、ストリームソケットとデータグラムソケットです。ストリームタイプはフローソケットとも呼ばれ、信頼性のある双方向通信に広く使用されています。ここで言う信頼性とは、情報が確実に受信されているかどうかが常に確認されるという意味です。ストリームソケットは、一般にTCPとして知られるTransmission Control Protocolを使用します。

このタイプのソケットには、もう1つ重要な特徴があります。それは、データパケットが常に決められた順序で到着するよう設計されている点です。つまり、情報は連続したリストのように転送され、パケットは送信された順番通りに届きます。このことから、どのような用途で使われるかは明確です。たとえば、リモートアプリケーションの制御のように、通信中にデータが失われることが許されず、確実な受信が求められる場面です。ただし、その代償として、このプロトコルは実用上やや低速になります。一般的な構造は図01に示されるような形になります。

図01

しかし、プログラミングの観点で本当に重要なのは別の点です。それは、このプロトコルがどのように選択され、作成するコードの中でどのように実装されるかという点です。TCPを使用する場合、WindowsとLinuxではコード構造に小さな違いがあります。ただし、そのような違いが通信そのものに影響を与えることはありません。つまり、WindowsアプリケーションとLinuxアプリケーションはTCPを介して問題なく通信でき、互いに完全に理解し合うことができます。もちろん、通信ルールが正しく守られていることが前提です。この点は、次に説明するプロトコルについても同様です。


UDPプロトコル

ストリームタイプを理解したところで、次にデータグラムタイプについて見ていきます。データグラムソケットは、ストリームやTCPソケットとは完全に異なります。これは、データグラムソケットが単方向かつ非信頼的な通信を目的としているためです。では、単方向で非信頼的な通信とはどういう意味でしょうか。順を追って説明します。

まず、このソケットはUDPと呼ばれるプロトコルを使用します。このプロトコルは、実際の接続を確立するものではなく、単にデータを送信するための仕組みです。理解を助けるために、手紙を書く状況を想像してみてください。手紙を投函した後、それが実際に相手に届くのか、いつ届くのかは分かりません。

さらに状況は複雑になります。手紙を送った後で、いくつかの重要な点を書き忘れたことに気付き、もう一通手紙を書くとします。このようなことは何度も起こり得ますが、それぞれの手紙は独立して送られます。

ここで重要な点があります。郵便システムが正常に機能し、どの手紙も失われなかったとしても、受取人はそれらを同時に受け取るかもしれませんし、送った順番通りに受け取るかもしれませんし、まったくランダムな順序で受け取るかもしれません。

受信者として、その内容を理解するためにどれほどの作業が必要になるかを想像してみてください。また、送信者の立場で返答を期待していた場合、相手が本当に手紙を受け取ったのか、あるいは理解したのかを保証する手段はありません。このような理由から、UDPプロトコルは単方向かつ非信頼的であるとされています。しかし、そのように聞こえるにもかかわらず、UDPは非常に有用です。

たとえば、データの探索やプロービングのように、順序や完全性がそれほど重要ではない状況があります。多少のデータが失われても、全体の傾向を把握するには十分な場合です。

典型的な例としては、ビデオ通話や音声通話が挙げられます。これらでは、正確性よりも速度が優先されます。また、リモートプローブやセンサーのように、特定の状態を確認できれば十分な用途にも適しています。このような場合、すべてのデータが届いたことを確認する必要はなく、分析に十分な量のデータが届けば問題ありません。このプロトコルは、通常、図02に示されるような構造を持ちます。

図02

この説明が、皆さんの好奇心を刺激し、より深くこのテーマを探求するきっかけになれば幸いです。実際、この分野は非常に広く、興味深いものです。MQL5コミュニティの中でも、記事やフォーラムの議論を通じて、多くの参考資料を見つけることができます。いずれにしても、このテーマは非常に奥が深いものです。ここでの簡単な導入は、これから何をおこなうのかを理解するための助けとなることを目的としています。


小規模なシステムのプログラミング

ここで少し補足が必要です。これからおこなう内容を示すためには、非常にシンプルなコードを使用する必要があります。MQL5自体では直接サーバーを作成することができないため、今回はMQL5を使ってクライアント側を作成します。つまり、クライアント–サーバーモデルを構築することになります。サーバー側は外部のプログラミング言語を使って作成します。この場合、ネットワークサーバーをサポートする任意の言語やプラットフォームを使って作ることができます。しかし、ポート番号やプロトコルの種類など、注意すべき重要な点があります。できるだけ簡単にするために、今回はWeb上で公開されているコードを直接学習できる形で使用します。言い換えれば、Microsoftのウェブサイトで公開されているサーバーコード(Servidor WinSock)を利用します。

記事の最後でも、この参考リンクを再度提示し、サーバーコードだけでなくクライアント側についても同じページで説明されている内容をステップごとに学べるようにします。

重要な注意:ここで参照しているサーバーは非常にシンプルなモデルです。サーバーは1つの接続しか受け付けず、送られてきたデータを受信するとすぐに接続を閉じます。そのため、別の接続を受け取ることはできません。サーバーは、クライアントから送られたデータをそのまま返す「エコーサーバー」として機能し、デモンストレーションのみを目的としています。

しかし、クライアントについては少し異なる方法を取ります。MQL5で直接クライアントを作成し、サイトで提供されているC/C++のクライアントコードは使用しません。これにより、通信がどのように機能しているかを理解することができます。なお、MetaTrader 5自体をサーバー化することも可能ですが、その場合はDLLを使用する必要があります。現時点では、そのようなリソースは導入しません。少なくとも、まだ導入しません。

では、作業を始めましょう。サーバーは前述のコードを使用しても、自分で任意の言語やプラットフォームで作成しても構いません。ここでの目的は、できるだけシンプルな控えめなシステムを構築し、通信の仕組みを理解するきっかけとすることです。サーバーがコンパイルされて起動したら、次にMQL5側の作業に進みます。そのためにMetaEditorを開き、純粋なMQL5でクライアントを作成してください。


MetaTrader側の実行

ローカルサーバーとの接続を確立する前に、接続を実際にどのようにおこなうかを理解する必要があります。MetaTrader 5は、デフォルトの設定では取引サーバー以外への接続を許可していません。これはセキュリティ上の措置であり、理解し受け入れる必要があります。MetaTraderのようなプラットフォームが任意のアドレスに自由に接続できることは適切ではありません。そのため、MetaTraderが接続を許可する前に、いくつかの小さな手順を踏む必要があります。

非常にシンプルに説明するために、MQL5の公式ドキュメントにある例を使用します。以下のコードは私のものではなく、公式ドキュメントの「SocketCreate」の項目からの引用です。ソースコードはドキュメントに記載されている通りです。

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. //+------------------------------------------------------------------+

MQL5ドキュメントのソースコード

このコードは、MetaTrader 5での接続操作と設定の方法を説明するのに最適です。非常にシンプルであるだけでなく、リモートアクセスの可能性も示しています。つまり、実際にWebページにアクセスする例です。ネットワークプログラミングの経験がある読者であれば、このコードは容易に理解できるでしょう。しかし、ここで示す概念のいくつかを後で理解する必要があるため、この主題について何も知らない方のために簡単に説明します。

このコードはスクリプトであり、スクリプトとしてコンパイルする必要があります。インジケーター内でソケットを使用することはできません。詳細はドキュメントを参照してください。それでは、このコードがどのように動作するのかを見ていきましょう。12行目ではアクセスするウェブサイトを指定しています。13行目では使用するポートを指定しています。具体的には、HTTPリクエストに応答するポートです。つまり、Webサーバーです。各ポートの挙動についてはドキュメントを参照してください。

コードの実行が開始されると(71行目)、最初におこなうのはソケットの作成です(73行目)。ここまでの内容は非常にシンプルです。しかし、作成されたソケットが有効かどうかを確認する必要があります(75行目)。78行目では、12行目と13行目で指定したサーバーとポートへの接続を試みます。接続に失敗した場合、下の画像のような状況が表示されます。

図03

接続できないのは、MetaTrader 5が接続をブロックしているためです。接続を有効にするには、CTRL + Oを押して、許可アドレスリストに例外を追加します。

図04

変更をおこなった後、スクリプトを再実行すると、下の画像のように接続が成功します。

図05

読者の皆さん、これはコードの小さな変更によるものです。では、どのようにしてWebサーバーから情報を取得できたのでしょうか。WebRequestを呼ぶ必要はなかったのでしょうか。実際には必ずしも必要ではありません。WebRequest呼び出しは、ほぼ同じことをおこないますが、もう少し高レベルでおこなわれます。WebRequestはソケットの上に抽象化を作るためです。したがって、どちらの方法でも結果は同じです。WebRequest関数については過去の記事で詳しく解説しています。以下を参照してください。

これらの記事でおこなったことは、ソケットを直接使用しても実現可能です。ただし、同じ結果を得るには少し多めのコードを書く必要があります。では、この記事でのシステムに戻ります。前のセクションで示したサーバーコードをコンパイルした後、スクリプトを実行する前にサーバーを起動しておく必要があります。任意の言語で独自のサーバーを作成して構いません。今のところの唯一の要件は、サーバーが受信したデータをクライアントに返すことです。これにより、後で説明する動作を得ることができます。

次に、MQL5で作成するクライアントのコードを見てみましょう。

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. //+------------------------------------------------------------------+

デモコード

このコードをMetaTrader 5で動作させる前に、いくつかのポイントを理解しておきましょう。まず重要なのは6行目です。この行でサーバーの場所を指定しています。この例では、MetaTrader 5と同じマシン上にサーバーがあることを指定しています。7行目ではサーバーのポートを指定しています。このポートはサーバーコードで定義したものと同じである必要があります。だからこそ、公開されている明確に説明されたコードを参照したのです。疑問がある場合は、ウェブサイトのドキュメントを参照してください。記事の最後にも再度リンクを掲載します。

基本的に、このMQL5スクリプト内の関数はほとんどが内容から理解できます。疑問があれば、ドキュメントを読むことで詳細を理解できます。ただし、少し不明瞭で説明が必要な部分があります。

28行目のループに注目してください。このループはサーバーがソケットに送信したデータを読み取るためのものです。しかし、なぜループを使うのでしょうか。ソケットを1回読むだけでは十分ではないのでしょうか。一見奇妙に思えるかもしれませんが、理由があります。ソケットに送信されたデータがどのように届くかは分かりません。届くことだけは分かっています。情報は1つのパケットで届くかもしれませんし、短いメッセージでも複数の小さなパケットに分割されることがあります。

多くのソケットプログラミング初心者がここでつまずきます。情報は1つのブロックで届くと仮定してしまうからです。しかし実際には、多くのブロックやパケットに分かれて届くことがあります。事前にこれを知る方法はあるのでしょうか。現実には、簡単な方法はありません。TCPを使用している場合、送信データは受信されると期待できますが、情報は通常パケット単位で受信されます。

理解を深めるために55行目を見てください。ここで9行目の関数を呼び出し、ソケットに送信する情報を取得しています。15行目で送信するメッセージを定義し、16行目で送信しています。サーバーがこのメッセージをどのように受信するか、何パケットに分割されるかは制御できません。システムが自動で処理します。

次に57行目で、サーバーが返した内容を読み取ります。注意してください。ここで読んでいるのは自分が送信したデータではなく、サーバーが返したデータです。今回使用するサーバーはエコーサーバーなので、送信したメッセージがそのまま返されます。これは、サーバーに対するPINGのようなものです。

送信の方法を制御できないのと同様に、サーバーが何パケットで返すかも分かりません。したがって、28行目のループを外して31行目だけを実行し、33行目でサーバーのレスポンスを文字列に変換すると、メッセージが分割されて欠けたように見える場合があります。しかし、メッセージが短い場合は、正常に届くこともあります。このような挙動が、多くの人が理解できない点です。

これは混乱を招き、非効率に感じられるかもしれません。何の役にも立たないと思われるかもしれません。しかし、ここで強調しておきたいことがあります。サーバー側のコードと、MetaTrader 5で実行されるクライアント側のコードの両方がどのように動作するかを理解すれば、非常に多くのことを実現できることに気づくでしょう。

しかし、このスクリプトを実行する前に、MetaTrader 5に使用するアドレスが許可されていることを知らせる必要があります。つまり、6行目で指定した値がMetaTrader 5の「許可されたアドレスリスト」に含まれている必要があります。リストは下の図のようになっているはずです。

図06

この変更がおこなわれた後で、両方のプログラムを実行できます。特に、複数のプロセスを同時に実行したことがない場合に備え、ローカルで両方のプログラムをテストする方法を示す動画も用意されています。この動画の目的は、特定のツールを宣伝することではなく、複数のワークスレッドでプログラムを実行し、開発を大きな困難なしにおこなえることを、初めての人にも示すことです。




最終的な考察

この記事では、MetaTrader 5で使用できる最も複雑な概念のひとつである「ソケット」について、簡単な導入をおこないました。この記事の目的は、MetaTrader 5内でソケットを使用するための基本を説明し、少なくともいくつかの必要かつ重要な概念を理解できるようにすることです。ここで紹介した内容は非常に基本的なものですが、ソケットとその応用を学びたい人にとっては不可欠な知識です。

しかし、今回おこなったのはサーバーへのエコー送信だけなので、実際にどれだけのことが可能かは完全には明確ではないかもしれません。その理解を助けるために、次の記事ではより精巧なシステムを構築します。このソケットの概念は、リプレイ/シミュレーターシステムの品質を大幅に向上させます。なぜなら、まだ実装する必要のある追加機能、たとえば注文システムなどがあるからです。そして、私はこれをより高度な方法で構築することを真剣に検討しています。しかし、読者の皆さんがこれからプログラムされる内容を本当に理解するためには、ここで示した小さな概念を理解しておくことが必要です。

プログラミングを学ぶ上で、深く学ぶべき対象が1つあるとすれば、それは「ソケット」です。ソケットの分野では、決して十分に知っているとは言えません。そして、すべてを探索したと思った瞬間でも、必ずまだ学ぶべきことが残っていることに気づくでしょう。次の記事もぜひお読みください。ソケットに関して、とても興味深く、かつ実装が簡単な内容を紹介します。


リンク

Microsoft WinSockドキュメント

ポート番号のリスト

ファイル 説明
Experts\Expert Advisor.mq5
Chart TradeとEAの連携を示す(Mouse Studyが必要)
Indicators\Chart Trade.mq5 送信する注文を構成するためのウィンドウを作成する(Mouse Studyが必要)
Indicators\Market Replay.mq5 リプレイ/シミュレーターサービスと対話するためのコントロールを作成する(Mouse Studyが必要)
Indicators\Mouse Study.mq5 グラフィカルコントロールとユーザー間のインタラクションを実現する(リプレイ/シミュレーターおよび実取引の両方で必須)
Servicios\Market Replay.mq5 マーケットリプレイおよびシミュレーションサービスを生成し、維持する(システム全体のメインファイル)
VS C++ Server.cpp C++でソケットサーバーを作成および管理する(ミニチャット版)
Python code Server.py MetaTrader 5とExcel間の通信用のPythonソケットを作成および維持する
ScriptsCheckSocket.mq5 外部ソケットとの接続を確認する
Indicators\Mini Chat.mq5 インジケーターとしてミニチャットを実装する(サーバーが必要)
Experts\Mini Chat.mq5 ミニチャットをEAとして実装する(サーバーが必要)

MetaQuotes Ltdによりポルトガル語から翻訳されました。
元の記事: https://www.mql5.com/pt/articles/12621

添付されたファイル |
Anexo.zip (550.91 KB)
Anexo.zip (560.03 KB)
EAのサンプル EAのサンプル
一般的なMACDを使ったEAを例として、MQL4開発の原則を紹介します。
ロイヤルフラッシュ最適化(RFO) ロイヤルフラッシュ最適化(RFO)
オリジナルの「ロイヤルフラッシュ最適化」アルゴリズムは、最適化問題を解決するための新しいアプローチを提示しています。この手法では、遺伝的アルゴリズムで一般的に用いられる古典的な二進符号化を、ポーカーの原理に着想を得たセクターベースのアプローチに置き換えています。RFOは、基本原理を単純化することで、効率的かつ実用的な最適化手法が実現できることを示しています。本記事では、アルゴリズムの詳細な解析とテスト結果を紹介します。
エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法 エラー 146 (「トレードコンテキスト ビジー」) と、その対処方法
この記事では、MT4において複数のEAの衝突をさける方法を扱います。ターミナルの操作、MQL4の基本的な使い方がわかる人にとって、役に立つでしょう。
取引におけるニューラルネットワーク:階層型ダブルタワーTransformer(最終回) 取引におけるニューラルネットワーク:階層型ダブルタワーTransformer(最終回)
複雑な多変量時系列の分析および予測を目的に設計された、Hidformer階層型ダブルタワーTransformerモデルの構築を引き続き進めます。本記事では、これまでに着手した作業を論理的な結論へと導き、実際の履歴データを用いてモデルを検証します。