MQL5ウィザードを使うことで、自動的にエキスパートアドバイザー(EA)のコードを生成できます。詳細はMQL5ウィザードでのエキスパートアドバイザー作成をチェックしてください。
この戦略は、2つの指数平滑移動平均(EMA)のクロスオーバーを基にした取引シグナルを利用します。移動平均はトレンド時には効果的ですが、その他の状況では多くの誤シグナルを発生させることがあります。戦略を改善する方法の一つは、時間フィルターを活用することです(例えば、FXのヨーロッパセッション中にのみ新規ポジションを開くなど)。
ここでは、インターデイ時間フィルターを用いた2つのEMAのクロスオーバーに基づく戦略を考えます。この戦略は「インターデイ時間フィルター付きの2EMAクロスオーバーに基づくシグナル」と呼ばれ、MQL5ウィザードで自動生成されるEAで使用されます。
取引シグナルは以下の通りです:
- ロングポジションを開く:ファストEMAがスロウEMAを上方にクロスし、インターデイ時間フィルターの条件を満たしていない場合。
- ショートポジションを開く:ファストEMAがスロウEMAを下方にクロスし、インターデイ時間フィルターの条件を満たしていない場合。
この戦略はCSignal2EMA_ITFクラスに実装されています。
取引システムは保留注文に基づいており、価格レベルは移動平均の値に基づいて計算され、ATR(アベレージ・トゥルー・レンジ)ユニットが使用されます。

図1. インターデイ時間フィルター付きの2EMAクロスオーバーに基づく取引シグナル
取引シグナル
この取引戦略はCSignal2EMA_ITFに実装されており、インジケーターの値にアクセスを簡素化するための保護されたメソッドがいくつかあります:
double FastEMA(int ind) // バーのファストEMAの値を返します double SlowEMA(int ind) // バーのスロウEMAの値を返します double StateFastEMA(int ind) // ファストEMAが上昇/下降した場合の正/負の値を返します double StateSlowEMA(int ind) // スロウEMAが上昇/下降した場合の正/負の値を返します double StateEMA(int ind) // ファストEMAとスロウEMAの差を返します double ATR(int ind) // バーのATRの値を返します
- Limit>0. 価格が市場価格より良い状態で移動平均の誤ブレイクに入る(取引シグナルに応じてBuy LimitおよびSell Limit注文が配置されます)
- Limit<0. 価格が移動方向に入る(取引シグナルに応じてBuy StopおよびSell Stop注文が配置されます)。
- Limit=0. この場合、市場価格を使用して取引します。
1. ロングポジションを開く
ロングポジションを開く条件を確認します:最後のバーでファストEMAとスロウEMAの差が「-」から「+」に変わったかどうか(StateEMA(1)>0 && StateEMA(2)<0)を確認します。
次に、CSignalITFクラスのCheckOpenLong()メソッドを呼び出してインターデイ時間フィルターの条件を確認します。取引が許可された場合、基準価格レベル(移動平均の値)と最後のバーのATR範囲の値を計算します。
Limit入力パラメータの符号に応じて、Buyの保留注文を配置します。注文価格、テイクプロフィットおよびストップロスのレベルは基準価格レベルに対して計算されます(ATR単位で)。注文の有効期限は、Expiration入力パラメータによって(バー単位で)定義されます。
//+------------------------------------------------------------------+ //| ロングポジションを開く条件をチェックします(買い) | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration) { if(!(StateEMA(1)>0 && StateEMA(2)<0)) return(false); if(!m_time_filter.CheckOpenLong(price,sl,tp,expiration)) return(false); //--- double ema=SlowEMA(1); double atr=ATR(1); double spread=m_symbol.Ask()-m_symbol.Bid(); //--- price=m_symbol.NormalizePrice(ema-m_limit*atr+spread); sl =m_symbol.NormalizePrice(price+m_stop_loss*atr); tp =m_symbol.NormalizePrice(price-m_take_profit*atr); expiration+=m_expiration*PeriodSeconds(m_period); //--- return(true); }
2. ロングポジションをクローズする
この場合、ロングポジションをクローズする条件をチェックする関数は常にfalseを返します。つまり、ロングポジションはテイクプロフィットまたはストップロスによってクローズされると仮定されています。必要に応じて、このメソッドの実装を含む独自のコードを書くことができます。
//+------------------------------------------------------------------+ //| ショートポジションをクローズする条件をチェックします | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckCloseLong(double& price) { return(false); }
3. ショートポジションを開く
ショートポジションを開く条件を確認します:最後のバーでファストEMAとスロウEMAの差が「+」から「-」に変わったかどうか(StateEMA(1)<0 && StateEMA(2)>0)を確認します。
次に、CSignalITFクラスのCheckOpenLong()メソッドを呼び出してインターデイ時間フィルターの条件を確認します。取引が許可された場合、基準価格レベル(移動平均の値)と最後のバーのATR範囲の値を計算します。
Limit入力パラメータの符号に応じて、Sellの保留注文を配置します。注文価格、テイクプロフィットおよびストップロスのレベルは基準価格レベルに対して計算されます(ATR単位で)。注文の有効期限は、Expiration入力パラメータによって(バー単位で)定義されます。
//+------------------------------------------------------------------+ //| ショートポジションを開く条件をチェックします(売り) | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration) { if(!(StateEMA(1)<0 && StateEMA(2)>0)) return(false); if(!m_time_filter.CheckOpenShort(price,sl,tp,expiration)) return(false); //--- double ema=SlowEMA(1); double atr=ATR(1); //--- price =m_symbol.NormalizePrice(ema+m_limit*atr); sl =m_symbol.NormalizePrice(price+m_stop_loss*atr); tp =m_symbol.NormalizePrice(price-m_take_profit*atr); expiration+=m_expiration*PeriodSeconds(m_period); //--- return(true); }
4. ショートポジションをクローズする
この場合、ショートポジションをクローズする条件をチェックする関数は常にfalseを返します。つまり、ポジションはテイクプロフィットまたはストップロスによってクローズされると仮定されています。必要に応じて、このメソッドの実装を含む独自のコードを書くことができます。
//+------------------------------------------------------------------+ //| ショートポジションをクローズする条件をチェックします | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckCloseShort(double& price) { return(false); }
5. Buy保留注文のトレーリングストップ
エキスパートアドバイザーは、現在の移動平均とATRの値に応じて保留注文をトレールします。
//+--------------------------------------------------------------------+ //| Buy保留注文を変更する条件をチェックします | //+--------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckTrailingOrderLong(COrderInfo* order,double& price) { //--- チェック if(order==NULL) return(false); //--- double ema=SlowEMA(1); double atr=ATR(1); double spread=m_symbol.Ask()-m_symbol.Bid(); //--- price=m_symbol.NormalizePrice(ema-m_limit*atr+spread); //--- return(true); }
6. Sell保留注文のトレーリングストップ
エキスパートアドバイザーは、現在の移動平均とATRの値に応じて保留注文をトレールします。
市場価格が注文価格に達した場合、注文が実行されます。
//+--------------------------------------------------------------------+ //| Sell保留注文を変更する条件をチェックします | //+--------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckTrailingOrderShort(COrderInfo* order,double& price) { //--- チェック if(order==NULL) return(false); //--- double ema=SlowEMA(1); double atr=ATR(1); //--- price=m_symbol.NormalizePrice(ema+m_limit*atr); //--- return(true); }
エキスパートアドバイザーの作成:MQL5ウィザードを使用
この戦略に基づく取引ロボットを作成するには、MQL5ウィザードの「インターデイ時間フィルター付きの2EMAクロスオーバーに基づくシグナル」を選択します:

図2. MQL5ウィザードでのインターデイ時間フィルター付きの2EMAクロスオーバーに基づくシグナルの選択
次に、必要なトレーリングストップアルゴリズムとマネーとリスク管理システムを指定します。エキスパートアドバイザーのコードは自動的に作成されるので、コンパイルしてMetaTrader 5クライアントターミナルのストラテジーテスターでテストできます。
テスト結果
歴史データ(EUenSD H1、テスト期間:2010年1月1日~2011年1月5日、PeriodFastEMA=5、PeriodSlowEMA=30、PeriodATR=7、Limit=1.2、StopLoss=5、TakeProfit=8、Expiration=4、GoodMinuteOfHour=-1、BadMinutesOfHour=0、GoodHourOfDay=-1、BadHoursOfDay=0、GoodDayOfWeek=-1、BadDaysOfWeek=0)に対するエキスパートアドバイザーのバックテストを考えます。
エキスパートアドバイザーの作成には固定ボリューム(固定ロット取引、0.1)を使用し、トレーリングストップアルゴリズムは使用されていません(トレーリングは使用されていません)。

図3. インターデイ時間フィルターなしでの2EMAクロスオーバーに基づくエキスパートアドバイザーのテスト結果
インターデイフィルターが使用されていないため、多くの誤シグナルが発生しています。取引シグナルは、取引時間に応じて結果を分析することで改善できます。
私たちのケースでは、2つのEMAのクロスオーバーは、6:00から23:59まで多くの誤シグナルをもたらすことがわかりました。インターデイ時間フィルターを設定することができます。
例えば、0:00から5:59までのみポジションを開くことを許可する時間フィルターを指定できます。これは、BadHoursOfDay=16777152=111111111111111111000000bの値を設定することで実行できます。他の取引時間は「悪い」ため、6:00から終日まで新しいポジションを開くことを禁止する方が良いでしょう。
BadHoursOfDay=16777152の値を設定すれば、多くの誤シグナルをフィルタリングできます:

図4. インターデイ時間フィルターを用いた2EMAのクロスオーバーに基づくエキスパートアドバイザーのテスト結果
CSignalITFは、他にも多くの時間フィルタリング機能を提供します(時間内の「良い」および「悪い」分、時間内の時間、週内の日などを指定するだけです)。
添付ファイル:CSignal2EMA-ITF.mqhはterminal_data_folder\MQL5\Include\Expert\Signalフォルダーに配置する必要があります。
expert_2ema_itf.mq5には、MQL5ウィザードを使用して作成されたエキスパートアドバイザーのコードが含まれています。