MQL5のExpert Advisorsのテストと最適化を行うためのガイド
はじめに
開発者にとって、EAのコードを書いて、それが高収益性という目的を達成すると確認することは、常にたいへん面倒なプロセスです。ここでは、EAを書くというめざす目標達成に近づくことができるよう、EAのテストと最適化に必要な重点ステップを見ていきます。
1. コードエラーの特定と修正
ここではまず、EAのコードを書く中で通常出くわす一般的なコードエラーを見ることから始めます。大抵の場合、初心者にとって、コードを書くとき、あるいは他の開発者によって書かれたコードを変更するとき、コードエラーを見つけ修正するのは骨の折れる作業です。この節では、MQL5の編集機能を使ってそういうエラーを見つけ修正するのがいかに簡単かを見ていきます。
コードを書き上げた直後は、エラーなどない、とほぼ確信しているので、すべてがうまくいくように思えます。あるいは、そのコードは他の人によって書かれたもので、あなたは多少の変更を担当したにすぎませんでした。それなのにコンパイル ボタン(またはF7)を押したら、メタエディターツールボックスウィンドウの エラー タブに示されるようにコードはエラーだらけなのを目の当たりにするのです。
図 1 EAのコンパイルエラー
なんということでしょう。エラー38件に警告1件です。実際にはここに表示されているほどのエラーはないかもしれませんが、ここではコンパイルするときに発生しうる各種エラーに対し、どのように修正するかについて学ぶことを目的としてエラーをあげています。上記の表についてご説明します。
- 1 で示されている箇所はコードのエラー内容です。 ここでエラーがどのようなものかを知ることができます。
- 2 で示されている箇所はエラーが存在するファイルです。 エラーファイルがあるとしたらこれは重要な情報です。なぜなら、この情報から、表示のエラーについてどのファイルを確認すればよいかわかるからです。
- 3 で示されている箇所は何行目の何列目にエラーがあるかというエラーの位置を示しています。これで表示のエラーについて確認するべき行が特定されます。
- 4 で示されている箇所はコンパイルエラーと警告の集計です。
では、エラーを一つづつ修正していきましょう。エラータブを最初の行までスクロールアップし、一番目から始めましょう。
図2 コードエラーの特定と修正
最初のエラーは「定数値のトランケーション」 とあり、位置は 16行目の20列目となっています。正確にこのコードのどの行にこのエラーが位置するのか知るには、メタエディターの編集メニューから行へ移動を選択するか、キーボード上でCTRL G を押します。
図3 エラーコード行番号の指定
次のようなダイアログボックスが表示されます。
図4 エラー行番号指定ダイアログボックス
ダイアログボックスに括弧内表記されている数値範囲はこのコードに存在する行の合計数です。したがって、ここに表示されている(1-354) は、このコードは354行目のコードであることを示しています。
ボックス内に確認したい行番号を入力し、OKボタンをクリックします。そうすると、すぐに指定した行に移動します。そして、その指定行上でカーソルが点滅しているのがわかります。
図5 カーソルによるエラー行ナンバー表示
ここでの問題は、ロットを整数(int) 変数として宣言したにもかかわらず、初期設定が実数値 (0.1)となっていることです。このエラー修正には、intをdoubleに変更し、ファイルを保存した後、エラーが修正されたか確認するため再度 コンパイルボタンをクリックします。
図6 修正後のコンパイルと格納
再度コンパイルすれば、第一の問題は解決です。でも下記のように、まだまだ問題は残っています。
図7 コンパイル後にまだ表示されているエラー
前回の処理同様の手順を踏まえ、今度は31行目に移動します。ただし、今回は エラー タブにあるエラーの上で右クリック し、 行へ移動を選択します。
図8 コードエラー行を特定するその他の方法
または単に エラーを選択しキーボード上でエンターを押します。すぐに31行目に移動します。
31行目でカーソルが点滅し、小さな赤い丸(エラーアイコン)がついているのがわかります。
図9a エラー行の特定
一方、16行目で修正した最初のエラーのように、警告メッセージの場合は、黄色の三角形(警告アイコン)が表示されます。
図9b エラー行の特定
さて、31行目に問題がないのは明らかですが、エラー内容表記には「'STP' - 予期せぬトークン」とあります。
そこで、何がおかしいのか知るために前の行(30行目)を確認します。よく見ると、30行目の"double ccminb = -95.0000" の後にセミコロンが抜けています。それが、31行目にエラーが現れた原因です。そこで、-95.0000 の後にセミコロンを入力し、エラーを修正したら、コードを再びコンパイルします。
これで 31 行目のエラーはなくなりました。次は下記にあるように100行目です。
図10 その他のエラー
オローサム、訊きたいんだけど、一個一個エラー修正した後コンパイルしなくちゃならないの?いったんエラー行ぜんぶに修正をかけて、個別にじゃなく、エラー修正後にまとめてコンパイルするっていうのはどうなんだ?
こんな疑問を持ちましたか?
ある意味それはもっともですが、あまり薦められません。問題は常に一つずつ順を追って解決していくものなのです。問題を一度にまとめて解決しようとすると、後で痛い目を見ることがあります。その理由はすぐに解ります。もう少し我慢しておつきあいください。
では、コードの問題に戻りましょう。次のエラー、100行目をチェックするところでした。エラー内容表記に「グローバルスコープではif文は許可されていません」とあります。が、100行目のif文はグローバルスコープではないのは明らかです。ではなぜこのエラーが発生したのでしょうか。とにかく100行目をみてみましょう。
図11 エラーの特定
どうやら100行目に問題はなさそうです。となると、31行目を修正したばかりなので、問題があるとするとそれは32行目から99行目の間とういうことになります。99行目までさかのぼってみましょう。(99行目はコメント行ですから、エラーのはずはありません。)宣言(MqlTick、MqlTradeRequest 、MqlTradeResult)までさかのぼってみても、すべて正しく宣言され句読点にも誤りはありません。
次に宣言コード行以前の if 文のコードを見て、文が正しいか確認しましょう。 よく見ると、if文には右中括弧が使われているのに左中括弧がありません。
図12 エラー行番号以前の行に着目&エラー特定
左中括弧を追記し、コードを再びコンパイルします。
//--- Do we have enough bars to work with int Mybars=Bars(_Symbol,_Period); if(Mybars<60) // if total bars is less than 60 bars { Alert("We have less than 60 bars, EA will now exit!!"); return; }
コードがコンパイルされると、 100行目、 107行目、 121行目、 126行目、 129行目などのエラーが消え、新しいエラーが表示されます。これで順を踏まえていくのがよい理由がわかりますね?
図13 その他のエラー
次は 56 行目です。ここにはエラーが2つあります。 「'cciVal1' - パラメータ変換は許可されていません」 と「'cciVal1' - 配列が必要です」です。
56行目をよく見ると、cciVal1 は配列として宣言されるはずだったことがわかります。配列としては宣言しませんでしたが、今から配列として使用することはできるのでしょうか?次の手順に進む前に宣言部を見て、これが可能であるのか確認しましょう。
//--- Other parameters int maHandle; // handle for our Moving Average indicator int cciHandle1,cciHandle2; // handle for our CCI indicator double maVal[]; // Dynamic array to hold the values of Moving Average for each bars double cciVal1,cciVal2[]; // Dynamic array to hold the values of CCI for each bars double p1_close,p2_close; // Variable to store the close value of Bar 1 and Bar 2 respectively
ここで誤ってcciVal1 を動的配列ではなく、実数として宣言してしまっていることに気づきます。角括弧 ([])が抜けているのです。角括弧を追記し(続くcciVal2[]とちょうど同じように)、コードを再びコンパイルします。
//--- Other parameters int maHandle; // handle for our Moving Average indicator int cciHandle1,cciHandle2; // handle for our CCI indicator double maVal[]; // Dynamic array to hold the values of Moving Average for each bars double cciVal1[],cciVal2[]; // Dynamic array to hold the values of CCI for each bars double p1_close,p2_close; // Variable to store the close value of Bar 1 and Bar 2 respectively
図14 コードエラーの大幅減少
なにが起こったのでしょうか。かなりのエラーが消えました。 56 行目のエラーを修正しただけなのに、他のエラーも自動的に解消されました。理由は 56 行目のエラーが他のエラーに影響を与えていたからです。段階的なプロセスを踏まえてエラーを解決していくのはこういうことなのです。
では次にエラー報告があがっている103行目にいきましょう。「'GetLastError' - 宣言されていない識別子」ということです。 ちょっと待ってください。 GetLastError は関数のはずですが。。。とにかく、 103 行目で何が問題なのか見てみましょう。
//--- Get the last price quote using the MQL5 MqlTick Structure if(!SymbolInfoTick(_Symbol,latest_price)) { Alert("Error getting the latest price quote - error:",GetLastError,"!!"); // line 103 return; }
たしかに103行目に問題があります。GetLastErrorは関数ですが、パラメータ入力には関数に括弧が一組必要です。空の括弧を一組入力してコードをコンパイルします。空の括弧は関数が引数やパラメータを取らないことを示すものです。
//--- Get the last price quote using the MQL5 MqlTick Structure if(!SymbolInfoTick(_Symbol,latest_price)) { Alert("Error getting the latest price quote - error:",GetLastError(),"!!"); // line 103 return; }
次は 159行目に進みます。「'=' -左辺値が必要です」 と 警告「論理式がブーレアン形式ではありません」です。では159 行目に移動して、このエラーの意味するところを見て見ましょう。
else if(PositionGetInteger(POSITION_TYPE) = POSITION_TYPE_SELL) // line 159 { Sell_opened = true; // It is a Sell
ここでは、POSITION_TYPE_SELLの値を if文の PositionGetInteger(POSITION_TYPE) に割り付けたように見うけられますが、これは意図したものではありません。割り付けではなく、比較がしたかったのです。 代入演算子ではなく等号演算子 を使う内容に文を書き換えます。(‘=’ではなく、‘==’です。)修正し、コードをコンパイルします。
else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) // line 159 { Sell_opened = true; // It is a Sell
いい感じですね!あと一つです。 292 行目に移動し、「'PositionsTotal' - 宣言されていない識別子」となっている理由を見ていきましょう。ちょっと待ってください。似たようなエラーがあったの、覚えていますか? 103行目の‘GetlastError’です。 PositionsTotal にも括弧をつけ忘れたのかもしれません。これも関数ですから。 ともかく292 行目を見て確認しましょう。
bool CheckTrade(string otyp) { bool marker = false; for (int i=1; i<=PositionsTotal;i++) // line 292 {
疑ったとおりです。関数 PositionsTotalに括弧を付け忘れていたのでした。括弧を一組追記し(PositionsTotal()のように) 、コードを再びコンパイルします。一言付け加えると、このエラーは、コード内でどこにも宣言していない変数を使った場合にも発生する可能性があります。
図15 全コンパイルエラー修正完了
やりましたね!!これですべてのコンパイルエラーを修正できました。次はコードのデバッグをして、ランタイムエラーがないか確認です。ここでは、デバッグ方法の詳しい説明はしません。それについてはすでにこちらの記事で説明済みです。
デバッグセッションが始まると、他のエラーに気づきます。
図16 コードデバッグ時のランタイムエラー
OK をクリックすると、エラー発生行に移動します。
図17 ランタイムエラー発生行の特定
上図のとおり、エラーの原因は 172 行目にあるこのコードです。エラーは「配列が範囲外」 となっています。これは、配列から得ようとしている値は有効な配列の値範囲から外れていることを意味しています。それでは、これからインジケーターバッファを配列にコピーした行に移動し、どんな問題が起こっているか確認しましょう。
//--- Copy the new values of our indicators to buffers (arrays) using the handle if(CopyBuffer(maHandle,0,0,3,maVal)<0) { Alert("Error copying MA indicator Buffers - error:",GetLastError(),"!!"); return; } if(CopyBuffer(cciHandle1,0,0,3,cciVal1)<0 || CopyBuffer(cciHandle2,0,0,3,cciVal2)<0) { Alert("Error copying CCI indicator buffer - error:",GetLastError()); return; }
CopyBuffer 関数からは、配列の値 maVal[0]、 maVal[1]、 そしてmaVal[2] 、また同じくcciVal1[0] 、cciVal1[1] 、cciVal1[2]などにアクセス可能なことを意味する3つの値(バー0、1、2)をコピーしただけであることが見て取れます。けれど、172行目のコードでは配列から値 cciVal1[3]を得ようとしました。これがエラーの原因です。 ここでデバッガーを止め、エラー修正をします。
図18 エラー修正のためデバッガー停止
このエラー修正のためにはインジケーターバッファからコピーするレコード数を5 まで増やす必要があります。そうすることで配列の値 cciVal1[0]、cciVal1[1]、 cciVal1[2]、 cciVal1[3] 、また必要であればcciVal1[4] まで得ることができるようになります。
//--- Copy the new values of our indicators to buffers (arrays) using the handle if(CopyBuffer(maHandle,0,0,5,maVal)<0) { Alert("Error copying MA indicator Buffers - error:",GetLastError(),"!!"); return; } if(CopyBuffer(cciHandle1,0,0,5,cciVal1)<0 || CopyBuffer(cciHandle2,0,0,5,cciVal2)<0) { Alert("Error copying CCI indicator buffer - error:",GetLastError()); return; }
記載どおりにコードを修正し、デバッガーを再起動します。今回は、このEAのトレーディング実行についてこれ以上エラーは認められません。
図19 エラーはすべて修正され、EAはデバッグ時トレードを実行
2. Expert Advisorのテスト
コードにエラーがなくなったことを確認したら、今度はEAが最良の結果を出すための最適な設定の検証をします。検証を行うにはStrategy Testerを使用します。これはMeta Trader ターミナル内に組み込まれたプログラムです。Strategy Testerを起動するには、端末の閲覧メニューから Strategy Testerを選択します。
図20 Strategy Testerの起動
2.1. Expert Advisorの先行検証
ここでは、Market Windowにて使用可能なシンボルを使ってExpertを検証したいと思います。この結果から、どの通貨ペアに対してこのExpertを最適化するのがよいか推測できるようになります。Expertで扱いたいと思っている通貨はほとんどMarket Windowに含まれていることを確認してください。
ストラテジーテスターの 設定 タブからExpertを選択します。想定している期間または時間枠を選択(もちろんその他複数の時間枠でも検証は可能です)、それから最適化フィールドで「MARKET Watchに選択された全シンボル」を選択します。ちょうど正面にあるのが最適化の結果パラメータです。Balance + max Profit Factor(残高+最大プロフィットファクター)を選択します。
図 21 Market Watchウィンドウ内の全シンボルに対する先行検証
1. ティック生成モードを選択:(ティック毎)
2. 最適化タイプを選択 :(MARKET Watch内の全シンボル)
3. 最適化から期待される結果タイプを選択
端末のヘルプから異なる最適化タイプに関する詳細情報を入手可能です。フォワードテストは行いません。よって、Forward(フォワード) はNoのままにします。
本検証に関しては、インプット タブの主要な値/パラメータ(グリーンでマークされているもの)を使用します。
図22 先行検証入力パラメータ
ここまで終えたら、 設定 タブに切り替えて、スタートボタンをクリックします。検証が完了すると、ジャーナルタブに以下のようなメッセージが表示されます。
図23 先行検証完了
検証が完了したら、 最適化結果 タブを開き、結果を確認します。
図24 先行検証最適化結果
気になるのは、今回の設定- (Balance + max Profit Factor)で最も良い結果が出たシンボルはどれかということです。それを知るために、 結果 タイトルをクリックして結果をソートし、結果の最もよかったシンボルがリストの一番上にくるようにします。
図25 先行検証結果分析
この結果からわれわれのEAは、今回選択した時間枠内ではシンボル (EURUSD、EURJPY、AUDUSD) について有益であるということがわかります。 その他の時間枠でさらにこの検証をすることも可能です。例えば、30分足などに設定したら結果はどう出るでしょうか。それは宿題にしますが、皆が知識を深めることができるように、結果はぜひ共有してください。
先行検証の結果から、われわれのEAをどのシンボルについてどの時間枠で最適化するか決定します。
この例では、EURUSD について 1 時間足の時間枠でEAを最適化します。 では、この決定のポイントは何でしょうか。
- プロフィットファクター:
プロフィットファクターとは、その検証における総損失に対する総利益の比を指します。プロフィットファクターが高いほど、トレード戦略は利益性が高いと言えます。
- ドローダウン率:
ドローダウン率とは、相対的な資金の減少、または資金の最高額からの最大損失(パーセント表示)のことを言います。ドローダウン(パーセント)が低いほど、戦略は優れていると言えます。
- リカバリーファクター:
リカバリーファクターとは最大ドローダウンに対する利益の割合を指し、トレード戦略のリスクを示します。
対象とするシンボルと時間枠を決定したら、EAの最適化を行いましょう。
2.2. Eport Advisorの最適化
最適化は、EAに書かれた戦略の有効性や利益性を決定する様々な数値要素(パラメータ)を用いテストすることでEAのパフォーマンスを微調整する作業です。検証に似た作業ですが、検証は一度だけ行われるのに対し、最適化ではインプットタブで選択された複数パラメータについて何度もテストが行われます。
まず、設定タブにを開きます。最適化を有効にしたら、これから行う最適化から導く結果タイプを選択します。
図26 最適化設定
1. ティック生成モードを選択:(ティック毎)
2. 最適化タイプを選択:(遺伝的アルゴリズム)
3. 最適化から期待する結果タイプを選択 (ここでは Balance + Max Profit Factorを選択します。)
ターミナルのヘルプから異なる最適化タイプに関する詳細情報を入手可能です。フォワードテストは行いません。よって、Forward(フォワード)はNoのままにします。最適化のプロパティを設定したので、インプットタブ で最適化のためのパラメータをセットします。
図27 最適化入力パラメータ
今行っているのは最適化ですので、黄色でマークされた箇所にのみ注目します。まず、この最適化に使用したくないパラメータは全てチェックを外します。言い換えれば、EAの最適化に使いたいパラメータのみにチェックを入れます。私はここで5個のパラメータにチェックを入れましたが、みなさんはご自身の戦略が有効に働くよう、1個か2個だけにチェックを入れるかもしれません。例えば、移動平均とCCI期間だけにチェックを入れて、EAが最高のパフォーマンスを行い、結果が選択したインジケーターについて最高値を示すよう設定するでしょう。ここが最適化のポイントです。
また、チェックを入れたパラメータの数によってみなさんのEAが行うテストの合計回数が決まります。今話している内容がどういうことかは、話を進めていくうちにすぐにご理解いただけるでしょう。
値の設定
スタート:
最適化を行うために選択された変数に対して使用される初期値です。 ストップロス変数を使って変数の設定のしかたを説明します。ストップロスに関して、テスターに対し、値30でスタートするよう要求をしました。これは最適化時、ストップロスに用いる最小値です。
ステップ:
ストップロスについての増分値です。増分値を2に設定した場合、最初のテストで30 を使ったら、二度目以降のテストでは32、36、34 などのうち、どれかを使います。30を使った後、32、34 などと使っていくということではありません。値の選択はランダムに行われますが、初期値と最終値の間で使われる値は常に2の倍数となります。
ストップ:
最適化に使用される最大値または最高値を指します。ここでは38を指定しました。これは、テストに使用される値は 30 から 38 で、2の倍数であるということです。40 以上の値が使われることはありません。
実行されるテストの合計回数は、この3か所の設定によります。この例では、 インプット タブのステップ 欄に示されるように、テスターはストップロスだけで合計5回、テイクプロフィットには合計8回行われます。他の変数をすべて選択しようものなら、テスト回数は何百、何千になってしまいます。EAを一つ最適化するまで何年もの時間を費やしたくなければ、あまり多くの変数を選択しないことです。ご自身のEAのパフォーマンスに大きな影響がある2~3の変数に留めるのがよいでしょう(ご自身のコードで使っていれば、特に指標期間)。また、ステップ値があまり多くのテストを行う結果を招かないよう注意も必要です。例をあげれば、ステップ値に1を設定した場合、ストップロスだけでテストの回数は10回まで増えることになります。前にも述べましたが、最適化作業に必要な合計時間はご自身のシステムに設定されている対応可能なエージェントの合計数量に依存します。
説明はこれで十分だと思います。
インプット設定を終えたら、設定タブに戻って、スタートボタンをクリックします。
最適化が完了すると、ジャーナルタブ内で詳細を見ることができます。
図28 ジャーナルタブ表示とおりに最適化完了
各テスト結果を閲覧するには、最適化結果 タブに行きます。結果ごとにアウトプットをソートするのは常にお薦めです。そうすることで、最良の結果をもたらした最適化設定が特定しやすくなります。最適化結果 タブ内の結果見出しをクリックすると、結果を昇順、降順に並べ替えます。
図29 最適化レポート
最適化グラフ タブに切り替え、グラフ表示を確認します。
図30 最適化グラフ
表示が難解ですか?だいじょうぶです。表示のドットは、選択した結果タイプに応じてEAが合格したテストの回数を描画化したものです。この場合は、Balance + max Profit factorが選択されています。
2.3. 結果を読み解く
最適化レポートがうまく読み取れたら、最適化結果タブに移ります。プロフィットファクター、予想支払日、ドローダウン率など、閲覧できないフィールドがあることに気づくでしょう。そういうフィールドを見るには、最適化 タブのどこでもよいので右クリックをして、以下のように見たい追加情報を選択します。
図31 最適化結果でドローダウン率を選択
図32 最適化結果でプロフィットファクターを選択
追加レコードを付け足したので、最適化結果分析を行い、今回のEAに対する最良の設定を判断します。
図33 最適化結果の分析
上図より、A、Bとして協調表示された箇所は、今回のEAに関わる最良の結果を表します。 ここからの選択はすべてみなさん次第です。みなさんが何を求めているかによるのです。ただし、ここでは最高収益を約束する設定だけにとらわれるのではなく、低い ドローダウン率にも着目します。
ご覧のとおり、セクションA (黄色でマークされています)は、利益 924.10で結果 (Balance + max Profit Factor) 22381.71 という最高値を示しています。一方、セクション B (グリーンでマークされています)は、結果の値は22159.25 で第二位です。が、利益は936.55と、セクションAよりも高い値となっています。また、セクションBが1.95という高いドローダウン率を示しているのに対して、セクションA は1.78 というBよりも低い ドローダウン率 に留まっています。
ストラテジーテスターは最適化結果を"<Client terminal data folder>\Tester\cache"フォルダに保存します。みなさんの場合、全最適化データはcci_ma_ea.EURUSD.H1.0.xmlファイルに保存されます。
そのとき、ファイル名は以下の形式となります。ExpertName.SYMBOL.PERIOD.GenerationMode.xml 各、
- ExpertName :専門アドバイザー名
- Symbol :シンボル
- Period : 時間枠 (M1,H1,...)
- GenerationMode :ティック発生モード (0-チック毎、1 - 1分足OHLC、 2 - 始値のみ)
XMLファイルはMS Excelで開くことが可能です。
2.4. 最良結果の選択
最終的に最良の結果を得るために、もう一度最適化グラフを見ましょう。最適化グラフに切り替えます。 グラフ内のどこでもよいので右クリックします。 そうして、1Dグラフを選択します。
図34 一次元(1-D)グラフを選択、結果分析
これで、最良の結果をもたらすインプットパラメータの値を簡単に知ることができます。 最高値を示すパラメータを個別に選択できるようになりました。グラフ上で右クリックし、X軸を選択した後、確認したいパラメータを選択します。ストップロスを例にとると、下記のように表示されます。
図35 最適化結果よりストップロスの最高値を得る
最適化結果からはストップロスが34、テイクプロフィットが78、最高CCI_Period1は62であることがよくわかります。 MAPeriod とCCI_Period2に最高値を得るため、それぞれを上記のように選択します。
図36 最適化結果より移動平均期間の最高値を得る
このグラフでは、MA_Period が最高結果として26という値を示しています。
図37 最適化結果よりCCI_Period1の最高値を得る
このグラフでは、CCI_Period1 の最高結果が62と出ています。
図38 最適化結果よりCCI_Period2の最高値を得る
このグラフでは、CCI_Period2 の最高結果が 28 または 30 と示されています。
それぞれのパラメータに対して最高値を得たところで、EAの最終テストを行います。
2.5. 最終テスト
最終テストは、EAテストで得た最高のパラメータを使って行います。今回の場合は、以下に示すとおりStrategy Tester のINPUTセクションにある最高値を使用します。
図26 最終テストインプットパラメータ
Strategy Testerの 設定タブにて以下のように最適化を無効化します。
図40 最終テストの設定
スタートボタンをクリックし、テストを開始します。テストが完了したら、結果 タブに結果が表示されます。
図41 最終テスト結果
同様にグラフ タブに結果のグラフが表示されます。
図42 最終テストグラフ結果
おわりに
ここでは、コードエラーの特定と修正方法、またMarket Watchから最高のシンボルを判別するためのEAの検証と最適化について述べてきました。
編集機能を用いたコードエラーの確認とストラテジーテスターを用いたEAの最適化と検証によってこれまでにない優れた収益性の高いEAを書くことができると確信してこの項を締めくくりたいと思います。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/156
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索