EAが連続でエントリーしてしまう問題を解決する【MQL】

EAの連続エントリーを防ぐコード
yuki
yuki
今回はMQL初心者さんが一度はぶつかってしまう、「EAが連続エントリーしてしまう」問題を解決するコードをご紹介していきます

連続でエントリーしてしまうEA

//+------------------------------------------------------------------+
//|                                      RSIを使ったEA(連続エントリーしてしまう) |
//|                                   ©2020  MT4ツール製作【シストレファクトリー】 |
//|                     https://interactivebrokers.work/first_entry/ |
//+------------------------------------------------------------------+
#property copyright "©2020  MT4ツール製作【シストレファクトリー】"
#property link      "https://interactivebrokers.work/first_entry/"
#property version   "1.00"
#property strict

input double p_buyLot = 0.01;       //買い注文のロット
input uint p_slippage = 2;          //許容スリップページ

input uint p_RSIPERIOD = 14;        //RSIを計算する期間
input uint p_RSIupperlimit = 70;    //RSI上側閾値
input uint p_RSIlowerlimit = 30;    //RSI下側閾値

datetime _newBarTime = 0;

//+------------------------------------------------------------------+
int OnInit() {

   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnTick() {
//決済条件:エントリー中、RSIが上側閾値を超すと決済
   for(int i = 0; i <= OrdersTotal(); i++) {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(RSIOverUpperLimit(0))
         int result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), p_slippage);
   }

//新しいローソク足に切り替わった時だけ実行する処理
   if(_newBarTime != Time[0]) {
      _newBarTime = Time[0];

//エントリー条件:RSIが下側閾値以下になるとロングエントリー
      if(RSIUnderLowerLimit(1)) {
         int result = OrderSend(Symbol(), OP_BUY, p_buyLot, Ask, p_slippage, 0, 0);
      }
   }
}
//+------------------------------------------------------------------+
//RSIが下側閾値以下になるとtrue(エントリー条件に使用)
bool RSIUnderLowerLimit(int bar) {
   double RSIValue = iRSI(Symbol(), PERIOD_CURRENT, p_RSIPERIOD, PRICE_CLOSE, bar);

   if(p_RSIlowerlimit >= RSIValue) return true;
   else return false;
}
//+------------------------------------------------------------------+
//RSIが上側閾値以上になるとtrue(決済条件に使用)
bool RSIOverUpperLimit(int bar) {
   double RSIValue = iRSI(Symbol(), PERIOD_CURRENT, p_RSIPERIOD, PRICE_CLOSE, bar);

   if(p_RSIupperlimit <= RSIValue) return true;
   else return false;
}
//+------------------------------------------------------------------+

 

今回のサンプルコードですが、ロジックとしては

・ローソク足確定時にRSIが30以下になったらロングエントリー

・RSIが70以上になったら決済

というシンプルなEAです。

 

MT4でコードを動かしてみると・・・

MT4のチャート

今回のコードを動かしてみますと、このようにRSIが下限でとどまっている時にローソク足が変わるとエントリーし続けてしまいます。

このエントリーを避けるために一工夫してみましょう。

上記ロジックに新たに 「一度エントリーしたらRSIが30を上回るまでエントリーしない」

というロジックを追加します。

 

再エントリーを防ぐコードの書き方

まずはグローバルにエントリー許可を管理するbool変数を作っておきます。(初期値はfalse)

bool _entryPermission = false;      //エントリー許可

 

更に、RSIが下側閾値を上回ったかどうかを判定する関数を作ります。

//RSIが下側閾値を上回るとtrueを返す関数(エントリー許可フラグに使用)
bool RSIOverLowerLimit(int bar) {
   double RSIValue = iRSI(Symbol(), PERIOD_CURRENT, p_RSIPERIOD, PRICE_CLOSE, bar);

   if(p_RSIlowerlimit < RSIValue) return true;
   else return false;
}

 

そしてOnTick関数内で、RSIが下側閾値(初期設定では30)を上回ったらエントリー許可をtrueにします。

//RSIが下側閾値を上回るとエントリー許可を出す
      if(RSIOverLowerLimit(1)) {
         _entryPermission = true;
      }

 

そしてエントリー条件は下記のように設定します

・ローソク足確定時にRSIが30以下

・エントリー許可がtrue

 

_entryPermission がtrue かつRSIが下側閾値以下になるとエントリーします。それと同時に 『_entryPermission』をfalseにします。

//エントリー条件:RSIが下側閾値以下になるとロングエントリー
      if(_entryPermission == true && RSIUnderLowerLimit(1)) {
         if(OrderSend(Symbol(), OP_BUY, p_buyLot, Ask, p_slippage, 0, 0))
            _entryPermission = false; //エントリーしたらエントリー許可をfalseにする
      }

 

こうすることで一度エントリーしたらRSIが下側閾値を上回るまでエントリー条件である _entryPermission == true が満たされなくなるので、次のローソク足からはエントリーしません。

そして先程のコードですが、このコードによってRSIが30以下にある状態から上に突き抜けると _entryPermissionがtrue になり、再び条件を満たしたらエントリーする事ができるようになります。

//RSIが下側閾値を上回るとエントリー許可を出す
      if(RSIOverLowerLimit(1)) {
         _entryPermission = true;
      }

 

再エントリーを修正したEAを動かしてみると・・

MT4のチャートRSIが30以下が続いてもエントリーは最初の1回だけになっています

 

連続エントリーの比較両方を見比べると連続エントリーされなくなっていますね

 

連続エントリーを防止したソースコード

//+------------------------------------------------------------------+
//|                                         RSIを使ったEA(連続エントリー防止) |
//|                                   ©2020  MT4ツール製作【シストレファクトリー】 |
//|                     https://interactivebrokers.work/first_entry/ |
//+------------------------------------------------------------------+
#property copyright "©2020  MT4ツール製作【シストレファクトリー】"
#property link      "https://interactivebrokers.work/first_entry/"
#property version   "1.00"
#property strict

input double p_buyLot = 0.01;       //買い注文のロット
input uint p_slippage = 2;          //許容スリップページ

input uint p_RSIPERIOD = 14;        //RSIを計算する期間
input uint p_RSIupperlimit = 70;    //RSI上側閾値
input uint p_RSIlowerlimit = 30;    //RSI下側閾値

datetime _newBarTime = 0;
bool _entryPermission = false;      //エントリー許可

//+------------------------------------------------------------------+
int OnInit() {

   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnTick() {
//決済条件:エントリー中、RSIが上側閾値を超すと決済
   for(int i = 0; i <= OrdersTotal(); i++) {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(RSIOverUpperLimit(0))
         int result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), p_slippage);
   }

//新しいローソク足に切り替わった時だけ実行する処理
   if(_newBarTime != Time[0]) {
      _newBarTime = Time[0];

//RSIが下側閾値を上回るとエントリー許可を出す
      if(RSIOverLowerLimit(1)) {
         _entryPermission = true;
      }

//エントリー条件:RSIが下側閾値以下になるとロングエントリー
      if(_entryPermission == true && RSIUnderLowerLimit(1)) {
         if(OrderSend(Symbol(), OP_BUY, p_buyLot, Ask, p_slippage, 0, 0))
            _entryPermission = false; //エントリーしたらエントリー許可をfalseにする
      }
   }
}
//+------------------------------------------------------------------+
//RSIが下側閾値以下になるとtrueを返す関数(エントリー条件に使用)
bool RSIUnderLowerLimit(int bar) {
   double RSIValue = iRSI(Symbol(), PERIOD_CURRENT, p_RSIPERIOD, PRICE_CLOSE, bar);

   if(p_RSIlowerlimit >= RSIValue) return true;
   else return false;
}
//+------------------------------------------------------------------+
//RSIが下側閾値を上回るとtrueを返す関数(エントリー許可フラグに使用)
bool RSIOverLowerLimit(int bar) {
   double RSIValue = iRSI(Symbol(), PERIOD_CURRENT, p_RSIPERIOD, PRICE_CLOSE, bar);

   if(p_RSIlowerlimit < RSIValue) return true;
   else return false;
}
//+------------------------------------------------------------------+
//RSIが上側閾値以上になるとtrueを返す関数(決済条件に使用)
bool RSIOverUpperLimit(int bar) {
   double RSIValue = iRSI(Symbol(), PERIOD_CURRENT, p_RSIPERIOD, PRICE_CLOSE, bar);

   if(p_RSIupperlimit <= RSIValue) return true;
   else return false;
}
//+------------------------------------------------------------------+

 

yuki
yuki
EAの連続エントリーは初心者がハマりやすいバグですが、「エントリーロジックを満たさなくなったらエントリー許可をtrueにする」という仕組みを実装することで防止することができます。ぜひ試してみてください。 
EAやインジケーターのコピー対策
MT4のEAやインジケーターのコピー防止方法【MQL言語】 EAやインジケーターには必ずコピー対策を! せっかく苦労して作ったEAやインジケーターですが、見た目のセンスがあったり、勝...
EA&インジケーター制作代行
EA&インジケーター制作代行承ります EA&インジケーター制作代行とは? EA&インジケーター制作代行では、皆さんが日頃使っている手法をMT4でエントリーサインを出して...