1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MetaTraderAdvent Calendar 2022

Day 5

C#とMetaTrader(MQL4)の連携方法その1

Posted at

目的

C#とMetaTraderでデータのやり取りをする。

データのやり取りに関する実現方法について

データのやり取りに関する実現方法については,主に3種類あると考えられます。

  1. 共有メモリを使用する方法
  2. ソケット通信による方法
  3. ファイルによる方法

恐らく3番目が一番実装しやすいのではないでしょうか。
ただし,3番目の場合,ファイルアクセスのルールを決めないといけないため,少しコードの工夫が必要です。

本稿では,ソケット通信による実装方法について検討したいと思います。

ソケット通信によるC#とMetaTraderの連携方法について

ソケット通信による方法では,C#に限らすPythonなどでも実装可能なので,少し応用の幅が広いと思います。

データのやり取りに関しては次のように考えます。

image.png

C#からの要求に対しては,MetaTraderでは常に決まったポートで待ち受けるようにします。
MetaTraderからの要求に対しても,常に決まったポートで待ち受けるようにします。

これを行うことで,C#からの要求がMetaTraderからの要求とぶつからないようにすることができます。

実装時は,データをやりとりできることをしか検証していないため同じポートでやりました。

コード

C#側

        private void connect_ClickAsync(object sender, EventArgs e)//ボタン割り当て
        {
            ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());

            foreach (IPAddress ip in ipHostInfo.AddressList)
            {
                Console.WriteLine(ip.ToString());
                if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {

                    ipAddress = ip;
                    //break;
                }
            }
            //ipAddress = ipHostInfo.AddressList[0];
            ipAddress = IPAddress.Parse("127.0.0.1");
            Task task = Task.Run(async () => { await SocketServer(); });

            //接続が成功したら
            //disconnect.Enabled = true;
            //connect.Enabled = false;
        }



        public async Task SocketServer()//受信用のサーバを立ち上げる
        {
            //ここからIPアドレスやポートの設定
            // 着信データ用のデータバッファー。
            byte[] bytes = new byte[1024];

            await Task.Run(() =>
            {
                try
                {

                    Regex reg = new Regex("\0");
                    if (server == null)
                    {
                        //指定IP 指定ポートでサーバを起動
                        server = new TcpListener(new IPEndPoint(ipAddress, port));
                    }
                    server.Start();
                    while (startFlg)
                    {
                        if (!startFlg)
                        {
                            server.Stop();
                            break;
                        }

                        using (TcpClient tcpClient = server.AcceptTcpClient())
                        using (Stream stream = tcpClient.GetStream())
                        {
                            int i = 0;
                            while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                            {
                                string data1 = reg.Replace(Encoding.UTF8.GetString(bytes), "");



                                // 任意の処理
                                //データの受取をReceiveで行う。
                                //int bytesRec = handler.Receive(bytes);
                                //string data1 = Encoding.UTF8.GetString(bytes, 0, bytesRec);
                                if (data1.Length > 0)
                                {
                                    Console.WriteLine("data1の数:" + data1.Length);
                                    Console.WriteLine(data1);

                                    String[] sep = { "," };
                                    String[] sba = data1.Split(sep, StringSplitOptions.RemoveEmptyEntries);

                                    if (this.InvokeRequired)
                                    {
                                        //別スレッドによるUI操作
                                        this.Invoke((MethodInvoker)(() =>
                                        {
                                            bidTbx.Text = sba[1];
                                            askTbx.Text = sba[2];
                                        }));
                                    }
                                    else
                                    {
                                        //UIスレッドからのUI操作
                                        bidTbx.Text = sba[1];
                                        askTbx.Text = sba[2];
                                    }




                                    //大文字に変更
                                    data1 = data1.ToUpper();

                                    //クライアントにSendで返す。
                                    byte[] msg = Encoding.UTF8.GetBytes(data1);
                                    stream.Write(msg, 0, msg.Length);
                                    Array.Clear(bytes, 0, bytes.Length);
                                }
                            }
                        }

                        // break;
                    }
                }
                catch (Exception ex)

                {
                    Console.WriteLine(ex.ToString());
                }

            });

        }
        public static void SocketClient(string st)//クライアント側(C#からMetaTraderにアクセスするとき)
        {
            //IPアドレスやポートを設定している。
            IPHostEntry ipHostInfo1 = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress ipAddress1 = ipHostInfo1.AddressList[0];

            foreach (IPAddress ip in ipHostInfo1.AddressList)
            {
                if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {
                    ipAddress1 = ip;
                    break;
                }
            }

            ipAddress1 = IPAddress.Parse("127.0.0.1");

            IPEndPoint remoteEP = new IPEndPoint(ipAddress1, 4545);

            //ソケットを作成
            Socket socket = new Socket(ipAddress1.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            //接続する。失敗するとエラーで落ちる。
            socket.Connect(remoteEP);

            //Sendで送信している。
            byte[] msg = Encoding.UTF8.GetBytes(st + "<EOF>");
            socket.Send(msg);

            //Receiveで受信している。
            byte[] bytes = new byte[1024];
            int bytesRec = socket.Receive(bytes);
            string data1 = Encoding.UTF8.GetString(bytes, 0, bytesRec);
            Console.WriteLine(data1);

            //ソケットを終了している。
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
        }

MetaTrader側でどう受け取るかにもよりますが,


   SocketClient("buy,141.25,,,OK");

といった具合に要求することを考えています。

MQL4

MQL4側は,ここを参考にしながら実装していければと思います。

完成品

一応置いておきますが,共有メモリでの実装に移行している関係で,正しく動きません!

REFERENCEs

さいごに

投資は自己責任!

カレンダー参加者募集してます!

Have a good MQL Life!!!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?