![多通貨エキスパートアドバイザーの開発(第7回):フォワード期間に基づくグループの選択](https://c.mql5.com/2/74/Developing_a_multi-currency_advisor_yPart_7c_600x314.jpg)
多通貨エキスパートアドバイザーの開発(第7回):フォワード期間に基づくグループの選択
はじめに
以前の記事では、2018年から2022年という同じ期間について、個々の取引戦略を最適化してきました。これはかなり長い期間であり、価格ダイナミクスに影響を与えるさまざまな出来事が含まれていることは間違いません。その一方で、大きすぎず、1回の実行時間は数十秒以内と十分に小さいです。選択された期間は、現在の時点までまだ1年以上残っているように配置されます。これにより、戦略のパラメータを最適化する際に使用しなかった履歴のセクションで、戦略のインスタンスがどのように動作するかを確認することができます。
標準的なMetaTrader 5のテスターは、いわゆるフォワード期間の存在を考慮に入れたシングルパスと最適化を実行することができます。これを使用する場合、テスターは指定されたテスト期間全体をメイン期間とフォワード期間の2つに分割します。メイン期間が終了すると、すべての取引が終了し、取引口座の残高は初期状態に戻されます。その後、EAはフォワード期間で再び作動し、テスターによって収集されたすべての統計は、メイン期間とフォワード期間で別々に計算されます。
機械学習の分野では、In-SampleとOut-Of-Sample(ISとOOS)という用語は、モデルが訓練されテストされたデータセットを指すのによく使用されます。私たちのエリアでは、メイン期間がISの役割を果たし、フォワード期間がOOSとなります。OOSはフォワード期間よりも広い概念であることに留意してください。テスターでフォワード期間を指定せずにEAテストを実行することは可能ですが、テスト期間が最適化が実施された期間外にある場合、これは依然としてOOSでのテストとなります。
これまでOOSテストは(この記事の最後を除いて)あまり使用してこなかったので、メイン期間のEAが示したように、フォワード期間での作業でも同等の結果を維持することが可能かどうかを確認する必要があります。
既製EAのフォワード期間
前回の記事から、手動で選択した戦略のグループと、最大利益に基づいて自動的に選択した戦略の最良グループについて、EAが示した結果を見てみましょう。2023年全体をフォワード期間とします。2024年の3ヶ月は、今のところ予備として残しておきます。私が達成したい結果は、フォワード期間がメイン期間より約5倍短いことです。フォワード期間がメイン期間の5分の1短いためです。フォワードのドローダウンは、メイン期間とほぼ同じかそれ以下であることが望ましいです。
手動で選択した戦略のグループ(BaselineExpert.mq5 EA)から始めましょう。青い線の垂直部分は、グラフ上でメイン期間とフォワード期間を明確に分けています。この境界では、口座残高は再び10,000米ドルに等しくなります。フォワード期間に関する部分は、グラフ全体のごく一部を占めているに過ぎません。さらに詳しく検証する必要がある場合は、ここでいうフォワード期間と呼ばれる時間間隔に対してのみ、別のテスターパスを実行することができます。
メイン期間
フォワード期間
図1:BaselineExpert.mq5メイン期間とフォワード期間のEA結果
この場合、フォワード期間の別個のパスがなくても、結果が大幅に悪化していることがはっきりわかります。しかし、これは戦略の完全な破綻を意味するものではありません。ドローダウンは10%から12%に増加し、回復期間は6ヶ月以上に及びます。しかし、これはまだバランスカーブのトレンドの逆転ではありません。それとも逆転でしょうか。どう考えても、結果は改善が必要です。
クラスタリングセットなしで選択された最良のグループ (OptGroupExpert.mq5 EA)を見てみましょう。
メイン期間
フォワード期間
図2:OptGroupExpert.mq5メイン期間とフォワード期間のEA結果
この戦略グループの場合、フォワード期間終了時にわずかな利益が出たにもかかわらず、結果も予想を大幅に下回っています。ドローダウンはほぼ1.5倍になりました。メイン期間の最良グループは、フォワードの最良グループよりも長くないようです。
パラメータセットのクラスタリングで選択されたグループ(OptGroupClusterExpert.mq5 EA)の結果を見てみましょう。ただ、すでに前の2つのケースとほぼ同じ結果になる疑いが強いです。
メイン期間
フォワード期間
図3:OptGroupClusterExpert.mq5メイン期間とフォワード期間のEA結果
実際、疑念が的中しました。ここでの結果も同様に不明確で、ドローダウンはさらに大きくなります。したがって、1つのクラスタに1セットしか残っていない、ファイルから選択された最良グループの結果は紹介しません。ほぼ同じです。
では、フォワード期間で期待通りの結果を残したグループはあるのでしょうか。この問いに答えるため、前回の最適化で得られたパラメータセットの全グループについて、テスターでEAを前進期間中に手動で起動しないように、前進期間を設けて新たな最適化を実施します。
フォワード期間を用いた最適化結果
そこで、OptGroupClusterExpert.mq5 EAについて、フォワード期間による最適化結果を得ました。使用したパラメータセットファイルは、64のクラスタごとに1セットずつあるファイルです。最適化結果の初期分析には、普通のExcelで十分でしょう。メイン期間とフォワード期間の最適化結果をXMLファイルにエクスポートし、Excel形式で保存してみましょう。
図4:メイン期間(IS)とフォワード期間(OOS)の最適化結果のソースファイル
フォワード期間用のファイルにはBack Result列があり、同じ最適化パラメータセットでメイン期間に得られた結果が含まれています。これは良いことですが、メイン期間の他の特徴もすべて隣に並べます。そこで、この2つのテーブルのデータをPassキー列で1つにまとめます。この列の同じ値は、パスの同じ入力の組み合わせに対応します。
統合後、メイン期間とフォワード期間に関連するデータに異なる色をつけ、一部の列を一時的に非表示にし、メイン期間の正規化利益の降順でデータを並び替えます。
図5:メイン期間とフォワード期間の合算結果
メイン期間の成績が最も良かった場合、フォワード期間の成績はほとんどがマイナスであることは明らかです。結果は決して悲惨なものではありません(年間初期残高の3~5%を失う)が、良くないことは確かです。
Forward Result列とBack Result列の値を取得する方法を思い出してみましょう。これは、合格後にEAが返すOnTester()関数の結果です。この値を正規化利益と呼び、次のように計算します。
Result = Profit * (10% / EquityDD)
ここでProfitはテスト期間中に得た利益、EquityDDはテスト期間中の資金の最大相対ドローダウンです。
この計算値の意味は、最大相対ドローダウンが10%になるように建てたポジションのサイズを変更した場合に得られるテスト期間中の推定利益です。
フォワード期間とメイン期間に同じポジションスケーリング係数を使用すると、パラメータ結果を正しく比較できます:coeff = (10% / EquityDD).この比率をフォワードテスト中のメイン期間の値として求めることには問題があるので、今そのような調整をしておきましょう。変換式は次のようになります。
ForwardResultCorrected = ForwardResult * (coeff_IS / coeff_OOS)
= ForwardResult * (EquityDD_OOS / EquityDD_IS)
調整後、以下の結果が得られました。
図6:フォワード期間の正規化利益を再計算した結果
フォワード期間の成績の絶対値が上昇していることがわかります。これは以下の理由から正しいです。例えば、メイン期間の2つ目のパラメータを取ったとしましょう。ドローダウンが1.52%であったことから、目標ドローダウン10%を達成するためにポジションサイズを10 / 1.52 = 6.58倍にします。もし、まだフォワード期間について何も知らないのであれば、ポジションのサイズも6.58倍にしなければなりませんが、この場合、フォワード期間で受け取った利益が-98であったとすると、正規化された利益は、利益に同じ比率6.58を乗じて計算されるべきです。つまり、-240ではなく、-635となります。240の値が小さかったのは、フォワード期間のドローダウンがほぼ3倍(1.52%ではなく4.03%)大きかったためで、正規化利益を計算すると、比率は10÷4.03=2.48、つまりほぼ3倍小さくなりました。
結果はあまり喜ばしいものではありません。もっと励みになることを探しましょう。まず、フォワード期間でポジティブな結果が出たかどうかを見てみましょう。Forward Result Correctedの列でデータを並び替えてみましょう。
図7:フォワード期間の結果で並び替えられた結果
それでも、フォワード期間でも好結果を残しているセットグループもあります。これらのグループは、主力期間中に約15,000~18,000の標準利益が達成されるグループに相当します。この場合、ドローダウンはメイン期間とフォワード期間であまり変わらず、フォワード期間の正規化利益はメイン期間の正規化利益の約5分の1であることがわかります。
では、良いグループを選ぶことは可能なのでしょうか。
哲学的な質問
実は、これはとても難しい質問です。それはさまざまな方法で定式化することができます。次は例です。
- フォワード期間を考慮した選択を利用する権利はあるのか。
- そのような選択によって、同じような結果を得続けられると期待するならば、私たちは自分自身を馬鹿にしているのではないのか。
- そんな選択をどこまで信用できるのか。
- フォワードを考慮したグループを選択した場合、フォワードを考慮しないグループを選択した場合と比べて、新しい期間においてフォワードの結果は明らかに良くなるのか。
- この結果は、今後どの期間で繰り返されるのか。フォワード期間と比較可能か。
- 例えば毎年同じような選考をおこなった場合、次の年も常に良いメンバーが揃うということなのだろうか。半年はどうか。毎週はどうか。
これらは共通の土台を持ちながらも、異なる側面に触れています。
これらの疑問に何とか答えようとするために、ベイズのアプローチを思い出してみましょう。まず、一連の仮説(または仮定)を立て、新しいデータを受け取る前にその確率を評価します。実験をおこなった後、新しいデータを考慮して推定値を更新します。ある仮説は可能性が高くなり、他の仮説は可能性が低くなるように見えます。ここでは、確率をある事象の結果に対する確信の度合いとして考えます。
主な仮説は以下の通りです。フォワード期間を考慮してグループを選択することで、フォワード後の期間で得られる結果が改善されます。対立仮説:フォワード期間を考慮したグループ選択は結果を改善しない。
可能な実験としては、フォワード期間を考慮したいくつかのグループと、フォワード期間を選択しないいくつかのグループを選択することです。次に、フォワード後の期間に選択された全グループをテストします。
もし、フォワード期間を考慮して選択したグループが、フォワード期間を考慮せずに選択したグループよりも成績が良ければ、これは主仮説を支持する弱い証拠となります。主仮説の妥当性に対する信頼は高まるでしょう。
もしフォワード期間を考慮せずに選択したグループの結果がほぼ同じかそれ以上であれば、これは対立仮説を支持する弱い証拠となります。同時に、どの戦略グループがフォワード後の期間に示した結果も、グループへの選択方法以外の多くの要因に左右されるため、どの仮説も完全に否定することはできません。単に、使用されている戦略にとって全体的に悪い時期であっただけかもしれないし、それゆえ、戦略をグループに選択する1つまたは別の方法が、顕著な効果を生み出さなかったかもしれません。
おそらく、これ以上の余裕はないでしょう。
この「フォワード期間を考慮」という表現は、少し間違って理解されているかもしれません。フォワード期間を考慮したセレクションを適用した場合、フォワード(OOS)期間であったものは、引き続きフォワード期間と呼びながらも、OOS期間でなくなり、IS期間となります。つまり、取引結果を評価するには、新しいフォワード期間(フォワードの後にフォワードが続く、トートロジーで申し訳ない)を使用する必要があります。
追加情報を得るために実施したい実験について、もう少し詳しく説明しましょう。2018年から2023年までの履歴データがあるとしましょう。これらに基づいて、2024年に良い結果を示す戦略グループを選択します。そうすれば、2つの方法があります。
- 2018年から2023年(IS)の期間で最適化を実施し、その結果に基づいて最適なグループを選択します。
- 2018-2022年(IS)に最適化をおこない、同時に2023年(OOS)のフォワード期間の検証をおこないます。両期間において、良好でほぼ同様の結果をもたらす最良のグループを選択します。
2つ目の方法では、1つ目の方法と同じグループは選択しない可能性が高くなります。その結果は多少悪くなりますが、最適化に参加しなかったOOS期間は1年続きました。最初の方法では、ISの期間外はチェックしていないので、選択されたグループについてこのようなことを言うことはできません。しかし最初の方法では、より長い期間にわたってグループを最適化(訓練)しました。2番目の方法では、2022年を将来の期間に割り当て、最適化には使用しない必要があったためです。
どちらの方法が良いでしょうか。このような実験を、2024年の取引時に2つの方法で選択したグループの結果を比較することでおこなってみましょう。
最初の方法で選択する
最初の方法で選択するためには、まず、2018年から2023年までの戦略のコピーを1つ最適化する必要があります。これまでは、2023年を含めずに2022年までの期間で最適化を実施していました。最適化の後、前回の記事で説明したように、クラスタに分割されたパラメータのセットが得られます。そして、8つのパラメータセットから良いグループを選択するために最適化を実行します。2018年から2023年、2024年の期間で、最も優れたセットグループの結果を見てみましょう。
図8:2018年~2023年のメイン期間でグループを選択するOptGroupClusterExpert.mq5の最適化結果
図9:OptGroupClusterExpert.mq5による2024年3ヶ月間のグループ選択結果
2018年から2023年のメイン期間で発見された最良グループは、2024年のフォワード期間でも概ね良好な結果を示しているが、互いにかなり大きな差があることがわかります。より徹底的なチェックのために、一番上のグループを選択し、スケーリングファクター値scale_= 10 / 2.04 = 5を割り当て、2023年のメイン期間と2024年のフォワード期間でテスターを実行します。
2023
2024年(3ヶ月)
図10: OptGroupClusterExpert.mq5 2023年と2024年の最適グループのEA結果
これらの結果から、このような一連の戦略パラメータセットを使用して、EAの今後の動作の見通しを具体的に評価することはできませんが、少なくとも2024年のバランスカーブの減少に向けた明確な傾向の始まりは見られませんでした。この結果を覚えておいて、後で2番目の選択法で得られた結果と比較してみましょう。
2番目の方法による選択
2023
2024年(3ヶ月)
図11: 2023年と2024年のOptGroupClusterExpert.mq5のEA結果
2023年のドローダウンは、本試験期間の計算値をほぼ2倍上回っています。1000米ドルの代わりに1820米ドル。
2023年をフォワード期間として考慮しながら、以下のアルゴリズムでグループ分けをおこないます。
- 2018年~2022年(メイン期間)と2023年(フォワード期間)の最適化結果の組み合わせ表で、すべてのパラメータについて、メイン期間とフォワード期間における値の比率を計算します。例えば、取引回数の場合:
TradesRatio = OOS_Trades / IS_Trades
これらの比率が1に近ければ近いほど、これらのパラメータの値が2つの期間でより同一であることを意味します。利益パラメータについては、異なる期間長を考慮した比率を導入します。1年後の利益は5年後の利益の約5倍であるべきです。
ResultRatio = OOS_ForwardResultCorrected* 5 / IS_BackResult - これらの関係すべてについて、単一性からの偏差の和を計算してみましょう。この値が、各グループのメイン期間とフォワード期間の成績の差を示す指標となります。
SumDiff = |1 - ResultRatio| + ... + |1 - TradesRatio| -
また、ドローダウンはメイン期間とフォワード期間の各パスで異なる可能性があることを考慮に入れてください。2つの期間から最大ドローダウンを選択し、それを使用して、標準化されたドローダウンの10%を達成するために建てたポジションのサイズに対するスケーリン グ係数を計算します。
Scale = 10 / MAX(OOS_EquityDD, IS_EquityDD)
-
ここで、ScaleがSumDiffよりも優勢なセットを選択します。そのためには、最後のパラメータを計算します。
Res = Scale / SumDiff
-
すべてのグループを、前のResステップで計算された値で降順に並び替えます。この場合、メイン期間とフォワード期間の成績がより似通っており、両期間のドローダウンが小さかったグループが上位に入ります。
- 一番上のグループを最初のグループとしましょう。次のグループを選択するには、最初のグループと同じクラスタインデックスを持つすべてのグループを並び替え、最後に一番上に来るものを再び選択します。これを2、3回繰り返し、前回選択したグループに含まれるすべてのインデックスを整理してみましょう。その結果できた4つのグループを新しいEAに採用します。
OptGroupClusterExpert.mq5EAに基づいて選択されたグループの連携をテストするには、新しいEAを作成し、それに若干の変更を加えます。EA は最適化のために使用されることはないので、OnTesterInit()関数とOnTesterDeinit()関数をEAから削除することができます。また、グループに含めるパラメータセットのインデックスを指定する入力は、実行された選択手順に基づいてコードにハードコードされるため、削除することもできます。
OnInit()関数で、選択されたグループ用のstrGroupsと、グループ倍率用のscalesという2つの配列を作成します。strGroups配列の要素は、パラメータセットのインデックスをカンマで区切った文字列です。
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Load strategy parameter sets int totalParams = LoadParams(fileName_, params); // If nothing is loaded, report an error if(totalParams == 0) { PrintFormat(__FUNCTION__" | ERROR: Can't load data from file %s.\n" "Check that it exists in data folder or in common data folder.", fileName_); return(INIT_PARAMETERS_INCORRECT); } // Selected set groups string strGroups[] = {"55,12,3,35,48,54,16,40", "11,54,33,30,62,6,10,23", "50,15,8,34,2,36,4,9", "26,42,25,22,36,51,53,0" }; // Scaling factors for selected set groups double scales[] = {4.16, 3.40, 3.33, 2.76 }; // Set parameters in the money management class CMoney::DepoPart(expectedDrawdown_ / 10.0); CMoney::FixedBalance(fixedBalance_); // Create an EA handling virtual positions expert = new CVirtualAdvisor(magic_, "SimpleVolumes_OptGroupForwardCluster"); CVirtualStrategyGroup *groups[ArraySize(strGroups)]; FOREACH(strGroups, { // Form the string from the parameter set indices separated by commas string strIndexes = strGroups[i]; // Turn the string into the array string indexes[]; StringSplit(strIndexes, ',', indexes); // Create and fill the array of all strategy instances CVirtualStrategy *strategies[]; FOREACH(indexes, { // Remove the cluster number from the parameter set string string param = CSVStringGet(params[StringToInteger(indexes[i])], 0, 11); // Add a strategy with a set of parameters with a given index APPEND(strategies, new CSimpleVolumesStrategy(param)) }); // Add the strategy to the next group of strategies groups[i] = new CVirtualStrategyGroup(strategies, scales[i]); }); // Form and add the group of strategy groups to the EA expert.Add(CVirtualStrategyGroup(groups, scale_)); return(INIT_SUCCEEDED); }
このコードを現在のフォルダのOptGroupForwardClusterExpert.mq5ファイルに保存します。
EAのテスト結果を見てみましょう。前回と同様、2023年と2024年の最初の3ヶ月間という2つの期間を1つのパスにまとめます。
2023
2024年(3ヶ月)
図12: 2023年と2024年のOptGroupClusterForwardExpert.mq5のEA結果
ここでは、2023年の結果の方が明らかに優れています。3月から7月にかけては、バランスカーブが有意な伸びを示さなかった期間もありますが、全期間を通じて上昇傾向が観察されます。この期間のドローダウンも改善され、予想される最大限度内に収まっています。
2024年の結果も良いですが、特に驚くべきものではありません。おそらく、3ヶ月という期間は、数年という長い期間のグラフを美しく見せるには短すぎます。
これらの結果を、良いグループを選ぶ最初の方法の結果と比較してみると、いずれの方法にも明確な優位性はまだ見られません。結果はおおむねよく似ていますが、2番目の方法は1番目の方法と比べ、より多くの労力を必要としました。ただし、2つ目の選択法の動作アルゴリズムを明確に示したので、将来的には自動化できるでしょう。
結論
見てわかるように、実施した実験では、フォワードとして追加期間を割り当て、両期間でのベストワークを考慮してグループを選抜する方が良いという確信を深めることはできませんでしたが、この方法を使用するべきではないということではありません。その上、比較のために2024年からの三ヶ月しか使用していません。というのも、使用されている取引戦略では、残高がゼロ付近で変動する期間が数ヶ月に及ぶことがあるためです。したがって、2024年の最初の3ヶ月間がそのような時期の始まりとなるのか、その後成長に取って代わられるのか、あるいはまったく成長しないのか、はっきりしません。
期間を1年ずらして同様の実験をしてみることもできます。この場合、メイン期間は2017年に始まり、2番目の方法による選考は2022年に実施され、2つの方法の比較のために2023年中と2024年初頭に実施されます。
しかし、私たちはさらに前進します。最初の方法を使用してグループの一部を選択し、2番目の方法を使用して他のグループを選択し、それらを1つのEAに結合することを妨げるものは何もありません。しかし、1つのEAに組み合わせることができる取引戦略インスタンスの最大数はいくつでしょうか。その結果、EAの動作に必要なサーバーリソースが増えすぎたり、異常に大量のRAMが必要になったりすることはないでしょうか。この問題については、次の記事で明らかにしたいと思います。
ご清聴ありがとうございました。
追記この記事の準備中、以前に作成したファイルに変更は加えていません。新しいファイルは1つだけ追加しました。下に添付しているのはこれだけです。その他のファイルについては、前回の記事で紹介しています。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/14549
![MQL5で日次ドローダウンリミッターEAを作成する](https://c.mql5.com/2/83/Creating_a_Daily_Drawdown_Limiter_EA_in_MQL5___LOGO.png)
![MQLプロジェクトでJSON Data APIを使用する](https://c.mql5.com/2/83/Using_Json_Data_API_in_your_MQL_projects__LOGO.png)
![知っておくべきMQL5ウィザードのテクニック(第26回):移動平均とハースト指数](https://c.mql5.com/2/83/MQL5_Wizard_Techniques_you_should_know_Part_26__LOGO2.png)
![MQL5 - MetaTrader 5クライアントターミナルにビルトインされたトレードストラテジーの言語](https://c.mql5.com/i/registerlandings/logo-2.png)
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索