トレンドとフラットの戦略を個別に最適化する

Alexander Fedosov | 11 2月, 2019

目次


概論

初期段階での取引戦略の開発において、市場参入のための条件、ポジションをサポートする方法、および決済の瞬間を定式化するというタスクが発生することは秘密ではありません。この目的のために、インジケータの形で市場の特性を評価するために使用される既製の自動システムと同様に、様々な数学的、統計的および他の市場評価方法が使用されています。取引戦略を構築する際の主な問題の1つは、普遍性の欠如です。取引システムは、絶対にすべての市場状況において等しく効果的に機能することはできません。したがって、通例として、エキスパートアドバイザを作成するときには、そこから利益を引き出すことが計画されている特定の市場条件を検出するための条件を選択します。 

また各取引システムには、それぞれに欠点があることも知られています。そのため、トレンド戦略は長期にわたるフラットまたは穏やかな市場状況ではうまく機能せず、フラット戦略は強い動きがあった場合などに、間違った参入など起こしてしまいます。誤ったシグナルの影響を減らして収益性を向上させるために、システムは柔軟に作られています。つまり、市場や市場の状態は常に変化を伴う為、システムには特定の設定や入力データのセットがあります。

時間が経つにつれて、どの取引システムもそれほど効果的ではなくなるので、そのパラメータを新しく現状に適応させる必要があります。この目的のためにMetaTrader 5取引プラットフォームには、ストラテジーテスターがあります。このツールは、市場の履歴からエキスパートアドバイザのパフォーマンスを分析し、のちに実際の取引の基礎として使用するのに最適な設定を決定するのに役立ちます。


個別最適化の概念

この記事では、ストラテジーテスターツールの使用をより広い意味で検討することを提案します。明らかに、市場のシステムの大部分は2つの方向で取引されており、どちらも特定の条件下で買われ、そして売られています。図1は、理想的なトレンド取引戦略の動きの簡単な例を示しています。その本質は簡単なもので、私たちは安値で買い、高値で売ります。


図1はトレンド取引戦略の概要

通常、このようなシステムでは、上昇トレンドと下降トレンドを決定するために同じ設定のセットが使用され、入力条件が反映されます。しかし、肝心なのは、スピードと期間など、多くの特性において、市場の成長と衰退の内容が大きく異なる可能性があることです。これに関連して、上昇トレンドおよび下降トレンド時の市場参入を決定するために、別個のシステムの選択肢を検討することを検証します。

これには、市場への出入りの条件を定義する2セットのパラメータが必要です。そしてここで我々はまさしく『個別最適化』の概念に至ります。

個別最適化とは、ストラテジーテスターを使用して上昇トレンドと下降トレンドを別々に使用したトレーディングシステムの最適パラメータを決定することです。

個別最適化をテストするために、2つの取引システムを選択することにしました。このトレンドシステムでは、上昇トレンドと下降トレンドを別々に最適化し、横ばいのチャネルでは、チャネル内の取引の別々の最適化を推定します。 


トレンド取引戦略の選択

個別最適化のテストで使用されるストラテジーとして次のものを選択しました。これは、CenterOfGravityOSMAというOSMAヒストグラムの形式で表示された、Ellers Center of Gravityシグナルを使用します。このシグナルは、平均価格レートAverage Speedを計算するシグナルによって確認されます。

パラメータ説明
使用したインジケータCenterOfGravityOSMA
使用したインジケータAverage Speed
時間枠H1
買い条件Ellers Center of Gravityシグナルは成長を示し(インジケータ値はゼロより小さい)、Average Speed値は境目の値を超える(初期設定で設定)。
売り条件Ellers Center of Gravityシグナルは低下を示し(インジケータ値はゼロより大きく)、Average Speed値が境目の値を超える(初期設定で設定)。
決済条件  テイクプロフィット/ストップロス

ストラテジーを図2に視覚的に示します。上の表からわかるように、取引戦略は売買時に市場に参入するための条件を明確に定義しています。これはトレンドであるため、買いの条件は上昇トレンドに対応し、そして売りの条件は下降トレンドに対応します。 

図2. トレンド戦略におけるの参入条件

MetaEditorでソフトウェアを実装する際には、必要に応じて、上昇トレンドでのみ、下降トレンドでのみ、またはその両方の状況で使用できるように、取引エキスパートアドバイザに条件を設定する必要があります。 

こういった場合も考慮に入れる必要があります。

  • 上昇、下降および両方の時のためのテストモードを制御する能力。
  • 個別最適化のために、共有だけでなく上昇トレンド、下降トレンドについてもエキスパートアドバイザを別々に使用する必要がある。
  • 上昇モードと下降モードでは、それぞれ独自のパラメータセットが必要である。これはジョイント取引でそれらを使用するために必要だが、最適化されたパラメータの異なるセットと共になる。

取引エキスパートアドバイザを作成するためのこれらの条件を満たすには、次のコードを入力します。

//+------------------------------------------------------------------+
//| 動作モードの列挙                                                   |
//+------------------------------------------------------------------+
enum Trend_type
  {
   UPTREND = 1,            //Uptrend       
   DOWNTREND,              //Downtrend
   BOTH                    //Both trends
  };

入力パラメータのセットは次のようになります。

//+------------------------------------------------------------------+
// | エキスパートアドバイザの入力パラメータ                               |
//+------------------------------------------------------------------+
input string               Inp_EaComment="Trend Strategy";              //EA Comment
input double               Inp_Lot=0.01;                                //Lot
input MarginMode           Inp_MMode=LOT;                               //MM

input Trend_type           Inp_Trend_type=3;                            //Trend type
//--- Uptrend parameters
input string               Inp_Str_label1="===Uptrend parameters===";   //Label
input int                  Inp_MagicNum1=1111;                          //Magic number
input int                  Inp_StopLoss1=40;                            //Stop Loss(points)
input int                  Inp_TakeProfit1=60;                          //Take Profit(points)

// --- CenterOfGravityOSMAインジケータのパラメータ
input uint                 Period_1=9;                                  //Averaging period
input uint                 SmoothPeriod1_1=3;                           //Smoothing period1
input ENUM_MA_METHOD       MA_Method_1_1=MODE_SMA;                      //Averaging method1
input uint                 SmoothPeriod2_1=3;                           //Smoothing period2
input ENUM_MA_METHOD       MA_Method_2_1=MODE_SMA;                      //Averaging method2
input Applied_price_       AppliedPrice1=PRICE_OPEN_;                   //Applied price

// --- Average Speedインジケータのパラメータ
input int                  Inp_Bars1=1;                                 //Days
input ENUM_APPLIED_PRICE   Price1=PRICE_CLOSE;                          //Applied price
input double               Trend_lev1=2;                                //Trend Level

//--- Downtrend parameters
input string               Inp_Str_label2="===Downtrend parameters==="; //Label
input int                  Inp_MagicNum2=2222;                          //Magic number
input int                  Inp_StopLoss2=40;                            //Stop Loss(points)
input int                  Inp_TakeProfit2=60;                          //Take Profit(points)

// --- CenterOfGravityOSMAインジケータのパラメータ
input uint                 Period_2=9;                                  //Averaging period
input uint                 SmoothPeriod1_2=3;                           //Smoothing period1
input ENUM_MA_METHOD       MA_Method_1_2=MODE_SMA;                      //Averaging method1
input uint                 SmoothPeriod2_2=3;                           //Smoothing period2
input ENUM_MA_METHOD       MA_Method_2_2=MODE_SMA;                      //Averaging method2
input Applied_price_       AppliedPrice2=PRICE_OPEN_;                   //Applied price

// --- Average Speedインジケータのパラメータ
input int                  Inp_Bars2=1;                                 //Days
input ENUM_APPLIED_PRICE   Price2=PRICE_CLOSE;                          //Applied price
input double               Trend_lev2=2;                                //Trend Level

Inp_Trend_type変数のコードからわかるように、取引エキスパートアドバイザーの操作モードの選択を担当し、Uptrendモード、そしてDowntrendモードの入力パラメータは、それぞれ上昇トレンドパラメータと下降トレンドパラメータに分けられています。Bothモードを選択するときには、入力パラメータは両方のセクションから使用されることに注意してください。

そして、ロジック実装の主なコードは、以下のようになります。

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
// --- 計算用データを取得する

   if(!GetIndValue())
      return;

   if(Inp_Trend_type==1 && !Trade.IsOpenedByMagic(Inp_MagicNum1))
     {
      // --- 買いシグナルで注文をする
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment);
     }
   else if(Inp_Trend_type==2 && !Trade.IsOpenedByMagic(Inp_MagicNum2))
     {
      // --- 売りシグナルで注文をする
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment);
     }
   else if(Inp_Trend_type==3)
     {
      // --- 買いシグナルで注文をする
      if(BuySignal() && !Trade.IsOpenedByMagic(Inp_MagicNum1))
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment);
      // --- 売りシグナルで注文をする
      if(SellSignal() && !Trade.IsOpenedByMagic(Inp_MagicNum2))
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
// | 買いの条件                                                       |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   return(avr_speed1[0]>Trend_lev1 && cog1[1]<cog1[0] &&(cog1[1]<0 && cog1[0]<0))?true:false;
  }
//+------------------------------------------------------------------+
// | 売りの条件                                                       |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   return(avr_speed2[0]>Trend_lev2 && cog2[1]>cog2[0] &&(cog2[1]>0 && cog2[0]>0))?true:false;
  }
//+------------------------------------------------------------------+
//| インジケータの現在の値を取得する                                     |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,cog1)<=0 ||
          CopyBuffer(InpInd_Handle2,0,0,2,cog2)<=0 ||
          CopyBuffer(InpInd_Handle3,0,0,2,avr_speed1)<=0 ||
          CopyBuffer(InpInd_Handle4,0,0,2,avr_speed2)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

上昇トレンドモードと下降トレンドモードの場合、取引スキームは単純です。上昇トレンドで買い、下降トレンドで売る、つまりトレンドに従います。Bothモードでは、これら両方のシステムが独自の入力パラメータUptrend+Downtrendを使用して、互いに独立して動作することがわかります。


トレンド戦略をテストする

選択した戦略をテストして個別に最適化するには、上昇モードでは上昇トレンドを、下降モードでは下降モードを選択するのが論理的です。したがって、図3に示す次の期間を選択することにしました。

図3. テスト期間の選択

それでは、どのようなテスト設定になったかをまとめてみましょう。

  • 期間:Uptrendモード2017/04/10 - 01.02.2018。Downtrendモードの場合2014年5月8日 - 2015年3月13日。
  • 通貨ペア:EURUSD
  • 取引モード:遅延なし。提示された戦略は高周波のものを参照していないので、遅延の影響は非常に小さいでしょう。
  • テスト:M1のOHLC。実際のティックでの予備テストは、このモードとほとんど区別がつかないことがわかりました。 
  • 初回デポジット:1000ドル
  • レバレッジ:1:500
  • サーバー:MetaQuotes-Demo
  • 引用符:5桁

テストと最適化の目的は、戦略で使用される指標のパラメータ、およびテイクプロフィットとストップロスの値です。

上昇トレンドについては、以下の最適化結果が得られました。


図4.上昇トレンドでのテストと戦略の最適化の結果。

下降トレンドでは、次のようになります。


図5.下降トレンドでのテストと戦略の最適化の結果。

したがって、一時的プロットの選択されたレジームに最適な最適化を使用して最良の収益性のあるパラメータを決定したら、これらのパラメータを上方向と下方向の両方のトレンド移動を持つ混合セクションで試してください。それでは、この取引戦略の存続可能性をテストします。 

次の時間間隔を選択することにしました。これは、上記の要求に非常に適しています。

図6.混合テストの選択期間

図6からわかるように、この時間間隔にはキックバックと横方向の動きを伴う上昇トレンドと下降トレンドの両方があります。それでは、エキスパートアドバイザが、不利な履歴でどのように動作するのかを見てみましょう。

図7.不利な部分で最適化されたトレンド戦略をテストした結果


このトレンド取引戦略のテスト結果に基づいて、次のことがわかります。

  • 不利な状況下で、戦略は肯定的な結果を示しました。
  • 成功したロングトレードの割合は、ショートトレードよりも高品質であることがわかりました。
  • また、収益性や期待収益などの指標は、この分野のテストでは戦略全体としてプラスの原動力で取引されているとわかりました。 

フラット戦略を選択する

フラットで個別の最適化を実行するために、エントリを買われすぎ、売られすぎを判定するウィリアムパーセントレンジを選択しました。このツールは、エントリを検索するための主要な指標として使用されます。ADXのトレンド指標を採用しますが、トレンドを判断するのではなく、それが存在しないことを判断するために使用します。

パラメータ説明
使用したインジケータWilliams Percent Range
使用したインジケータADX
時間枠H1
買い条件WPRインディケータは売られすぎゾーン(-80未満)にあり、ADX値は設定されたしきい値を下回っています。
売り条件WPRインディケータは買われすぎゾーン(-20より上)にあり、ADX値は設定されたしきい値を下回っています。
決済条件  テイクプロフィット/ストップロス

図5では、この戦略の市場参入の視覚的な例を示しています。

図8.フラット戦略の参入条件

選択した戦略に基づいて、トランザクションの種類ごとに個別の最適化が実行されます。つまり、買いモードと売りモードです。

//+------------------------------------------------------------------+
//| 動作モードの列挙                                                   |
//+------------------------------------------------------------------+
enum Trend_type
  {
   UPTREND = 1,            //Buy       
   DOWNTREND,              //Sell
   BOTH                    //Both 
  };

このようにして、選択された戦略がフラットな条件下でどのように振舞うかを決定することが可能になります。下記はエキスパートアドバイザのリストコードです。

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
// --- 計算用データを取得する

   if(!GetIndValue())
      return;

   if(Inp_Trend_type==1 && !Trade.IsOpenedByMagic(Inp_MagicNum1))
     {
      // --- 買いシグナルで注文をする
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment);
     }
   else if(Inp_Trend_type==2 && !Trade.IsOpenedByMagic(Inp_MagicNum2))
     {
      // --- 売りシグナルで注文をする
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment);
     }
   else if(Inp_Trend_type==3)
     {
      // --- 買いシグナルで注文をする
      if(BuySignal() && !Trade.IsOpenedByMagic(Inp_MagicNum1))
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment);
      // --- 売りシグナルで注文をする
      if(SellSignal() && !Trade.IsOpenedByMagic(Inp_MagicNum2))
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
// | 買いの条件                                                       |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   return(wpr1[0]<-80 && adx1[0]<Inp_FlatLevel1)?true:false;
  }
//+------------------------------------------------------------------+
// | 売りの条件                                                       |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   return(wpr2[0]>=-20 && adx2[0]<Inp_FlatLevel2)?true:false;
  }
//+------------------------------------------------------------------+
//| インジケータの現在の値を取得する                                     |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,wpr1)<=0  ||
          CopyBuffer(InpInd_Handle2,0,0,2,wpr2)<=0 || 
          CopyBuffer(InpInd_Handle3,0,0,2,adx1)<=0  ||
          CopyBuffer(InpInd_Handle4,0,0,2,adx2)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+


フラット戦略をテストする

トレンド戦略をテストするときと同様に、最初に選択したフラット戦略をトレーニングし最適化するための履歴の一部を選択します。次の図はテスト間隔を示しています。

図9.フラットストラテジーに選択したテスト間隔

一般的なテストの条件は以下の通りです。

テストと最適化のための、インディケータとテイクプロフィットとストップロスの値のパラメータがあります。買いモードにおける個別最適化の結果が、下の表になります¥。


図10. 買いモードでのフラット戦略のテストと最適化の結果。

そして売りモードの個別最適化の結果はこのようになりました。


図11.売りモードでのフラット戦略のテストと最適化の結果。

個別最適化の助けを借りて両方のモードに最適なパラメータを決定できたので、不利な分野で戦略をテストし、新しい条件にどれほどうまく根付くかを見る時が来ました。実験として、マーケットの時間間隔を選択します。これは横ばいではなく、トレンド戦略をテストするためにすでに選択されているものです。これは図6に示す間隔を意味します。これはBoth(Uptrend + Downsrend)モードのトレンド戦略の混在テストに使用しました。

結果は次のようになりました。

図12.最適でない戦略を不利な分野でテストした結果。

戦略が横ばいであるという事実、および長期にわたるトレンドの動きを伴うテスト領域を考慮すると、それ自体は非常によく示しており、悪くないプラスであることがわかりました。 


複合戦略

個別最適化の例として、トレンドとフラット戦略を検証しました。どちらの戦略も2つの要素に分けられ、有利な市場で訓練され最適化されました。さらに、彼らの生存能力は市場の未知の部分でテストされ、その結果は非常に有望なものでした。それでは、この記事のまとめとして、上記の2つの戦略をより広い時間間隔で組み合わせた戦略をチェックし、その結果がこのような総合モードでも動作するのかを見てみたいと思います。しかし、最初に、両方の戦略を1つに組み合わせる必要があります。 

戦略のプログラム実装後に、トレンド戦略の2つのモードとフラット戦略の2つのモードの最適化されたパラメータを最初に設定しました。

//+------------------------------------------------------------------+
// | エキスパートアドバイザの入力パラメータ                               |
//+------------------------------------------------------------------+
input string               Inp_EaComment="Universe Strategy";           //EA Comment
input double               Inp_Lot=0.01;                                //Lot
input MarginMode           Inp_MMode=LOT;                               //MM

//--- Uptrend parameters
input string               Inp_Str_label1="===Uptrend parameters===";   //Label
input int                  Inp_MagicNum1=1111;                          //Magic number
input int                  Inp_StopLoss1=50;                            //Stop Loss(points)
input int                  Inp_TakeProfit1=55;                          //Take Profit(points)

// --- CenterOfGravityOSMAインジケータのパラメータ
input uint                 Period_1=9;                                  //Averaging period
input uint                 SmoothPeriod1_1=3;                           //Smoothing period1
input ENUM_MA_METHOD       MA_Method_1_1=MODE_SMA;                      //Averaging method1
input uint                 SmoothPeriod2_1=3;                           //Smoothing period2
input ENUM_MA_METHOD       MA_Method_2_1=MODE_SMA;                      //Averaging method2
input Applied_price_       AppliedPrice1=PRICE_TRENDFOLLOW1_;           //Applied price

// --- Average Speedインジケータのパラメータ
input int                  Inp_Bars1=1;                                 //Days
input ENUM_APPLIED_PRICE   Price1=PRICE_LOW;                            //Applied price
input double               Trend_lev1=1.6;                              //Trend Level

//--- Downtrend parameters
input string               Inp_Str_label2="===Downtrend parameters==="; //Label
input int                  Inp_MagicNum2=2222;                          //Magic number
input int                  Inp_StopLoss2=40;                            //Stop Loss(points)
input int                  Inp_TakeProfit2=70;                          //Take Profit(points)

// --- CenterOfGravityOSMAインジケータのパラメータ
input uint                 Period_2=15;                                 //Averaging period
input uint                 SmoothPeriod1_2=3;                           //Smoothing period1
input ENUM_MA_METHOD       MA_Method_1_2=MODE_SMA;                      //Averaging method1
input uint                 SmoothPeriod2_2=3;                           //Smoothing period2
input ENUM_MA_METHOD       MA_Method_2_2=MODE_SMA;                      //Averaging method2
input Applied_price_       AppliedPrice2=PRICE_HIGH_;                   //Applied price

// --- Average Speedインジケータのパラメータ
input int                  Inp_Bars2=1;                                 //Days
input ENUM_APPLIED_PRICE   Price2=PRICE_WEIGHTED;                       //Applied price
input double               Trend_lev2=1.0;                              //Trend Level


//--- Buy parameters
input string               Inp_Str_label3="===Buy parameters===";       //Label
input int                  Inp_MagicNum3=3333;                          //Magic number
input int                  Inp_StopLoss3=40;                            //Stop Loss(points)
input int                  Inp_TakeProfit3=60;                          //Take Profit(points)

// --- WPRインジケータのパラメータ
input int                  Inp_WPRPeriod1=11;                           //Period WPR
// --- ADXインジケータのパラメータ
input int                  Inp_ADXPeriod1=13;                           //Period ADX
input int                  Inp_FlatLevel1=25;                           //Flat Level ADX

//--- Sell parameters
input string               Inp_Str_label4="===Sell parameters===";      //Label
input int                  Inp_MagicNum4=4444;                          //Magic number
input int                  Inp_StopLoss4=30;                            //Stop Loss(points)
input int                  Inp_TakeProfit4=30;                          //Take Profit(points)

// --- WPRインジケータのパラメータ
input int                  Inp_WPRPeriod2=7;                            //Period WPR
// --- ADXインジケータのパラメータ
input int                  Inp_ADXPeriod2=15;                           //Period ADX
input int                  Inp_FlatLevel2=40;                           //Flat Level ADX

また、複合エキスパートはトレーニングや最適化の対象にならないため、モードを設定するオプションがパラメータから削除されました。戦略自体は次のように実装されました。

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
// --- 計算用データを取得する

   if(!GetIndValue())
      return;

// --- 買いシグナルで注文を開く(Trend Strategy)
   if(BuySignal_1() && !Trade.IsOpenedByMagic(Inp_MagicNum1))
      Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss1,Inp_TakeProfit1,Inp_MagicNum1,Inp_EaComment);
// --- 売りシグナルがある状態で注文を開く(Trend Strategy)
   if(SellSignal_1() && !Trade.IsOpenedByMagic(Inp_MagicNum2))
      Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss2,Inp_TakeProfit2,Inp_MagicNum2,Inp_EaComment);

// --- 買いシグナルで注文を開く(Flat strategy)
   if(BuySignal_2() && !Trade.IsOpenedByMagic(Inp_MagicNum3))
      Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss3,Inp_TakeProfit3,Inp_MagicNum3,Inp_EaComment);
// --- 売りシグナルで注文を開く(Flat Strategy)
   if(SellSignal_2() && !Trade.IsOpenedByMagic(Inp_MagicNum4))
      Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss4,Inp_TakeProfit4,Inp_MagicNum4,Inp_EaComment);
  }
//+------------------------------------------------------------------+
// | 買い条件(トレンド戦略)                                           |
//+------------------------------------------------------------------+
bool BuySignal_1()
  {
   return(avr_speed1[0]>Trend_lev1 && cog1[1]<cog1[0] &&(cog1[1]<0 && cog1[0]<0))?true:false;
  }
//+------------------------------------------------------------------+
// | 売り条件(トレンド戦略)                                           |
//+------------------------------------------------------------------+
bool SellSignal_1()
  {
   return(avr_speed2[0]>Trend_lev2 && cog2[1]>cog2[0] &&(cog2[1]>0 && cog2[0]>0))?true:false;
  }
//+------------------------------------------------------------------+
// | 買い条件(フラット戦略)                                           |
//+------------------------------------------------------------------+
bool BuySignal_2()
  {
   return(wpr1[0]<-80 && adx1[0]<Inp_FlatLevel1)?true:false;
  }
//+------------------------------------------------------------------+
// | 売り条件(フラット戦略)                                           |
//+------------------------------------------------------------------+
bool SellSignal_2()
  {
   return(wpr2[0]>=-20 && adx2[0]<Inp_FlatLevel2)?true:false;
  }
//+------------------------------------------------------------------+
//| インジケータの現在の値を取得する                                     |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,cog1)<=0       ||
          CopyBuffer(InpInd_Handle2,0,0,2,cog2)<=0       ||
          CopyBuffer(InpInd_Handle3,0,0,2,avr_speed1)<=0 ||
          CopyBuffer(InpInd_Handle4,0,0,2,avr_speed2)<=0 ||
          CopyBuffer(InpInd_Handle5,0,0,2,wpr1)<=0       ||
          CopyBuffer(InpInd_Handle6,0,0,2,wpr2)<=0       ||
          CopyBuffer(InpInd_Handle7,0,0,2,adx1)<=0       ||
          CopyBuffer(InpInd_Handle8,0,0,2,adx2)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

ここで注意しなければならないのは、2つの戦略の4つのモードすべてが互いに独立して機能し、トレーニング後に独自のパラメータセットを持ち、互いに干渉することは決してないという点です。テストのために、より広い範囲を選択することにしました。最後の3年間とし、テスト条件の完全なリストは以下のようになりました。

  • 間隔: 01/01/2015 - 11/30/2018。
  • 通貨ペア:EURUSD
  • 取引モード:遅延なし。提示された戦略は高周波のものを参照していないので、遅延の影響は非常に小さいでしょう。
  • テスト:M1のOHLC。実際のティックでの予備テストは、このモードとほとんど区別がつかないことがわかりました。 
  • 初回デポジット:1000ドル
  • レバレッジ:1:500
  • サーバー:MetaQuotes-Demo
  • 引用符:5桁

テストの後、私たちはとても面白い結果を得ることができました。

図13.複合戦略のテスト結果

パラメータの新しい最適化は行われておらず、パラメータは、好ましい間隔で個別の最適化中に定義された最適値から「そのまま」採用された点に注目してください。しかし、4つの独立した戦略が共通の不利な条件で機能したことを考えると、結果はプラスといえます。


まとめ

2つの戦略のテスト結果を上昇トレンド、下降トレンド、および横ばいの条件で比較した後、次のように結論付けることができます。

私がテストのためにランダム取引システムを選択し、別々の最適化によってそれらを改良し、そして最終チェックが最も不利な履歴間隔で行われたことを考えると、この研究の結果は肯定的といえます。結果は、個別最適化の方法が非常に効率的であり、取引システムの開発と構成に使用されるに値することを示しました。


まとめ

記事の最後にある添付のアーカイブには、リストされているすべてのファイルが含まれています。正しく動作させるためには、MQL5フォルダを端末のルートディレクトリに保存する必要があります。

記事で使用されているプログラム:

#
 名前
タイプ
説明
1
TrendStrategy.mq5EA
 トレンド戦略に基づくエキスパートアドバイザ
2
FlatStrategy.mq5EA フラット戦略に基づくマーケットエキスパートアドバイザ
3UniverseStrategy.mql5 EA  複合戦略に基づくエキスパートアドバイザ
4Trade.mqhライブラリ 取引関数のクラス
5
average_speed.mq5インディケータ 平均価格インジケータ。トレンド戦略に使用されます。
6centerofgravityosma.mq5インディケータ Ehlersの重心指標。トレンド戦略に使用されます。