2019年6月8日土曜日

MetaTrader を複数起動してストラテジーテスターを行う方法

MetaTrader は /portable オプションを付けることで、フォルダ単位に起動することができます。 つまり、フォルダをコピーすれば複数の MetaTrader を同時起動することができるということです。

しかし、都度フォルダをコピーするのは大変1。 そこで、MetaTrader を簡単に複数起動することができるスクリプトを作ってみました。

Windows のジャンクション機能を使っているので、普通にコピーするより速く起動します。

terminal_for_tester.js を作成

metatrader.exe と同じフォルダに 以下のスクリプトを置きます。

terminal_for_tester.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
var shell = WScript.CreateObject('WScript.Shell');
var fso = WScript.CreateObject('Scripting.FileSystemObject');
 
// Create temporary folder
var tmpFolder = fso.GetSpecialFolder(2) + '\\' + fso.GetTempName();
fso.CreateFolder(tmpFolder);
 
// Make junctions of subfolders except 'tester'
{
  var enuFolders = new Enumerator(fso.GetFolder('.').SubFolders)
  for (; !enuFolders.atEnd(); enuFolders.moveNext()) {
    var folder = enuFolders.item();
    if (folder.Name == 'tester') continue;
    shell.Run('cmd.exe /c mklink /j ' + tmpFolder + '\\' + folder.Name + ' ' + folder, 0);
  }
}
 
// Create 'tester\files' folder
fso.CreateFolder(tmpFolder + '\\tester');
fso.CreateFolder(tmpFolder + '\\tester\\files');
 
// Copy exe file
var SRC_FILE = 'terminal.exe';
var DST_FILE = tmpFolder + '\\' + SRC_FILE;
fso.CopyFile(SRC_FILE, DST_FILE);
 
shell.Run('cmd.exe /c start /wait "' + tmpFolder + '" "' + DST_FILE + '" /portable', 0, true);
 
// Delete temporary dir
{
  fso.DeleteFolder(tmpFolder + '\\tester', false);
  // Unlink the junctions
  var enuFolders = new Enumerator(fso.GetFolder(tmpFolder).SubFolders)
  for (; !enuFolders.atEnd(); enuFolders.moveNext()) {
      var folder = enuFolders.item();
      shell.Run('cmd.exe /c rmdir ' + folder, 0, true);
  }
  // Make sure that the unlinking has been completed
  do {
    WScript.Sleep(100);
    var subFolders = fso.GetFolder(tmpFolder).SubFolders
  } while (subFolders.Count != 0);
  fso.DeleteFolder(tmpFolder, false);
}

WSH (JScript) なので複雑に見えますが2、やっていることは単純です。 一時フォルダを作成し、その中に tester フォルダ以外のジャンクションをはります。その後、terminal.exe をコピーして実行するだけです。

起動後の一時フォルダ削除が少々複雑ですが、ジャンクション削除のお作法です。

なお、terminal.exe は勝手にアップデート問題があるため、コピーにしています3

参考

MetaTrader 4 は勝手に再起動してアップデートすることがある | Strategy of C

起動

terminal_for_tester.js をダブルクリックで起動。何個でも起動します。

あえてアイコンはコピーしていません。 デフォルトのアイコンになるので、区別しやすいかと思います。

注意点

使用上の注意点がいくつかあります。

history フォルダはバックアップしておいた方がよい

history フォルダを共有しているので、複数のプロセスから書き込みが行われると不整合が起こる可能性があります。 基本的には terminal.exe の終了時に上書きが走るようなので、同時に閉じないようにすれば大丈夫な気がしていますが、確かではありません。

私はオフラインにして履歴が更新されないようにしていますが、そこまではしなくても良いかもしれません。

tester\files フォルダは消えてしまう

実行しているフォルダは MetaTrader の実行が終わると削除されてしまいます。同時に tester\files フォルダも消えてしまいます。 結果をファイルに出力する等している場合、別フォルダに移動する必要があります4

同時に実行する数に注意

CPU のコア数までは複数起動してもあまりパフォーマンスには影響しないでしょう5。 論理プロセッサ数を超えるとパフォーマンスは下がっていくと思いますが、倍くらいまでならそれなりに動くのではないかと思います。 参考にして下さい。

余談ですが、CPU の情報は「タスクマネージャー」で見ることができます。

タスクバー右クリック → タスクマネージャー

パフォーマンスタブの CPU

  1. そして、history が大きくなると時間がかかる 
  2. なぜ WSH にしたかというと、ダブルクリックでスマートに起動したかったからだけ 
  3. /skipupdate というオプションもありますが、最近のものでは動作していない気がする 
  4. それをスクリプトに書いてもいいかもしれない 
  5. ストレージへのアクセス時は若干遅くなるはず 
?