MT4/MQL4とPythonの連携➀ ソケット

自動売買

MT4 (Metatrader 4)上で動くEA (Expert Advisor) は通常MQL4と呼ばれる言語で記述されます。機械学習を用いたアプローチでEAを作成する場合、既存の機械学習のライブラリやコードを用いるためにも、ロジックをPythonで記述できれば便利です。

MT5では公式にPythonとの連携機能が用意されているのですが、残念ながら国内業者での採用が多いMT4では用意されていません。そこで今回は、MT4/MQL4とPythonの連携方法について解説します。

MT4/MQL4とPythonの連携方法

MT4/MQL4からPythonのコードを実行、またはMT4/MQL4とPythonの間で情報を受け渡すにはさまざまな方法が考えられます。

  1. ソケット (この記事で解説)
  2. 名前付きパイプ
  3. ファイル
  4. 共有メモリ
  5. Pythonの埋め込み機能

第1回として本記事ではソケットを用いた方法を解説します。ソケットのメリットとしては比較的難易度が低いことと、MT4/MQL4とPythonをそれぞれ別のコンピュータ上で動作可能であることなどがあります。

全体構成

MT4でレートの取得と売買を行い、Python側では売買の判定のみを行うという構成にする場合、MT4とPythonの間で最低でも以下の3種類のデータをやりとりする必要があります。

  1. レート(MT4→Python)
  2. 売買や情報取得命令(Python→MT4)
  3. 売買や情報取得命令の結果を返す(MT4→Python)

今回は簡単のため、Python側でソケットサーバーを作成して接続を待ち受け、MT4のOnTick()のタイミングごとにPythonのソケットサーバーに接続し、データを送受信する構成をとります。

MT4の準備

まず、MT4のオプション→エキスパートアドバイザで、「WebRequestを許可するURLリスト」に「http://localhost」を追加しておきます。

Pythonの準備

Pythonのセットアップは完了しているものとします。Flask をインストールしておきます。pipの場合次のようにします。

pip install Flask

Flaskの動作確認のため、Pythonで次のコードを実行します。

# -*- coding: utf-8 -*-
from flask import Flask, request
app = Flask(__name__)

@app.route("/")
def root():
    return 'OK'

if __name__ == '__main__':
    app.run(debug=False, host='127.0.0.1', port=8080)

Webブラウザで http://localhost:8080 にアクセスし、OKと表示されたら、Flaskは正常に動いています。

MT4とPythonで通信する

Pythonで次のコードを実行します。

# -*- coding: utf-8 -*-
from flask import Flask, request
app = Flask(__name__)

prev_close = -1

@app.route("/")
def root():
    return 'OK'

@app.route("/reset")
def reset():
    global prev_close
    prev_close = -1
    return ""

@app.route("/ontick")
def ontick():
    open  = float(request.args.get('open'))
    high  = float(request.args.get('high'))
    low   = float(request.args.get('low'))
    close = float(request.args.get('close'))
    global prev_close

    if prev_close == -1:
        prev_close = close

    print(open, high, low, close, prev_close)
    prev_close = close

    return 'OK'

if __name__ == '__main__':
    app.run(debug=False, host='127.0.0.1', port=8080)

次に、MetaEditorで次の内容のEAを作成し、実行します。

void OnTick()
{
   static datetime prev_time = Time[0];
   
   // 新しい足ができていないときはなにもせずに抜ける   
   if(Time[0] == prev_time) {
      return;
   }
   
   prev_time = Time[0];

   string cookie=NULL, headers;
   char   post[], result[];
   string format = "http://localhost:8080/ontick?symbol=%s&time=%s&open=%f&high=%f&low=%f&close=%f";
   string request = StringFormat(format, Symbol(), TimeToStr(Time[0] , TIME_DATE | TIME_SECONDS), Open[0], High[0], Low[0], Close[0]);

   int response = WebRequest("GET", request, cookie, NULL, 500, post, 0, result, headers);
   if (response == -1) {
     Print("Error in WebRequest. Error code  =",GetLastError());
   } else {
      if (response == 200) {
         // サーバーから返ってきた値を表示する
         Print("Return from python: " + CharArrayToString(result));
      } else {
         PrintFormat("Request '%s' failed, error code %d", url, response);
      }
    }
}

上記のプログラムは、MT4からPythonに時刻と四本値を送信し、PythonからMT4には”OK”という文字列を返しています。こうして、MT4とPythonの間で情報をやりとりすることができます。注意点としては、実際に上記のプログラムを動かしてみるとわかるのですが、ときどきエラーで止まってしまいます。このため、実運用する際には、エラー処理なども作り込む必要があります。

次回は、名前付きパイプを利用してPythonとMT4を連携する方法を紹介します。

ゴールデンウェイジャパン(FXTF MT4)

本サイトの内容は、投資の勧誘を目的としたものではなく、本サイト内の情報に基づいて行った取引の損失について、本サイトは一切の責を負いかねます。当該情報の欠落・誤謬等につきましてもその責を負いかねますのでご了承ください。免責事項もご覧ください。

自動売買

コメント

  1. 野守 より:

    大変参考になりました。ありがとうございます。

    ただ、MetaEditorのEAの内容についてコピペではうまくいかなかった箇所があったので
    コメントに残させていただきます。
    ・14行目
    string format = “http://localhost:8080/tick?symbol=%s&time=%s&open=%f&high=%f&low=%f&close=%f”;

    URL部について、sample2.pyでは、ポートを「port=80」と定義しているため、
    http://localhost:8080ではなくhttp://localhost:80だと思われます。

    また、route以降を「tick」としていますが、sample2.pyでは、
    routeを「/ontick」と定義しているため、http://localhost:80/ontick
    だと思われます。

    pythonを使ってEAやインジケータを作るにあたり大変参考にさせていただきましたので
    差し出がましいようであれば、申し訳ございません。

    ありがとうございました。

タイトルとURLをコピーしました