MT4(MQL4) から外部プログラムにデータを渡して処理したくなることがあります。 そんなとき,Windows の名前付きパイプ(NamedPipe)を使うと比較的容易に実現できます。
「MT4(MQL4) と Python の連携 ~名前付きパイプを使ってデータを渡す~」では,MT4(MQL4) から Python で作った外部プログラムに一方的にデータを渡していましたが,今回は双方向の通信をやってみます。
プログラムの動きは以下のような流れになります。
今回は Python を使って外部プログラムを作成します。 パイプから送られてきた文字列を数値に変換し,2 倍した結果を文字列に変換して名前付きパイプに書き込むプログラムです。「倍返しだ!」
Python で Windows の名前付きパイプを扱うには,win32pipe モジュールを使います。
import win32pipe
import win32file
# 名前付きパイプの作成
pipe = win32pipe.CreateNamedPipe(
r'\\.\pipe\TestPipe',
win32pipe.PIPE_ACCESS_DUPLEX,
win32pipe. PIPE_TYPE_BYTE | win32pipe.PIPE_READMODE_BYTE | win32pipe.PIPE_WAIT,
1, 256, 256, 0, None)
# クライアントの接続を待つ
win32pipe.ConnectNamedPipe(pipe, None)
# バッファの準備
s = b''
# 無限ループ
while True:
# パイプから 1 文字読み取って
hr, c = win32file.ReadFile(pipe, 1)
# バッファに追加
s += c
# 改行文字を読んだら
if c == b'\n':
# 読み取ったデータを数値に変換して 2 倍する
x = float(s) * 2.0
# 結果を文字列に変換
res = '{0:.3f}\r\n'.format(x)
# コンソールに表示
print(res, end='')
# パイプに書き込む
win32file.WriteFile(pipe, res.encode())
# 次の準備
s = b''
MT4(MQL4) 側は EA(エキスパートアドバイザ)としてプログラムを作成します。 ティックごとに Bid 価格を文字列に変換してパイプに書き込み,外部プログラムの処理結果をパイプから読み取ってターミナルに表示するプログラムです。
MT4(MQL4) から既存のパイプに接続するには FileOpen 関数を使います。
#property strict
const string pipeName = "TestPipe"; // パイプ名。外部プログラムで作成した名前に合わせる。
int pipe = INVALID_HANDLE;
int OnInit()
{
// 名前付きパイプを開く(接続する)。
pipe = FileOpen("\\\\.\\pipe\\" + pipeName, FILE_READ | FILE_WRITE | FILE_BIN | FILE_ANSI);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
// パイプを閉じる。
FileClose(pipe);
}
// ファイルから 1 行読み取る
inline string ReadLine(int file)
{
string s;
while (1)
{
string c = FileReadString(file, 1);
s += c;
if (c == "\n") break;
}
return s;
}
void OnTick()
{
// Bid 価格を文字列に変換
string s = DoubleToString(Bid);
// 文字列をパイプに書き込む
FileWriteString(pipe, s + "\r\n");
// パイプから 1 行読み取って,ターミナルに表示
Print(ReadLine(pipe));
}
上記のプログラムを動かすときは,はじめに外部プログラムを起動して待受状態にした後,MT4 側で EA をチャートに適用します。 うまく行けば外部プログラムに以下のように処理結果が表示されます。また,MT4 のターミナルにも同じ結果が表示されます。
209.386
209.388
209.388
209.392
209.388