連続でエントリーしてしまう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でコードを動かしてみると・・・
今回のコードを動かしてみますと、このように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を動かしてみると・・
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;
}
//+------------------------------------------------------------------+