
実トレーディングにおける売買ロボットの自動最適化
はじめに
履歴に対してインプットが調整されている Expert Advisor は、初回(かなり短く)の利益のためにトレードを行うと想定されています。この考えかたは自動売買トレーディング チャンピオンシップ 2006を見た後で間接的に確認されたようです。「チャンピオンシップ」が開始されたとき、その後、何件かは競争力がないと判明したときに比べ、収益性あるがもっと多くありました。ゴールに 到達しなかった Expert Advisors のほとんどは履歴に対して調整されていたと想定したのはこの理由によります。
実務でこの仮定を確認する考えは、本ウェブサイトのロシア語フォーラム、理想的な自動トレーディングシステムのセクションで生まれました。主旨は日次で EA の最適化を自動でスタートし、その後取得した最適化結果を分析し、EA の変数にそれを記録する、というものです。この考えを実現するため、MetaTrader 4 クライアントターミナルから既成のExpert Advisor と MACD サンプを採り、そこに自分達の自動最適化関数を挿入することにしました。その少しあと、自動オプティマイザのコードは準備ができ、同じフォーラムの 自動オプティマイザセクションにアップロードされました。それから少しのち、自動オプティマイザ部門でこの考えの最初の立証が見られたのです。それからオプティマイザはより良いユーザビリティのために mqh-library に姿を変えたのです。
自動オプティマイザのインストール
以下がこのタスクを行うために必要な事柄です。
- 事前にインストールされインターネットに接続された MetaTrader 4 クライアントターミナルのフォルダに MACD Sample_1.mq4 をコピーします。
- そして、MetaTrader 4 クライアントターミナルとともにそのフォルダーを新規ロケーションにコピーします。
ユーザビリティをよりよくするために、ここから元のターミナルを『ターミナル』、一方コピーを『ターミナルーテスター』と名付けます。H1 タイムフレームで EURUSD についてまずターミナルからの Expert Advisor でチェックテストを行いますが、MACD Sample_1.mq4. はやや変更したものとします。

ターミナルテスターのセットアップ
ターミナルテスターに MACD Sample_1.mq4 をコンパイルすることをお忘れなく。まず、クライアントターミナルを起動します。それからストラテジーテスタを起動し、以下のスクリーンショットにあるようにセットアップします。

最適化は3日間行われます。これは自動最適化を確認するのにかなり十分です。最適化日を次の式に従って『日から』で選択します。すなわち現在日付-3日です。最適化中は、選択されたシンボル(ここのでは EURUSD)に対して必要な履歴がダウンロードされます。
初めて最適化を行う方は MetaTrader 4 クライアントターミナルのヘルプメニュー:<ヘルプ - ヘルプトピック F1 - 自動トレーディング - エキスパート最適化 - 設定> で必要な手順説明を参照することができます。また記事 Testing of Expert Advisors in the MetaTrader 4 Client Terminal: An Outward Glance で読むことができます。
以下のスクリーンショットにある最適化する変数を確認します。

自動最適化は限られた4つの変数を対象としますが、われわれの目的達成と時間の節約には3つで十分です。変数が選択されたら、MACD Sample_1.set という名前の設定ファイルに最適化設定を格納します。このファイルはターミナルテスターの 'tester' フォルダに保存する必要があります。それからプレ最適化を起動し、開始時刻を記憶します。これは現在使用のパラメータによる自動最適化に必要な時間を計算するのに必要となります。この最適化終了後、必要な待ち時間を計算します。その後、このターミナルを閉じます。なぜかというとそれをプログラムで起動することはできないからです。
ターミナル内の Expert Advisor セットアップ
これには、MetaEditor でテスト用 Expert Advisor MACD Sample_1.mq4 を開き、以下を行います。
- 自動最適化の開始時刻を設定します。たとえば、毎日 00:01。
datetime SetHour = 0; // Optimization starting hour; datetime SetMinute = 1; // Optimization starting minute.
- 最適化日数を設定します(プレ最適化で設定したのと同じにします)
int TestDay = 3;
- 最適化終了待ち時間を分で設定します。前に計算したもので、たとえば4分です。
int TimeOut = 4;
- Expert Advisor 名を入力します。
string NameMTS = "MACD Sample_1"; // EA's name
- 設定のある設定ファイル名を入力します。
// Set-file name with the settings string NameFileSet = "MACD Sample_1.set";
- インストール済みターミナルテスターを持つフォルダーへのパスをs入力すます。たとえば以下です。
// Path to the tester string PuthTester = "D:\Program Files\Forex Best Trade Station";
- フィルターの優先順位を設定します。
// Sorting by Maximal profit int Gross_Profit = 1; // Sorting by Maximal profit factor int Profit_Factor = 2; // Sorting by Maximal expected payoff int Expected_Payoff = 3;
- 最適化変数名を書き込みます。
string Per1 = "FastEMA"; string Per2 = "SlowEMA"; string Per3 = "SignalSMA"; string Per4 = "";
- インクルードフォルダにアタッチしたファイル auto_optimization.mqh をコピーします。
- Expert Advisor にライブラリファイルをインクルードします。
//--- Including the auto optimizer's library #include <auto_optimization.mqh>
- あとはご自身の Expert Advisor の start() 関数の冒頭に以下のコードをコピーするだけです。MACD Sample_1.mq4 にはすでに入っています。
// Not to be launched at testing and optimizing if(!IsTesting() && !IsOptimization()) { // Compare the current hour with that preset for launching if(TimeHour(TimeLocal()) == SetHour) { // Protection against restarting if(!StartTest) { // Compare the minute range to the minute // preset for launching if(TimeMinute(TimeLocal()) > SetMinute - 1) { // the range is necessary, in case that for some reasons // no new tick is available for a long time if(TimeMinute(TimeLocal()) < SetMinute + 1) { // Flag of tester launching StartTest = true; TimeStart = TimeLocal(); Tester(TestDay, NameMTS, NameFileSet, PuthTester, TimeOut, Gross_Profit, Profit_Factor, Expected_Payoff, Per1, Per2, Per3, Per4); } } } } } FastEMA = GlobalVariableGet(Per1); SlowEMA = GlobalVariableGet(Per2); SignalSMA = GlobalVariableGet(Per3); TrailingStop = GlobalVariableGet(Per4); // If the tester launching is flagged if(StartTest) { // If more time has elapsed the launching than it was set // to be the test waiting time if(TimeLocal() - TimeStart > TimeOut*60) { // Zeroize the flag StartTest = false; } }
以上です。自動オプティマイザが再度コンパイルされたら、起動することができますが、プレ最適化が行われたのと同一シンボルおよびタイムフレームでしか使用できません。われわれの場合、H1で EURUSD についてです。自動オプティマイザを確認するには、int init () function関数に以下で提供されているコードを挿入します。そうすると、Expert Advisor の起動時に自動オプティマイザが起動します。
Tester(TestDay,NameMTS,NameFileSet,PuthTester,TimeOut, Gross_Profit,Profit_Factor, Expected_Payoff, Per1,Per2,Per3,Per4);
自動オプティマイザの機能
自動オプティマイザはターミナルのチャートにアタッチされた Expert Advisor のパラメータを最適化するためにターミナルテスターを用いることで動作します。このためにプログラムは、ターミナルテスターに対して最適化パラメータ(optimise.ini)を持つプログラムを送信し、最適化モードでターミナルテスターを起動します。そののち、それは取得した "FileReport........htm" の結果をターミナルにコピーし、取得結果から最良値をフィルターにかけます。

自動オプティマイザ機能の詳細
現時点では、たとえば 00.01 で自動オプティマイザを起動する必要があります。変数には値を書き込みます。
// Path to the terminal string PuthTerminal = TerminalPath() + "\experts\files"; // Name of the ini file for the tester string FileOptim = "optimise.ini"; string FileOptim1 = "\optimise.ini"; // Calculation of the starting date datetime DayStart = TimeLocal()-86400*TestDay; // Optimization starting date string DateStart = TimeToStr(DayStart,TIME_DATE); // Optimization ending date string DateStop = TimeToStr(TimeLocal(),TIME_DATE); // Tester report file name string FileReport = "FileReport_" + Symbol() + "_" + DateStop + ".htm"; string FileReport1 = "\FileReport_" + Symbol() + "_" + DateStop + ".htm"; // Limitation for the minimum amount of trades per day double MinTr = TestDay - 2; // Limitation for maximal amount of trades per day double MaxTr = (60 / Period()*TestDay) + 2; // The amount of attempts to copy the report file int KvoPptk = 10; // The amount of lines for sorting int StepRes = 12;
そして文字列配列に ini ファイルのパラメータが書き込まれます。
// Prepare the ini file for optimization ArrayOpttim[0] = ";optimise strategy tester"; // Enable/Disable Expert Advisors ArrayOpttim[1] = "ExpertsEnable = false"; // Name of the EA file ArrayOpttim[2] = "TestExpert=" + NameMTS; // Name of the file containing parameters ArrayOpttim[3] = "TestExpertParameters=" + NameFileSet; // Symbol ArrayOpttim[4] = "TestSymbol=" + Symbol(); // Timeframe ArrayOpttim[5] = "TestPeriod=" + Period(); // Modeling mode ArrayOpttim[6] = "TestModel=" + 0; // Recalculate ArrayOpttim[7] = "TestRecalculate=false"; // Optimization ArrayOpttim[8] = "TestOptimization=true"; // Use date ArrayOpttim[9] = "TestDateEnable=true"; // From ArrayOpttim[10] = "TestFromDate=" + DateStart; // To ArrayOpttim[11] = "TestToDate=" + DateStop; // Report file name ArrayOpttim[12] = "TestReport=" + FileReport; // Rewrite the report file ArrayOpttim[13] = "TestReplaceReport=true"; // Shut down the terminal upon completion ArrayOpttim[14] = "TestShutdownTerminal=true";
最適化パラメータは配列から ini ファイルに記録されます。ini ファイルの作成方法も MetaTrader 4 クライアントターミナルヘルプで確認可能です。<ヘルプ - ヘルプ トピック F1 - ツール - 起動時コンフィギュレーション>を参照ください。
// Write data into the ini file // Find out about the array size OptimArraySize = ArraySize(ArrayOpttim); // Open a file to write opttim = FileOpen(FileOptim, FILE_CSV|FILE_WRITE, 0x7F); if(opttim > 0) { for(int i = 0; i < OptimArraySize; i++) { // from the array into the variable ini = ArrayOpttim[i]; // from the variable into the file FileWrite(opttim, ini); } // close the file FileClose(opttim); } else { Print("Failed writing data into the ini file. Error No ", GetLastError()); return(0); }
ini ファイルにパラメータが記録されると、標準ウィンドウズデリバリにインクルードされた shell32.dll が接続され、ShellExecuteA 関数が起動します。
#import "shell32.dll" //Connect a dll (provided with Windows) int ShellExecuteA(int hwnd,string Operation,string File,string Parameters,string Directory,int ShowCmd); #import
パラメータを持つファイルがターミナルテスターフォルダに送信されます。
// copy the ini file into the tester folder copyini = ShellExecuteA(0,"Open","xcopy", "\"" + PuthTerminal + FileOptim1 + "\" \"" + PuthTester + "\" /y", "", 3); // wait until the file is copied Sleep(1200); if(copyini < 0) { Print("Failed copying ini file"); return(0); }
そしてテスターが起動し、定義済み関数の最適化を始めます。Expert Advisor は最適化中停止状態となります。
// Start Tester start = ShellExecuteA(0, "Open", "terminal.exe", FileOptim, PuthTester, 3); if(start < 0) { Print("Failed starting Tester"); return(0); } Comment("Wait until optimization is complete"); // wait until optimization is complete Sleep(60000*TimeOut);
最適化が完了すると、テスターは自動でレポートファイルに結果を記録します。このファイルはターミナルを持つフォルダにコピーされます。
for(Pptk = 0; Pptk < KvoPptk; Pptk++) { //Start a cycle attempting to compy the resport file Comment("Attempt # " + Pptk + " to copy the report file"); ShellExecuteA(0, "Open", "xcopy", "\"" + PuthTester + FileReport1 + "\" \"" + PuthTerminal + "\" /y", "", 3); // wait until the file is copied Sleep(1200); // Try to open the report file file = FileOpen(FileReport, FILE_READ, 0x7F); if(file < 0) { // if it fails to open, wait some more and try again Sleep(60000); } else break; } if(file < 0) { Print("Failed copying the report file"); return(0); }
そうするとのちの処理に備え、レポートファイルからのデータが文字列配列に入れられます。
// Read from file into the array // Cycle, until the file ends while(FileIsEnding(file) == false) { // Read a string from the report file FileLine = FileReadString(file); // Find the necessary string and set the reference point there index = StringFind(FileLine, "title", 20); if(index > 0) { // Increase the array in size ArrayResize(ArrayStrg, NumStr + 1); // Record the strings from the file in the array ArrayStrg[NumStr] = FileLine; NumStr++; } } // Close the file FileClose(file); // Delete the file in order not to produce too many copies FileDelete(FileReport); // Set the array size by the amount of data read from the file ArrayResize(ArrayData, NumStr); strings .
そして配列内で必要な値が選択されます。
for(text = 0; text < NumStr; text++) { select = ArrayStrg[text]; //------------------------------------------------------------------------- // Reporting text processing (These are apples and oranges) | //------------------------------------------------------------------------- // Position Pass ClStep=StringFind(select, "; \">",20)+4; // Find the end of position ClStepRazm = StringFind(select, "td>", ClStep); // Read the value CycleStep = StringSubstr(select, ClStep, ClStepRazm - ClStep); // Position Profit // Find the beginning of the position GrProf = StringFind(select, "", ClStepRazm); // Find the end of position GrProfRazm = StringFind(select, "td>", GrProf); // Read value GrossProfit = StringSubstr(select, GrProf+4, GrProfRazm - (GrProf + 4)); // Position Total Trades // Find the beginning of position TotTrad = StringFind(select, "", GrProfRazm); // Find the end of position TotTradRazm = StringFind(select, "td>", TotTrad); // Read the value TotalTrades = StringSubstr(select, TotTrad+4, TotTradRazm - (TotTrad + 4)); // Position Profitability // Find the beginning of position ProfFact = StringFind(select, "", TotTradRazm); // Find the end of position ProfFactRazm = StringFind(select, "td>", ProfFact); // Read the value ProfitFactor = StringSubstr(select, ProfFact + 4, ProfFactRazm - (ProfFact + 4)); // Position Expected Payoff // Find the beginning of position ExpPay = StringFind(select, "", ProfFactRazm); // Find the dn of position ExpPayRazm=StringFind(select, "td>", ExpPay); // Read the value ExpectedPayoff = StringSubstr(select, ExpPay+4, ExpPayRazm - (ExpPay + 4)); // Variables' positions starting with the second one // Find the beginning of position P1 = StringFind(select, Per1, 20); // Find the end of position P1k = StringFind(select, ";", P1); // Read the Variable Perem1 = StringSubstr(select, P1 + StringLen(Per1) + 1, P1k - (P1 + 1 + StringLen(Per1))); // Find the beginning of position P2 = StringFind(select, Per2, 20); // Find the end of position P2k = StringFind(select, ";", P2); // Read the Variable Perem2 = StringSubstr(select, P2 + StringLen(Per2) + 1, P2k - (P2 + 1 + StringLen(Per2))); // Find the beginning of position P3 = StringFind(select, Per3, 20); // Find the end of position P3k = StringFind(select, ";", P3); // Read the Variable Perem3 = StringSubstr(select, P3 + StringLen(Per3) + 1, P3k - (P3 + 1 + StringLen(Per3))); // Find the beginning of position P4 = StringFind(select, Per4, 20); // Find the end of position P4k = StringFind(select, ";", P4); // Read the Variable Perem4 = StringSubstr(select, P4 + StringLen(Per4) + 1, P4k - (P4 + 1 + StringLen(Per4))); Comment("The obtained results are being analyzed");
その後、数字形式に変換される前に、取得された結果はトレードの最低額および最高額でフィルターにかけられます。 Profit_Factor 値ゼロは正しく格納し、その後振るい分けをするために1000と置き換えられます。
// Transform into number format TotalTradesTransit = StrToDouble(TotalTrades); GrossProfitTransit = StrToDouble(GrossProfit); ExpectedPayoffTran = StrToDouble(ExpectedPayoff); nodubl = true; if(MinTr < TotalTradesTransit && MaxTr > TotalTradesTransit) { // Filter by the amount of trades PrFactDouble = StrToDouble(ProfitFactor); // Replace 0 in the Profit_Factor for proper analysis if(PrFactDouble == 0) { PrFactDouble = 1000; }
そして値は重複がないか確認され、フィルターにかけられます。
// Filter data having identical values for(Dubl = 0; Dubl <= ResizeArayNew; Dubl++) { // Start the loop searching for identical values if(GrossProfitTransit == ArrayData[Dubl][1]) { // check whether the results for maximal profit coincide if(TotalTradesTransit == ArrayData[Dubl][2]) { // check whether the results for the amount of trades coincide if(PrFactDouble == ArrayData[Dubl][3]) { // check whether the results for Profit Factor coincide if(ExpectedPayoffTran == ArrayData[Dubl][4]) { // check whether the results for expected payoff coincide nodubl=false; // If everything coincides, flag it as coincided } } } } }
ソート用に準備された値が配列に書き込まれます。
// Write the filtered data in the array if(nodubl) { ArrayData[text][1] = GrossProfitTransit; ArrayData[text][2] = TotalTradesTransit; ArrayData[text][3] = PrFactDouble; ArrayData[text][4] = ExpectedPayoffTran; ArrayData[text][5] = StrToDouble(Perem1); ArrayData[text][6] = StrToDouble(Perem2); ArrayData[text][7] = StrToDouble(Perem3); ArrayData[text][8] = StrToDouble(Perem4); ResizeArayNew++; }
データは事前に設定した優先順位で分析開始されます。分析は以下のように行われます。
- ループが起動し、最初のパスで第一パラメータによって値がソートされます。たとえば、最高利益額などです。複数の最良値が選択され(デフォルトでは12)、その他は削除されます。
- 第二のパスでは、値は2番目のパラメータによってソートされます。たとえば、プロフィットファクターです。最初のソートの半分にあたる最良値がいくつか選択され、残りは削除されます。
- 第三のパスでは、3番目のパラメータについて最終ソートが行われます。たとえば予想ペイオフです。2番目のソート後の半分の値が残り、あとは削除されます。
// Analyzer // Analyzing principle is the sequential checking of maximal // values according to the predefined filtering priority ArrayResize(ArrayTrans, ResizeArayNew - 1); for(int PrioStep = 1; PrioStep < 4; PrioStep++) { for(PrCycle = 0; PrCycle < ResizeArayNew; PrCycle++) { Sort = ArrayData[PrCycle][0]; Prior1 = ArrayData[PrCycle][1]; transit = ArrayData[PrCycle][2]; Prior2 = ArrayData[PrCycle][3]; Prior3 = ArrayData[PrCycle][4]; transit1 = ArrayData[PrCycle][5]; transit2 = ArrayData[PrCycle][6]; transit3 = ArrayData[PrCycle][7]; transit4 = ArrayData[PrCycle][8]; if(PrioStep == 1) { //Prepare for the 1st sorting if(Gross_Profit ==1) { SortTrans = Prior1; } if(Profit_Factor == 1) { SortTrans = Prior2; } if(Expected_Payoff == 1) { SortTrans = Prior3; } } if(PrioStep == 2) { // Restore if(Gross_Profit ==1) { Prior1 = Sort; } if(Profit_Factor == 1) { Prior2 = Sort; } if(Expected_Payoff == 1) { Prior3 = Sort; } //Prepare for the 2nd sorting if(Gross_Profit == 2) { SortTrans = Prior1; } if(Profit_Factor == 2) { SortTrans = Prior2; } if(Expected_Payoff == 2) { SortTrans = Prior3; } } if(PrioStep == 3) { // Restore if(Gross_Profit == 2) { Prior1 = Sort; } if(Profit_Factor == 2) { Prior2 = Sort; } if(Expected_Payoff == 2) { Prior3 = Sort; } //Prepare for the 3rd sorting if(Gross_Profit ==3) { SortTrans = Prior1; } if(Profit_Factor == 3) { SortTrans = Prior2; } if(Expected_Payoff == 3) { SortTrans = Prior3; } } ArrayTrans[PrCycle][0] = SortTrans; ArrayTrans[PrCycle][1] = Prior1; ArrayTrans[PrCycle][2] = transit; ArrayTrans[PrCycle][3] = Prior2; ArrayTrans[PrCycle][4] = Prior3; ArrayTrans[PrCycle][5] = transit1; ArrayTrans[PrCycle][6] = transit2; ArrayTrans[PrCycle][7] = transit3; ArrayTrans[PrCycle][8] = transit4; } ArraySort(ArrayTrans,StepRes, 0, MODE_DESCEND); // Sort the array ArrayResize(ArrayTrans, StepRes); // Cut off the unnecessary things for(int CopyAr = 0; CopyAr < StepRes; CopyAr++) { ArrayData[CopyAr][0] = ArrayTrans[CopyAr][0]; ArrayData[CopyAr][1] = ArrayTrans[CopyAr][1]; ArrayData[CopyAr][2] = ArrayTrans[CopyAr][2]; ArrayData[CopyAr][3] = ArrayTrans[CopyAr][3]; ArrayData[CopyAr][4] = ArrayTrans[CopyAr][4]; // Per1 Variable 1 ArrayData[CopyAr][5] = ArrayTrans[CopyAr][5]; // Per2 Variable 2 ArrayData[CopyAr][6] = ArrayTrans[CopyAr][6]; // Per3 Variable 3 ArrayData[CopyAr][7] = ArrayTrans[CopyAr][7]; // Per4 Variable 4 ArrayData[CopyAr][8] = ArrayTrans[CopyAr][8]; } StepRes = StepRes / 2; }
この方法でフィルターにかけられた値がグローバル変数に書き込まれます。グローバル変数の値は EA に代入されます。
// Write the obtained results in variables double Peremen1 = ArrayTrans[0][5]; double Peremen2 = ArrayTrans[0][6]; double Peremen3 = ArrayTrans[0][7]; double Peremen4 = ArrayTrans[0][8]; // If the variable name is specified, write the result in // global variables if(Per1 != "") { GlobalVariableSet(Per1, Peremen1); } if(Per2 != "") { GlobalVariableSet(Per2,Peremen2); } if(Per3 != "") { GlobalVariableSet(Per3,Peremen3); } if(Per4 != "") { GlobalVariableSet(Per4,Peremen4); } Comment(Per1, " ", Peremen1, " | ", Per2, " ", Peremen2, " | ", Per3, " ", Peremen3, " | ", Per4, " ", Peremen4); Print(Per1, " ", Peremen1, " | ", Per2, " ", Peremen2, " | ", Per3, " ", Peremen3," | ",Per4," ",Peremen4); } // Function ends. 以上です。自動最適化は完了です。
自動オプティマイザ処理結果
自動オプティマイザの処理結果は以下のスクリーンショットにあるように、チャートの左上に表示されるメッセージで見ることができます。
最適化結果がメッセージに表示されると、最適化が完了しデータが受け取られたことを意味します。
個別に自動オプティマイザの動作を推定するには、中央値を持ち動作プロセスで保存されたファイルをすべて調べます。テスターは "FileReport_EURUSD_2007.03.12.htm" という名前のファイルにデータを格納します。ここで、シンボルとデータが選択されたシンボルと現在の最適化日付に応じてファイル名に代入されます。このファイルはターミナルテスターフォルダにあります。レポートを持つこういったファイルは自動的に削除されます。よってパラメータ変化のチェックにそれらを利用することができます。

次のファイル FileTest1.csv はトレード金額によって値がフィルターにかけられ、コピーが削除されたあとに保存されます。ファイルは D:\Program Files\terminal_folder_ame\experts\files に保存されます。

それから各ふり分けステップ後に取得した値は FileTest2.csv に保存されます。ファイルは次のフォルダにも保存されます。:D:\Program Files\terminal_folder_name\experts\files

上記テーブルは取得値がどのようにフィルターにかけられるか示しています。フィルターにかける順序はデフォルトでは次のように設定されています。:1- Gross_Profit、2- Profit_Factor、3- Expected_Payoff.
自動オプティマイザのコードには詳しいコメントが入っており、必要に応じてもっとも適した変数パラメータを固定することができます。たとえば、直近日付以外の期間に対してを最適化したい、または最適化期間中のトレード額を増やす/減らす予定をしているなど。このためには auto_optimization.mqh 内で対応する値を直接変更するだけです。
// Limitation of minimal amount of trades per day double MinTr = TestDay - 2; // Limitation on maximal amount of trades per day double MaxTr = (60 / Period()*TestDay) + 2; // The amount of attempts to copy the report file int KvoPptk = 10; // The amount of strings to be sorted int StepRes = 12;
おわりに
本稿は初心者に Expert Advisor 最適化のエレメントを教えることを目的としているのではありません。よって、の自動最適化を設定する前に通常の最適化を学習することを強くお薦めします。異なる時間に違った影響を Expert Advisor に与える基本的な変数を選択してから自動オプティマイザを使用する方がよいのです。すなわち、マーケットの変動に応じて他の変数よりも EA 処理に影響をあたえる変数のパラメータを固定するためにこの自動オプティマイザを使用するほうがよいのです。
そのうえ、あまり大きな最適化期間は設定しないようがよいものです。Expert Advisor が毎日6~12 時間最適化されるとします。そうするとある疑問が出ます。:それは何をトレードするのか?別の言い方をすれば、最適化はそれ自体としては必要ないのです。EA がトレードを行うとされるタイムフレームを考慮して、最適化の周期(最適化起動周期を意味します)を設定することをお薦めします。これはテスターターミナルの起動時、履歴データが大量に投入されることを考慮する必要があり、ブローカーは指定の時期に対する履歴データを必要な分所有しない可能性があることを意味します。本稿の冒頭で述べた仮定を検証するには、24時間の安定したインターネット接続が必要となるでしょう。
作成された自動最適化プログラムは、添付ファイル内:auto_optimization.mqh にあります-ライブラリ自体、MACD Sample_1.mq4 -MetaTrader 4 クライアントターミナル標準発送セットに入っているやや変更された Expert Advisor。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/1467





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索