MetaTrader 5をダウンロードする
MQL5 リファレンスMQL5 プログラム取引ストラテジーのテスト 

取引ストラテジーのテスト

自動売買のアイディアは、取引ロボットが四六時中ノンストップで働くことが出来るという事実によって魅力的です。ロボットは、心理的な問題から完全に解放されており、疲れたり、疑問を持ったり怖がったりしません。取引ルールを定式化してアルゴリズムで実装すれば、ロボットはたゆまず努力する準備ができています。しかし、初めに次の 2 つの重要な条件が満たされていることを確認する必要があります。

  • エキスパートアドバイザーは取引システムの規則に従って取引操作を行う
  • EA に実装された取引ストラテジーが履歴的に利益を示している

これらの質問に答えるためには MetaTrader 5 のクライアント端末に含まれるストラテジーテスターが使用されます。

このセクションでは、ストラテジーテスターでのプログラムのテストと最適化の機能について説明します。

 

ストラテジーテスターーでの機能の制限

クライアント端末のストラテジーテスターの一部の関数には操作上の制限があります。

Print() 及び PrintFormat() 関数

パフォーマンス向上のため、Print() 及び PrintFormat() 関数は取引ロボットパラメータの最適化の際には実行されません。例外は OnInit() ハンドラでのこれらの関数の使用です。これによって、エラーが発生した時に簡単に原因を見つけることが出来ます

Alert()、MessageBox()、PlaySound()、SendFTP、SendMail()、SendNotification()、及び WebRequest() 関数

「外部世界」との相互作用のために設計されたAlert()MessageBox()PlaySound()SendFTP()SendMail()SendNotification() 及び WebRequest() 関数はストラテジーテスターでは実行されません。

 

ティック生成モード

エキスパートアドバイザーは MQL5 で書かれた、外部のイベント対応するたびに実行されるプログラムです。エキスパートアドバイザーは事前定義されたイベントの 1 つに対応する関数(イベントハンドラ)を持っています。

NewTick イベント(価格変更)はエキスパートアドバイザーの主要なイベントなので、エキスパートアドバイザーのテストは連続してティックを作成することが必要です。MetaTrader 5 クライアント端末のストラテジーテスターには 3 つのティック生成のモードがあります。

  • 全ティック
  • 1 分足 OHLC(1 分足を持ったOHLC 価格)
  • 始値のみ

基本的で最も詳細なものは「全ティック」モードで、他の 2 つのモードは基本的なものを単純化したもので、「全ティック」モードに比較して説明されます。それらの違いを理解するために全ての 3 つのモードを考えてみましょう。

「全ティック」

金融商品の履歴相場データは、パックされた 1 分足の形で MetaTrader 5 クライアント端末に取引サーバから転送されます。リクエストの発生及び必要な時間フレームの構成に関する詳細な情報は MQL5 リフェレンスのデータアクセスの整理チャプターで取得出来ます。

価格履歴の最小要素は1 分足で、価格の 4 値の情報を得ることが出来ます。

  • 始値 - 1 分足が開かれた時の価格
  • 高値 - 1 分足の間に達成された最大値
  • 安値 - 1 分足の間に達成された最小値
  • 終値 - 1 分足の終値

新しい1 分足は、新しい分が始まる(秒数が 0 に等しくなる)瞬間ではなく、価格が少なくても 1 ポイントによって変動しティックが発生した時に開かれます。この図は、2011年1月10日午前零時零分のオープン時間を持つ新たな取引週の最初の1 分足を示します。為替レートは、着信ニュースに反応して週末にでも変動するため、チャート上の金曜日と月曜日との間の価格差は一般的です。

金曜日と月曜日との価格差

1 分足が 2011 年 1 月 10 日午前 0 時 0 分に開かれたことは分かっていますが、秒については何も分かりません。0 時 0 分 12秒 または 0 時 0 分 36秒(新しい日の始まりから 12 または 36 秒後)またはその分内のどの秒に開いたかもしれません。しかし新しい1 分足が開いた時に EURUSD の始値が 1.28940 であったことは分かります。

また、1 分足の終値に対応する2 番目のティックが受信された秒も分かりません。分かっているのは1 分足の最後の終値だけです。この分では、その価格は 1.28958 でした。高値と安値の出現時刻も不明ですが、値がそれぞれ 1.28958 と 1.28940 のレベルにあったことは分かります。

取引ストラテジーのテストには、エキスパートアドバイザーの作業をシミュレートする連続したティックが必要です。全ての1 分足での、価格が間違いなく位置した4制御点の場所は分かっています。足にティックが 4 つある場合、テスト実行には充分な情報ですが、ティックボリュームは通常 4 以上です。

従って、始値、高値、安値及び終値の間に発生したティックの追加制御点を生成する必要があります。「全ティック」の原則は、The Algorithm of Ticks’ Generation within the Strategy Tester of the MetaTrader 5 Terminalに記述されており、下に図が引用されています。

ティック生成アルゴリズム

「全ティック」モードのテストでは、エキスパートアドバイザーの OnTick() が全ての制御点で呼ばれます。各制御点は、生成されたシーケンスからのティックです。エキスパートアドバイザーは、オンラインで作業する場合と同じように、シミュレートされたティックの時間と価格を受信します。

重要事項:「全ティック」テストモードは一番正確ですが、同時に一番時間がかかります。大部分の取引ストラテジーの初期テストとしては、通常、他の 2 つのテストモードのいずれかを使用することで充分です。

「1 分足 OHLC」

3 つのモードのうちで「全ティック」モードは一番正確ですが、同時に一番低速です。ティックボリュームは非常に多くなりえるのですが、OnTick() ハンドラは全てのティックで起こります。足全体での価格変動のティックシーケンスが重要ではないストラテジーでは、より速く、より粗い「1 分足 OHLC」シミュレーションモードがあります。

「1 分足 OHLC」モードでは、ティックシーケンスは1 分足の OHLC 価格でのみ構成され、生成された制御点の数が大幅に削減されます。従って、テスト時間も減少します。OnTick () 関数は 1 分足 OHLC の価格によって構築されている全ての制御点で起動されます。

始値、高値、安値及び終値以外での追加の中間ティックを生成しないことで、始値が決定された瞬間から、価格展開を決定します。これにより、テストバランスの素晴らしい上向きのグラフを示す「テストグレイル」を作成することが出来ます。

そのようなグレイルの例はコードベースの Grr-al でみられます。

Grr-al エキスパートアドバイザーは、OHLC 価格の特別な機能を使用します。

図は、このエキスパートアドバイザーテストの非常に魅力的なグラフを示しています。それはどのように取得されたのでしょうか?1 分足の 4 価格は知られており、また、最初は始値で最後が終値であることも知られています。それらの間に高値と安値があり、発生順序は不明ですが、高値が始値以上であること(かつ安値が始値以下であること)も知られています。

始値を受信した瞬間を決定した後、現時点で持っている価格が高値か安値かを決定するために、次のティックを分析するので充分です。価格が始値を下回っている場合は、このティックでは安値と買いがあり、次のティックは、買いを閉めて売りに開く高値に対応します。終値である次のティックが最後で、ここでは売りを閉じます。

価格の後、始値よりも価格の大きいティックを受信した場合、取引の順番が逆になっています。 この「カンニング」モードで1 分足を処理し、次のものを待ちます。

このようなエキスパートアドバイザーを履歴上でテストする場合全てがスムーズに行きますが、オンラインで起動すると、バランスラインが安定したままですが、下向きだという、真実が明らかになります。このトリックを公開するには、単に「全ティック」モードでエキスパートアドバイザーを実行するだけです。

注意事項: 粗雑なテストモード(「1分 OHLC」と「始値のみ」)でのエキスパートアドバイザーのテスト結果があまりにも良すぎる場合は「全ティック」モードでテストしてみてください。

「始値のみ」

このモードでは、ティックはテストのために選択された時間軸の OHLC 価格に基づいて生成されます。エキスパートアドバイザーの OnTick() 関数は始値でのバーの初めでのみ実行されます。この機能により、ストップレベルや未決済は(特に高い時間軸のテストで)指定とは異なる価格でトリガされることがあります。代わりに、すぐにエキスパートアドバイザーの評価テストを実行する機会があります。

W1 及び MN1 期間は「始値のみ」ティック生成モードの例外です。これらの時間軸では、ティックは週または月の OHLC 価格ではなく、毎日の OHLC 価格に生成されます。

「始値のみ」モードでEURUSD H1 でエキスパートアドバイザーをテストするとします。この場合、ティック(制御点)の合計数はテスト間隔内の1時間のバーの数 4 倍以下です。しかしOnTick() ハンドラは 1 時間足の開始でのみ呼ばれます。. 正しいテストのために必要なチェックは(エキスパートアドバイザーから「隠れ」ている)ティックの残りの部分で発生します。

  • 証拠金要件の計算
  • 決済逆指及び決済指レベルのトリガ
  • 未決注文のトリガ
  • 期限切れの未決注文の削除

ポジションや未決注文がない場合、隠れたティックのチェックは無用で、速度の増加はかなリ大きいです。 この「始値のみ」モードは、未決注文、決済逆指及び決済指注文を使わずにバーの開始時のみで取引を処理するストラテジーのテストに適しています。そのようなストラテジーのクラスでは、テストの必要な精度が維持されます。

どのモードでのテストも可能なエキスパートアドバイザーの一例として、標準パッケージからMoving Average(移動平均)エキスパートアドバイザーを使用してみましょう。このエキスパートアドバイザーの論理は、意思決定の全てがバーのオープン時でなされるような方法で構築されており、取引は未決を使用せずにすぐに実行されます。

エキスパートアドバイザーのテストを 2010.09.01 から 2010.12.31 までの EURUSD H1 で実行し、グラフを比べてみます。図は、3 つのモードの全てのテストレポートからのバランスグラフを示します。

標準パッケージの Moving Average.mq5 エキスパートアドバイザーのテストグラフはテストモードに依存しません。

標準パッケージの Moving Average.mq5 エキスパートアドバイザーのグラフは異なるテストモードで全く同じです。

「始値のみ」モードには制限があります。

  • ランダム遅延実行モードは使用出来ません。
  • テストされているエキスパートアドバイザーでは、テストと最適化に使用されるより低い時間軸のデータはアクセス出来ません。例えば、H1 期間をテスト/最適化する場合、H2、H3、H4のデータにアクセスすることが出来ますが、M30、M20、M10などにはアクセス出来ません。また、アクセスされた長い時間軸は、テストの時間軸の倍数でなければなりません。例えば、M20でテストを実行する場合、M30のデータにアクセスすることは出来ません。が、H1にアクセスすることは可能です。これらの制限は、テスト/最適化中に生成されたバーのうち、下側または非多重時間軸のデータの取得が不可能なことに関係しています。
  • 他の時間軸のデータへのアクセスの制限は、データエキスパートアドバイザーが使用している他のシンボルにも適用されます。この場合、各シンボルの制限は、テスト/最適化中に初めにアクセスされた時間軸によって異なります。EURUSD H1 Eのテスト中に、エキスパートアドバイザーが GBPUSD M20 のデータにアクセスすると仮定します。この場合、エキスパートアドバイザーは EURUSD H1、H2、だけでなく、GBPUSD M20、H1、H2などのデータを使用することが出来るようになります。

注意事項:「始値のみ」モードのテスト時間は最短ですが、このモードは取引ストラテジーの全てには適していません。取引システムの特性に基づいて、所望のテストモードを選択するべきです。

このセクションを締めくくりとして 2011.01.11 21:00:00 から 2011.01.11 21:30:00 の間隔の 2 つの M15 バーでの EURUSD での異なるティック生成モードを視覚的に比較して検討してみましょう。

ティックは WriteTicksFromTester.mq5 エキスパートアドバイザーを使用して異なるファイルに保存され、ファイル名の終わりは filenameEveryTick、filenameOHLC 及び filenameOpenPrice 入力パラメータに指定されています。

WriteTicksFromTester エキスパートアドバイザーのティックの始まりと終わりの日(start 及び end 変数)の指定が可能です。

「全ティック」、「1分 OHLC」と「始値のみ」の 3 つのモードで、3ティック配列で3つのファイルを取得するために、エキスパートアドバイザーは、単一の実行で、対応するモードで 3 回起動されました。そして、この 3 つのファイルからのデータは TicksFromTester.mq5 指標を使用してチャート上に表示されました。 指標コードはこの記事に添付されています。

3 つの異なるテストモードでの MetaTrader 5 端末のストラテジーテスターでのティックシーケンス

デフォルトでは MQL5 言語のファイル操作は「ファイルサンドボックス」内で行われ、テストではエキスパートアドバイザーはこれらの「ファイルサンドボックス」にしかアクセス出来ません。テスト中で指標とエキスパートアドバイザーが 1 つのフォルダのファイルと作業出来るために FILE_COMMON フラグ が使用されました。エキスパートアドバイザーからのコード例

//--- ファイルを開く
   file=FileOpen(filename,FILE_WRITE|FILE_CSV|FILE_COMMON,";");
//--- ファイルハンドルをチェックする
   if(file==INVALID_HANDLE)
     {
      PrintFormat("Error in opening of file %s for writing. Error code=%d",filename,GetLastError());
      return;
     }
   else
     {
      PrintFormat("The file will be created in %s folder",TerminalInfoString(TERMINAL_COMMONDATA_PATH));
     }

指標のデータを読むために FILE_COMMON フラグも使用されました。これによって、必要なファイルの別のフォルダへの手動転送を回避できました。

//--- ファイルを開く
   int file=FileOpen(fname,FILE_READ|FILE_CSV|FILE_COMMON,";");
//--- ファイルハンドルをチェックする
   if(file==INVALID_HANDLE)
     {
      PrintFormat("Error in open of file %s for reading. Error code=%d",fname,GetLastError());
      return;
     }
   else
     {
      PrintFormat("File will be opened from %s",TerminalInfoString(TERMINAL_COMMONDATA_PATH));
     }

スプレッドのシミュレーション

売値と買値との価格差はスプレッドと呼ばれています。テストでは、スプレッドはモデルされる代わりに履歴データからとられます。履歴データでスプレッドがゼロ以下の場合、最後の既知の(生成の瞬間での)スプレッドがテストエージェントによって使用されます。

ストラテジーテスターでは、スプレッドは常に浮動と考えられています。つまり SymbolInfoInteger(symbol, SYMBOL_SPREAD_FLOAT) は常に true を返します。

更に、履歴データはティック値と取引高を含みます。データ格納と取得のためには特別な MqlRates 構造体が使用されます。

struct MqlRates
  {
   datetime time;         // 期間開始時刻
   double   open;         // 始値
   double   high;         // 期間の高値
   double   low;          // 期間の安値
   double   close;        // 終値
   long     tick_volume;  // ティックボリューム
   int      spread;       // スプレッド
   long     real_volume;  // 取引高
  };

テストでの実際ティックの使用

実際ティックのテストと最適化は、実世界の条件をより近く再現します。分足データに基づいてティックを生成する代わりに、ブローカによって蓄積された実際のティックを使用することが可能です。これらは、取引所および流動資産プロバイダーからのティックです。

最も正確なテスト精度を保証するために、分足は実際ティックモードでも使用され、ティックデータをチェックし修正するために適用されます。これにより、テスターとクライアント端末のチャートの相違を避けることもできます。

テスターは、ティックデータと分足パラメータを比較します。ティックはバーの高/低レベルを超えてはならず、最初と最後のティックはバーの始値/終値と一致する必要があります。ボリュームも同様に比較されます。不一致が検出された場合、この分足に対応するすべてのティックは破棄され、生成ティックが代わりに使用されます( 「全ティック」モード同様)。

シンボル履歴にティックデータを持たない分足が存在する場合、テスターは「全ティック」モードでティックを生成します。これにより、ブローカのティックデータが不十分な場合に、テスターに正しいチャートがプロットされます。

シンボル履歴に分足が存在しないが、その分の適切なティックデータが存在する場合、テスターはそのデータを使用します。たとえば、取引シンボルのペアは最終価格を使用して形成されたとします。最終価格が設定されていないBid /Ask価格のティックのみがサーバーから到着した場合、バーは生成されません。これらのティックデータは分データと矛盾しないので、テスターに使用されます。

ソースからクライアント端末にデータを送信する際の接続損失または他の不具合といった様々な理由により、ティックデータは分足と一致しないことがあります。テストにおいては分足データの信頼性はより高いと考えられます。

実際ティックでテストするときは、次の点にご注意ください。

  • テストを開始すると、シンボルの分足データがティックデータと同期されます。
  • ティックは、ストラテジーテスターのシンボル・キャッシュに格納されます。キャッシュサイズは128,000ティックを超えません。新しいティックが到着すると、最も古いデータがキャッシュから削除されます。しかし、CopyTicks機能によってキャッシュ外でティックを受け取ることが可能です(実際ティックでテストする場合のみ)。その場合、データは、対応するクライアント端末データベースと完全に類似しているテスターティックデータベースから要求されます。このベースでは分足は補正されていません。したがって、そこにあるティックは、キャッシュに格納されているティックと異なる場合があります。

クライアント端末のグローバル変数

テストではクライアント端末のグローバル変数もエミュレートされますが、これらは、端末で F3 ボタンでみられる、現在の端末のグローバル変数とは関係ありません。これは、テスト中の端末のグローバル変数の全ての操作は、クライアント端末の外で(テストエージェントで)行われることを意味します。

テスト中の指標の計算

リアルタイムモードでは、指標値は、全てのティックで計算されます。ストラテジーテスター指標計算のために費用対効果の高いモデルを採用し、エキスパートアドバイザーの実行直前のみに指標が再計算されます。これは、指標の再計算が OnTick()、OnTrade() 及び OnTimer() 関数の呼び出しの前に行われることを意味します。

特定のイベントハンドラで指標の呼び出しがあるかどうかは問題ではありません。iCustom() または IndicatorCreate() 関数によってハンドルが作成された指標の全てが、イベントハンドラを呼び出す前に再計算されます。

結果的に「全ティック」モードでのテストでは、指標の計算は OnTick() 関数呼び出しの前になされます。

エキスパートアドバイザーでEventSetTimer() を使用してタイマーがかかっている場合、指標は OnTimer() ハンドラが呼ばれる前に毎回再計算されます。このため、非最適な方法で記述された指標を使用すると、テスト時間が大幅に増加することがあります。

テスト中の履歴の読み込み

テストされるシンボルの履歴は、テストプロセスの開始前に端末によって取引サーバから読み込みまた同期されます。端末は、後のリクエストを避けるために、初めに使用可能な全てのシンボル履歴を順番に読み込みます。その後は、新しいデータのみが読み込まれます。

テストエージェントは、テスト開始の直後に、テストされるシンボルの履歴を端末から受け取ります。他の金融製品のデータがテストの過程で使用されている(例えば、多通貨エキスパートアドバイザー)場合、テストエージェントは、データの最初の呼び出し時にクライアント端末から必要な履歴を要求します。履歴データが端末で利用可能な場合、それらはすぐにテストエージェントに渡されます。データが利用可能でない場合は、端末はサーバからリクエスト及びダウンロードしてからテストエージェントに渡します。

取引操作のクロスレートを計算するには、追加的な製品のデータも必要です。例えば、米ドル預金通貨での EURCHF ストラテジーをテストする際、ストラテジーにはそれらを直接使用する呼び出しが含まれないにもかかわらず、テストエージェントは、最初の取引操作を処理する前に、クライアント端末から EURUSD とUSDCHF の履歴データをリクエストします。

多通貨ストラテジーをテストする前に、クライアント端末に全ての必要な履歴データをダウンロードすることをお勧めします。これによって、必要なデータのダウンロードに関連したテスト/最適化の遅れが防げます。例えば、適切なチャートを開いて履歴先頭にスクロールすることによって、履歴をダウンロードすることが出来ます。端末への履歴の強制読み込みの例は MQL5 リフェレンスのデータアクセスの整理セクションでみられます。

代わりに、テストエージェントは端末からパックされた形式で履歴を受け取ります。必要なデータはテスタの前回の実行以降利用可能であるため、次のテスト中にはテスタは端末から履歴を読み込みません。

  • 端末は、エージェントが初めにテストされるシンボルの履歴をリクエストする際に、取引サーバから一度だけ履歴を読み込みます。トラフィックを減らすために、履歴はパック形式で読み込まれます。
  • ティックはネットワーク経由で送信されず、テストエージェント上で生成されます。

多通貨テスト

ストラテジーテスターは、複数シンボルの売買、ストラテジーのテストを実行することが出来ます。 以前のプラットフォームではテストは単一のシンボルに対して実施されていたので、このようなエキスパートアドバイザーは従来「多通貨エキスパートアドバイザー」と呼ばれます。MetaTrader 5 端末のストラテジーテスターでは、利用可能な全てのシンボルの取引をモデル化することが出来ます。

テスタはシンボルデータの最初の呼び出し時に自動的に使用される記号の履歴を(取引サーバからではなく)クライアント端末 から読み込みます。

テストエージェントはテスト開始時に指標の計算に必要で欠けている小幅な履歴データをダウンロードします。 D1 以下の時間軸では、ダウンロードされた履歴の最小容量は1年です。

よって、2010.11.01-2010.12.01 の間隔を(各足が 15 分に等しい)M15 期間でテストした場合、端末は2010年 1 年間の履歴をリクエストします。週足では、約 2 年(1年は 52 週)である 100 足の履歴を要求します。月足でのテストのために、エージェントは 8 年の履歴(12 カ月 × 8 年 = 96 ヶ月)を要求します。

足が足りない場合、必要な足数を確保するためにテスト前にテストの開始日が過去から現在まで自動的にシフトされます。

テスト中には「気配値表示」もエミュレートされ 銘柄情報が取得出来ます。

デフォルトでは、テスト開始時にストラテジーテスターの「気配値表示」にはテストが実行されている 1 つのみの銘柄が存在します 。必要なシンボルの全ては自動的に(端末ではなく)ストラテジーテスターの「気配値表示」に参照されます。

多通貨エキスパートアドバイザーのテストを開始する前に、端末の「気配値表示」のテストに必要なシンボルを選択して必要なデータを読み込む必要があります。「外来」シンボルの最初の呼び出し時には、その履歴が自動的にテストエージェントとクライアント端末間で同期されます。「外来」シンボルとはテストが実行されているシンボル以外のシンボルです。

「他の」シンボルへの参照は次の場合に起こります。

  • 以下の関数を使用した銘柄/時間軸のための時系列のリクエスト

「その他」の銘柄の最初の呼び出しの時点で、テストプロセスが停止され、銘柄/時間軸の履歴が端末からテストエージェントにダウンロードされます。同時に、このシンボルのティックシーケンスが生成されます。

シンボルごとに個々のティックシーケンスが、選択されたティック生成モードに応じて生成されます。OnInit() ハンドラの SymbolSelect() の呼び出しによって、目的のシンボルの履歴を明示的にリクエストすることも出来ます。履歴ダウンロードはエキスパートアドバイザーテストの直前に行われます。

この様に MetaTrader 5 クライアント端末での多通貨テストの実行は余分な労力を必要としません。ただ、クライアント端末で適切な銘柄のチャートを開くだけです。適切なデータが含まれていれば全ての必要なシンボルの履歴は自動的に取引サーバからアップロードされます。

ストラテジーテスターーでの時間のシミュレーション

テスト中、TimeLocal() ローカル時刻は常に TimeTradeServer() サーバ時刻と同じです。そして、サーバ時刻は常に TimeGMT() GMT に等しいです。こうすれば、これらの全ての関数は、テスト中に同じ時刻を表示します。

GMT、ローカル、及びストラテジーテスターでのサーバ時刻との差の欠如は、サーバへの接続がない場合には、意図的に行われます。テスト結果は接続のあるなしに関係なく同じでなければなりません。サーバ時刻に関する情報はローカル格納されておらず、サーバから取得されます。

テストでのグラフィックオブジェクト

テスト/最適化中には、グラフィックオブジェクトはプロットされません。よって、テスト/最適化の際に作成されたオブジェクトのプロパティを参照すると、エキスパートアドバイザーはゼロ値を受け取ることになります。

この制限は、ビジュアルモードでのテストには適用されません。

ストラテジーテスターーでの OnTimer() 関数

MQL5 はタイマーイベントを処理するための機会を提供します。OnTimer() ハンドラはテストモードにかかわらず呼び出されます。これは、テストが H4 期間で「始値のみ」モードを実行し、エキスパートアドバイザーが毎秒コールに設定されたタイマを有する場合、それぞれの H4 足の開始時に OnTick() ハンドラが1 回呼ばれ、その後 OnTimer() ハンドラが 14,400 回( 3,600 秒 * 4 時間)呼ばれることを意味します。エキスパートアドバイザーのテスト時間が増加される量は、その論理に依存します。

テスト時間のタイマーに所定された頻繁度依への存性を確認するために、取引操作なしの簡単なエキスパートアドバイザーを作成しました。

//--- 入力パラメータ
input int      timer=1;              // 秒単位でのタイマー値
input bool     timer_switch_on=true; // タイマーがオン
//+------------------------------------------------------------------+
//| エキスパート初期化に使用される関数                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- timer_switch_on==true  の場合タイマーを実行
   if(timer_switch_on)
     {
      EventSetTimer(timer);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| エキスパート初期化解除に使用される関数                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- タイマーを停止する
   EventKillTimer();
  }
//+------------------------------------------------------------------+
//| Timer 関数                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
// ハンドラ本体が空なので何もしない
  }
//+------------------------------------------------------------------+

タイマパラメータ(タイマーイベントの時間軸)の異なる値でテスト時間の測定が取られました。取得されたデータを使用して、テスト時間をタイマー時間軸の関数としてプロットします。

タイマー時間軸の関数としてのテスト時間

timer パラメータが小さいほど、EventSetTimer(Timer) 関数の初期化中の OnTimer() ハンドラの呼び出しの間隔が小さく、テスト時間 T が大きいことが明確です。

ストラテジーテスターーでの Sleep() 関数

Sleep() 関数は、グラフを操作する場合、エキスパートアドバイザーまたはスクリプトがしばらくの間 MQL5 プログラムの実行を中断することを可能にします。これは、リクエスト時にデータが準備されてなく準備が出来るまで待つ必要がある場合に便利です。Sleep() 関数の繊細な使用例は データーアクセスの整理セクションでみられます。

テストプロセスは Sleep() の呼び出しで滞ることはありません。Sleep() が呼び出されると生成されたティックは指定された遅延以内に「プレイ」され、未決注文やストップのトリガになるかもしれません。Sleep() の呼び出し後に、ストラテジーテスターでのシミュレート時刻は Sleep 関数のパラメータで指定された時間分進みます。

Sleep() 関数の実行結果として、ストラテジーテスターで現在時刻がテスト期間を超えてしまった場合は、「Infinite Sleep loop detected while testing(テスト中に無限スリープループが検出されました)」とのエラーを受け取ることになります。このエラーが受け取られた場合、テスト結果は拒否されず、全ての計算は全体(取引数、沈下など)にわたって行われ、テスト結果は端末に渡されます。

OnDeinit() の呼び出しは、テスト期間の範囲を超えることが保証されるため、Sleep() 関数は OnDeinit() では動作しません。

MetaTrader 5 端末で Sleep() 関数を使用する方式

数値計算や最適化問題のためのストラテジーテスターーの使用

MetaTrader 5 端末のテスタは、取引ストラテジーテストにだけでなく数学的な計算のためにも使用することが出来ます。使用するには「数値計算」モードの選択が必要です。

math_calculations

この場合、OnInit()、OnTester()、OnDeinit() の 3 つの関数のみが呼ばれます。「数値計算」モードでは、ストラテジーテスターは、いかなるティックも生成せず履歴もダウンロードしません。

終了日より後日の開始日を指定された場合も、ストラテジーテスター「数値計算」モードで動作されます。

数学問題の解決にテスタを使用する場合は、履歴のアップロードとティックの生成は起こりません。

多変数関数の極値を探すことは MetaTrader 5 ストラテジーテスターで解決する典型的な数学の問題です。

解決するには

  • 関数値の計算は OnTester() 関数に位置するべきです。
  • 関数のパラメータはエキスパートアドバイザーの入力変数として定義されるべきです。

エキスパートアドバイザーをコンパイルして「ストラテジーテスター」ウィンドウを開きます。「パラメータ」タブで必要な入力パラメータを選択し、各関数変数のスタート、ストップ、及びステップ値を指定してパラメータセットの値を定義します。

「設定」タブの「オプティマイズ」(最適化の種類)で、「完全アルゴリズム(低速)」または「遺伝的アルゴリズム(高速)」を選びます。関数の極値の簡単な検索のためには、高速な最適化を選択した方が良いですが、変数のセット全体の値を計算する場合は、時間をかけた最適化を使用するのが最適です。

「数値計算」モードを選び「スタート」ボタンを使用して最適化の実行をします。ストラテジーテスターは最適化中に OnTester 関数の極大値を検索することにご注目ください。極小値を見つけるには OnTester 関数で計算された関数値の逆数を返します。

return(1/function_value);

ゼロ除算による重大なエラーの取得を回避するために function_value がゼロでないことを確認する必要があります。

この記事の読者によって示唆された、より便利で最適化の結果を歪めない別方法があります。

return(-function_value);

このオプションは function_value がゼロに等しいかどうかの確認を必要とせず、3次元表現における最適化の結果の面は同じ図形を有します。違いは、これがオリジナルのミラーリングということです。

例として sink() 関数を提供します。

sink_formula

極値を見つけるためのエキスパートアドバイザーのコードは OnTester() に配置されます。

//+------------------------------------------------------------------+
//|                                                         Sink.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.MQL5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.MQL5.com"
#property version   "1.00"
//--- 入力パラメータ
input double   x=-3.0; // スタート= -3、ステップ = 0.05、ストップ = 3
input double   y=-3.0; // スタート = -3、ステップ = 0.05、ストップ = 3
//+------------------------------------------------------------------+
//| テスタ関数                                                  |
//+------------------------------------------------------------------+
double OnTester()
  {
//---
   double sink=MathSin(x*x+y*y);
//---
   return(sink);
  }
//+------------------------------------------------------------------+

最適化をして、最適化の結果 を 2D グラフで見ましょう。

2D グラフでみる sink (x*x+y*y) 関数の完全な最適化の結果

より良い値が与えられた(x、y)パラメータの組はより飽和した色を持ちます。sink() 式の形の観点から期待されたように、その値は( 0, 0 )を中心とする同心円を形成しています。関数は、単一の最大値・最小値を持っていないことは 3D グラフで見ることが出来ます。

3D Graph of Sink 関数の 3D グラフ

「始値のみ」モードでのバーの同期

MetaTrader 5 クライエント端末のテスタは、いわゆる「多通貨」エキスパートアドバイザーをチェックすることが出来ます。多通貨エキスパートアドバイザーとは 2 つ以上のシンボルで売買をするエキスパートアドバイザーです。

複数のシンボルを売買するストラテジーのテストは、テスタにいくつかの追加的な技術要件を課しています。

  • シンボルのティック生成
  • シンボル指標値の計算
  • シンボルの証拠金要件の計算
  • 全ての取引シンボルの生成されたティックシーケンスの同期

ストラテジーテスターは、ティックを生成し選択された取引モードに応じて各金融製品のためにティックシーケンスを再生します。同時に、他のシンボルにどのようにバーが開いたかに関係なく、それぞれのシンボルに新しいバーが開かれます。これは、多通貨エキスパートアドバイザーのテスト時に、ある製品では新しい足が既に開かれていても他の製品では開かれていないという状態が発生する可能性がある(実際によくあります)ことを意味します。よって、テストでも現実のように事が起こります。

テスタでのこの本格的な履歴シミュレーションは「全ティック」及び「1分足 OHLC」テストモードが使用されている限り問題を発生することはありません。これらのモードでは、1 つのローソク足に充分なティックが生成され、異なるシンボルのバーの同期まで待つことが出来ます。しかし、金融製品の取引でのバーの同期が必須である場合、多通貨ストラテジーは「始値のみ」モードではどのようにテストされるのでしょうか。このモードでは、エキスパートアドバイザーはバーのオープン時に対応する 1 つのティックのみで呼ばれています。

例を使用して説明します。 EURUSD のエキスパートアドバイザーがテストされていて、1 時間足が EURUSD で開いたとします。この事実は簡単に認識出来ます。「始値のみ」モードでは NewTick イベントはテスト期間のバーのオープン時に対応します。しかし、エキスパートアドバイザーで使用されている USDJPY 上で開いたローソク足について保証するものではありません。

通常の状況では OnTick() 関数の操作を完了して次のティックでの新しい USDJPY バーの出現を確認するので充分です。しかし「始値のみ」モードでのテストでは他のティックが存在しないので、このモードは多通貨エキスパートアドバイザーのテストには向いていないように見えるかもしれません。しかし、これはそうではありません。MetaTrader 5 のテスタは現実そっくりに動作することを忘れてはいけません。Sleep() を使用して新しいバーが別のシンボルに開かれるまで待てばいいのです。

「始値のみ」モードでのバー同期化を示すエキスパートアドバイザーの Synchronize_Bars_Use_Sleep.mq5 のコード

//+------------------------------------------------------------------+
//|                                   Synchronize_Bars_Use_Sleep.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.MQL5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, MetaQuotes Software Corp."
#property link      "https://www.MQL5.com"
#property version   "1.00"
//--- 入力パラメータ
input string   other_symbol="USDJPY";
//+------------------------------------------------------------------+
//| エキスパート初期化に使用される関数                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- シンボルをチェックする
   if(_Symbol==other_symbol)
     {
      PrintFormat("You have to specify the other symbol in input parameters or select other symbol in Strategy Tester!");
      //--- 強制的なテスト終了
      return(INIT_PARAMETERS_INCORRECT);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| エキスパートティック関数                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- 最後のバーの時刻の格納に使用される静的変数
   static datetime last_bar_time=0;
//--- 同期化フラグ
   static bool synchonized=false;
//--- 静的変数が初期化されていない場合
   if(last_bar_time==0)
     {
      //--- 始めての呼び出し。バーを保存して終了する。
      last_bar_time=(datetime)SeriesInfoInteger(_Symbol,Period(),SERIES_LASTBAR_DATE);
      PrintFormat("The last_bar_time variable is initialized with value %s",TimeToString(last_bar_time));
     }
//--- チャートシンボルの最後のバーの開始時刻を取得する
   datetime curr_time=(datetime)SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE);
//--- 時刻が異なる場合
   if(curr_time!=last_bar_time)
     {
      //--- バーの開始時刻を静的変数に保存する
      last_bar_time=curr_time;
      //--- 同期されていない
      synchonized=false;
      //--- メッセージを出力する
      PrintFormat("A new bar has appeared on symbol %s at %s",_Symbol,TimeToString(TimeCurrent()));
     }
//--- 他のシンボルのバーの開始時刻
   datetime other_time;
//---他のシンボルの開始時刻が curr_time になるまで反復する
   while(!(curr_time==(other_time=(datetime)SeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE)) && !synchonized))
     {
      PrintFormat("Waiting 5 seconds..");
      //--- 5 秒待ってSeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE) を呼び出す
      Sleep(5000);
     }
//--- バーは同期されている
   synchonized=true;
   PrintFormat("Open bar time of the chart symbol %s: is %s",_Symbol,TimeToString(last_bar_time));
   PrintFormat("Open bar time of the symbol %s: is %s",other_symbol,TimeToString(other_time));
//--- TimeCurrent() は役立たないので TimeTradeServer() を使用する
   Print("The bars are synchronized at ",TimeToString(TimeTradeServer(),TIME_SECONDS));
  }
//+------------------------------------------------------------------+

同期の事実が確立された時、現在の時刻を表示するエキスパートアドバイザーの最後の行にご注目ください。

   Print("The bars synchronized at ",TimeToString(TimeTradeServer(),TIME_SECONDS));

現在時刻の表示には TimeCurrent() の代わりに TimeTradeServer() 関数を使用しました。TimeCurrent() 関数は Sleep() の使用後に変更されない最後のティックの時刻を返します。「始値のみ」モードでエキスパートアドバイザーを実行すると、バーの同期に関するメッセージが表示されます。

Synchronize_Bars_Use_Sleep_EA

最後ティック到着時刻ではなく現在のサーバ時刻を取得する必要がある場合TimeCurrent() の代わりにTimeTradeServer() 関数を使用します。

バーを同期させるためには、タイマーを使用した別方法があります。そのよなエキスパートアドバイザーの例はこの記事に添付されている Synchronize_Bars_Use_OnTimer.mq5 です。

テスタの IndicatorRelease() 関数

単一のテストの完了後、機器のチャートが自動的に開かれ、完成した約定とエキスパートアドバイザーで使用される指標を表示します。これは、視覚的にエントリーポイントと終了ポイントをチェックして指標の値と比較するのに役立ちます。  

注意事項: テスト終了時に自動に開くチャートに表示された指標は、テスト終了時に新たに計算されます。これらの指標がテストされたエキスパートアドバイザーで使用されていた場合にもです。

しかし、場合によって、プログラマが指標が取引アルゴリズムに関与された場合の情報を非表示にすることがあります。例えば、エキスパートアドバイザーのコードが、ソースコードなしの実行可能ファイルとしてレンタルまたは販売されている場合です。この場合 IndicatorRelease() 関数が適しています。

端末は、クライアント端末のディレクトリ/プロファイル/テンプレートでテンプレートの名称を tester.tpl と設定した場合、それが開かれたチャートに適用されます。それがない場合、デフォルトのテンプレートが適用されます。(default.tpl).

IndicatorRelease() 関数はもともと、不要になった場合指標の演算部を解放するのに意図されています。各ティックが指標計算を呼ぶので、メモリとCPU リソースの両方を保存することが出来ます。 その 2 つ目の目的は、単一のテストの実行後、テストチャートでの指標の表示を禁止することです。

テスト後に指標の表示を禁止するには IndicatorRelease() 関数を OnDeinit()ハンドラの指標ハンドルと呼びます。OnDeinit() 関数は、常にテスト完了後及びチャート表示前に呼び出されます。

//+------------------------------------------------------------------+
//| エキスパート初期化解除に使用される関数                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   bool hidden=IndicatorRelease(handle_ind);
   if(hidden) Print("IndicatorRelease() successfully completed");
   else Print("IndicatorRelease() returned false. Error code ",GetLastError());
  }

テスト後に指標の表示を禁止するには OnDeinit() ハンドラで IndicatorRelease() を呼びます。

テスタでのイベントハンドル

MetaTrader 5 テスタで履歴データのテストをするにはエキスパートアドバイザーでの OnTick() ハンドラの存在は必須ではありません。エキスパートアドバイザーが下記の関数ハンドラの 1 つを持つことで充分です。

  • OnTick() - 新しいティック到着のイベントハンドラ
  • OnTrade() - 取引イベントハンドラ
  • OnTimer() - タイマからの信号到達のイベントハンドラ
  • OnChartEvent() - クライアントイベントハンドラ

エキスパートアドバイザーのテストでは、カスタムイベントは OnChartEvent() 関数で処理出来ますが、指標では、この関数はテスタで呼ぶことが出来ません。指標に OnChartEvent() イベントハンドラがあって指標がテストされたエキスパートアドバイザーに使用されていたとしても、指標自体はカスタムイベントを受け取りません。

テスト時に、指標は EventChartCustom() 関数を使用してカスタムイベントを作成することができ、エキスパートアドバイザーは個のイベントをOnChartEvent() で処理出来ます。

これらのイベントに加えて、ストラテジーテスターではテストと最適化のプロセスに関連する特別なイベントが生成されます。

  • Tester - このイベントはエキスパートアドバイザーの履歴データのテストの完了時に生成されます。Tester イベントは OnTester() 関数で処理されます。この関数は、エキスパートアドバイザーのテスト時にのみ使用でき、主に入力パラメータの遺伝的最適化のためのカスタム最大基準として使用される値の計算のために意図されています。
  • TesterInit - このイベントは、ストラテジーテスターでの最適化の一番初めのパスの開始時に発生します。TesterInit イベントは OnTesterInit() 関数で処理されます。最適化の開始時に、このハンドラを持つエキスパートアドバイザーは、テスタに指定されたシンボルと時間軸を持つ別の端末チャートに自動的に読み込まれ、TesterInit イベントを受け取ります。この関数は、更なる最適化結果の処理のために、最適化の開始前にエキスパートアドバイザーを開始するために使用されます。
  • TesterPass - このイベントは新しいデータ枠が受信された時に生成されます。TesterPass イベントは OnTesterPass() 関数で処理されます。このハンドラを持つエキスパートアドバイザーは、テストのために指定された銘柄/時間軸で別の端末のチャートに自動的に読み込まれ、最適化の間にフレームが受信された時にTesterPass イベントを受け取ります。この関数は、完了を待たずの「その場で」の最適化の結果の動的処理に使用されます。フレームは OnTester() ハンドラの単一パスの後で呼ばれる FrameAdd() 関数で追加されます。
  • TesterDeinit - このイベントは、ストラテジーテスターにおけるエキスパートアドバイザーの最適化の終了後に生成されます。TesterDeinit イベントは OnTesterDeinit() 関数で処理されます。このハンドラを持つエキスパートアドバイザーは、最適化の開始時に自動的にチャートに読み込まれ、終了後にTesterDeinit を受け取ります。この関数は最適化の結果の全ての最終処理に使用されます。

テストエージェント

MetaTrader 5 クライエント端末でのテストはテストエージェントを使用して行われます。ローカルエージェントは自動的に作成されて有効にされます。ローカルオブジェクトのデフォルト数は、コンピュータ内のコアの数に対応しています。

それぞれのテストエージェントはクライエント端末と関係なく独自のグローバル変数のコピーを持ちます。端末自体は、ローカル及び遠隔エージェントにタスクを分散するディスパッチャです。エキスパートアドバイザーのテストの作業を実行した後、エージェントは指定されたパラメータで端末に結果を返します。単一のテストには、単一のエージェントが使用されます。

端末から受信された履歴はエージェントによって製品の名称を使用した別々のフォルダに保存されるので、EURUSD の履歴はEURUSD という名称のフォルダに保存されます。また、金融製品の履歴は、そのソースによって分類されています。履歴は以下のように保存されます。

tester_catalog\Agent-IPaddress-Port\bases\name_source\history\symbol_name

例えば MetaQuotes-Demo サーバからの EURUSD の履歴は tester_catalog\Agent-127.0.0.1-3000\bases\MetaQuotes-Demo\EURUSD fフォルダに保存されます。

ローカルエージェントは、テストの完了後に次の呼び出しのために立ち上げに時間を無駄にしないように、次のタスクを待って5分間スタンバイモードに入ります。待機期間が終わって初めてローカルエージェントはシャットダウンし CPU メモリからアンロードされます。

ユーザがテストを早期終了(「キャンセル」ボタン)した場合やクライアント端末が閉じられた場合、全てのローカルエージェントはすぐに作業を停止しメモリからアンロードされます。

端末とエージェントの間でのデータ交換

テスト実行時に、クライアント端末はエージェントに送信するパラメータブロックをいくつか用意します。

  • テストの入力パラメータ(シミュレーションモード、テスト、金融製品、最適化基準等の間隔など)
  • 「気配値表示」で選択されたシンボルのリスト
  • シンボルテストの仕様(契約サイズ、決済逆指値及び決済指値を設定するための市場からの許容補償金)
  • テストされるエキスパートアドバイザーと入力パラメータの値
  • 追加的なファイルの情報(ライブラリ、指標、データファイル - # property tester_ ...

tester_indicator

string

「indicator_name.ex5」形式でのカスタム指標の名称テストが必要な指標は対応するパラメータが定数文字列で設定されている場合 iCustom() 関数の呼び出しで自動的に定義されます。それ以外は全て( IndicatorCreate() 関数の使用または指標銘を設定するパラメータでの非定数文字列の使用)このプロパティは必須です。

tester_file

string

テスタのファイル名。二重引用符内で拡張子の表示も含みます(文字列定数)。指定されたファイルはテスタに渡されます。テストされるべき入力ファイルがある場合、指定が必ず必要です。

tester_library

string

二重引用符内で拡張子を含むライブラリ名。ライブラリは拡張子として dll または ex5 を持つことが出来ます。テストを必要とするライブラリは自動的に定義されます。しかし、ライブラリがカスタム指標で使用された場合、このプロパティは必須です。

パラメータの各ブロックで、MD5 ハッシュ形式のデジタル指紋が作成されてエージェントに送信されます。MD5 ハッシュは、基づいて計算された情報の量よりもはるかに小さく、セットごとに一意です。

エージェントは、ブロックのハッシュを受信し、既に持っているものと比較します。与えられたパラメータブロックの指紋がエージェントに存在しない、または受信したハッシュが、既存のものと異なる場合、エージェントは、このパラメータのブロックを要求します。これによって、端末とエージェント間のトラフィックが減少します。

テスト後にエージェントは「テスト結果」と「最適化の結果」タブに表示される、受信利益、約定数、シャープ係数、OnTester() 関数の結果などの実行結果をプラットフォームに返します。

最適化中に、端末はエージェントにテスト作業を小型パッケージで渡し、それぞれのパッケージにはいくつかのタスクが含まれています(ここで、それぞれのタスクとは、入力パラメータのセットを持つ単一のテストを意味します。)。これは、端末とエージェント間の交換時間を短縮します。

エージェントは、セキュリティ上の理由のため、端末から取得した EX5 ファイル(エキスパートアドバイザー、指標、ライブラリなど)をハードディスクに記録することはありません。実行中のエージェントを持つコンピュータが送信したデータを使用することが出来ないようにです。DLL を含んだ他の全てのファイルはサンドボックスに記録されます。遠隔エージェントではDLL を使用してのエキスパートアドバイザーのテストは出来ません。

テスト結果は、必要な時に迅速にアクセス出来るように、端末によって結果の特別なキャッシュ(結果キャッシュ)に追加されます。再実行を回避するために、端末はパラメータのセットごとに以前の実行からの既に入手可能な結果を結果キャッシュ内で検索します。この様なパラメータセットで結果が見つからない場合、エージェントにテスト実行タスクが与えられます。<

端末とエージェントの間のトラフィックは全て暗号化されます。

ティックはネットワーク経由で送信されず、テストエージェント上で生成されます。

全てのクライアント端末の共有フォルダの使用

全てのテストエージェントは、互いから、またクライアント端末から単離されています。各エージェントは、ログが記録されている独自のフォルダを持っています。また、テスト中のエージェントのファイル操作の全てはagent_name/MQL5/Files フォルダで行われます。しかし、ファイルのオープン時に FILE_COMMON フラグを指定された場合、クライアント端末の全てに共有フォルダを介してローカルエージェントとクライアント端末間の相互作用を実現することが出来ます。

//+------------------------------------------------------------------+
//| エキスパート初期化に使用される関数                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- 全てのクライアント端末の共有フォルダの使用
   common_folder=TerminalInfoString(TERMINAL_COMMONDATA_PATH);
//--- このフォルダの名称を書く
   PrintFormat("Open the file in the shared folder of the client terminals %s", common_folder);
//--- ファイルを共通フォルダで開く( FILE_COMMON フラッグで示される)
   handle=FileOpen(filename,FILE_WRITE|FILE_READ|FILE_COMMON);
  ... 更なるアクション
//---
   return(INIT_SUCCEEDED);
  }

DLL の使用

最適化を速めるために、ローカルだけではなく遠隔エージェントも利用出来ます。この場合、遠隔エージェントにはいくつかの制限があります。まず第一に、遠隔エージェントはログにポジションの開閉に関する Print() 関数実行の結果を表示しません。間違って書かれたエキスパートアドバイザーが、遠隔エージェントに使用されているコンピューターをメッセージで破壊しないように、ログには最小限の情報が表示されます。

2 番目の制限はエキスパートアドバイザーのテストで DLL が使用出来ないことです。セキュリティ上の理由から、遠隔エージェントでの DLL の呼び出しは絶対禁止となっています。ローカルエージェントでは、エキスパートアドバイザーのテストでの DLL の呼び出しは、適切な「インポートDLLを許可」でのみ許可されています。

MQL5 プログラムの「インポートDLLを許可」オプション

注意事項: DLL 呼び出しを必要とするサードパーティーのエキスパートアドバイザー(スクリプト、指標)の使用にあたって、端末の設定でこのオプションを許可する場合にとるリスクには注意するべきです。エキスパートアドバイザーがどのように(テストまたはチャートでの実行)使用されるかには関係なくです。