MT4 EAの作り方|RSIで逆張りするEAを作る方法

MT4 RSI EA|RSIで逆張り判定するEAの作り方
EAサンプル・ノウハウ
記事内に商品プロモーションを含む場合があります
スポンサーリンク

「RSIを使った逆張りロジックをEAとして自動化したい」
「MQL4でRSIの値をどう取得・判定するのか知りたい」
という方に向けて、この記事ではMT4で動くRSI EAのサンプルコードを公開します。

RSIは0~100の数値で相場の過熱感を確認できるインジケーターです。
今回のEAでは、RSIが設定した水準を下回ったらBUY、上回ったらSELLするシンプルな逆張りロジックを実装します。

RSIの値取得にはMT4標準のiRSI()関数を使用します。
また、当サイトで公開しているMT4 EAベーステンプレートを土台に、RSI用のパラメータと売買条件を追加する構成にしています。

📘 この記事で解説する内容
  • RSIの基本と70・30の考え方
  • RSIを使った逆張りエントリー
  • MT4のiRSI()でRSI値を取得する方法
  • ベーステンプレートから変更した箇所
  • RSI EAのMQL4サンプルコード
  • パラメータ設定とバックテスト結果

このRSI EAの仕様

まず、今回作成するRSI EAの内容をまとめます。

項目内容
対応MT4 / MQL4
使用インジケーターRSI(Relative Strength Index)
使用関数iRSI()
BUY条件RSIが買い水準を下回る
SELL条件RSIが売り水準を上回る
判定タイミング新しいローソク足ができたとき(1本前の確定足を使用)
利確固定pips
損切り固定pips
ポジション管理口座内に注文がない場合のみ新規エントリー
MagicNumber管理なし(学習用サンプルのため)

RSIとは?70・30を使った逆張りの基本

RSI(Relative Strength Index)は、価格の上昇・下落の勢いから相場の過熱感を数値化するオシレーター系インジケーターです。

値は0~100の範囲で推移し、一般的には次のような目安が使われます。

  • RSIが70以上:買われ過ぎの目安
  • RSIが30以下:売られ過ぎの目安

逆張りでは、RSIが低い水準まで下がった場面でBUY、高い水準まで上がった場面でSELLする考え方があります。

70・30はあくまで一般的な目安です。
今回のサンプルEAでは、初期値を「買い30・売り76」としています。売買水準はパラメータから変更できます。

RSI EAのエントリーロジック

BUY条件

1本前の確定足のRSIが、設定した買い水準を下回っている場合にBUYします。

初期値では買い水準を30としているため、次の条件です。

RSI < 30

SELL条件

1本前の確定足のRSIが、設定した売り水準を上回っている場合にSELLします。

今回の初期値では売り水準を76としているため、次の条件です。

RSI > 76

確定足のRSIで判定する

今回のEAでは、iRSI()のバーシフトに1を指定し、1本前の確定したローソク足のRSIを使用します。

形成中の0番足ではなく確定足を使うことで、ローソク足の途中でRSI値が変化したことによる判定のブレを避けやすくしています。

RSI逆張りEAを使う前の注意点

このコードは、RSIの取得と逆張りロジックを理解しやすくすることを優先したサンプルです。
複数EAを同一口座で管理するためのMagicNumberによるポジション識別などは実装していません。

RSIを使った逆張りは、値動きが一定範囲を往復する相場では機能しやすい一方、強いトレンドではRSIが高値圏・安値圏に長く滞在することがあります。

そのため、「RSIが低いから必ず上がる」「RSIが高いから必ず下がる」というものではありません。

トレンド方向を限定したい場合は、移動平均線やADXなどをフィルターとして組み合わせ、変更後の結果をバックテストで確認します。

また、このEAはOrdersTotal()で口座全体の注文数を確認するため、そのまま使用する場合は、他のEAや手動ポジションと同じ口座で併用せず、EA単独で検証する方法を推奨します。

ベーステンプレートからの変更点

今回のRSI EAは、当サイトで公開しているMT4 EAベーステンプレートを土台に作成しています。

ベーステンプレートからの主な変更点は次の通りです。

  • RSI期間・買い水準・売り水準のパラメータを追加
  • iRSI()で1本前の確定足RSIを取得
  • RSIが買い水準を下回ったらBUY
  • RSIが売り水準を上回ったらSELL
  • TP・SLはベーステンプレートの固定pips方式をそのまま使用
  • 独自の決済条件は追加せず、TP・SLで決済
  • 共通関数は実際に使用するfuncOrder_Send()のみ掲載

つまり、今回のRSI EAはベーステンプレートの基本構造と固定TP・SLをそのまま利用し、新規注文判断へRSIの逆張り条件を追加したEAです。

RSI EAをダウンロード

今回の記事で解説しているRSI EAはこちらからダウンロードできます。

📥 RSI EAをダウンロード

👉 ダウンロード後のパラメータ設定を見る

💡 コードを書かずにEAを作ってみたい方へ
無料MT4 EAビルダーでは、RSIを使った逆張り条件を画面上で設定してEAを作成できます。
今回のサンプルを試したあと、RSI期間や売買水準を変えて自分のEAを作ってみたい方にもおすすめです。

無料MT4 EAビルダーを使ってみる

RSI EAのMQL4サンプルコード

以下が今回の公開版ソースコードです。
公開表記はv1.0、ソース上は#property version "1.00"としています。

💡 コードの見方
背景色が付いている行が、ベースEAテンプレートから主に変更・追加した部分です。
RSI固有のパラメータと売買判定部分を中心に強調しています。
//+------------------------------------------------------------------+
//|                                                      09_RSI.mq4 |
//|                                Copyright © 2020-2026 ぷろぐらむFX |
//|                                             https://fx-prog.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2020-2026 ぷろぐらむFX"
#property link      "https://fx-prog.com/"
#property version   "1.00"
#property strict

input double Lots = 0.01;              //ロット
input int TP = 10;                     //利確(pips)
input int SL = 10;                     //損切り(pips)

//***【パラメータ設定↓】***//

input int RSI_KIKAN = 10;              //RSI期間
input int RSI_KAI = 30;                //買い水準
input int RSI_URI = 76;                //売り水準

//***【パラメータ設定↑】***//

string Ea_Name = WindowExpertName();   //EA名称をオーダーコメントに使用
double PipValue;                       //ブローカー桁数に対応したPoint補正
datetime prevtime;                     //ローソク足時間保持用

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){

   if(Digits == 3 || Digits == 5){
      PipValue = Point * 10;
   }else{
      PipValue = Point;
   }

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){

   //新しいローソク足ができたときだけ処理
   if(Time[0] != prevtime){
      prevtime = Time[0];
   }else{
      return;
   }

   int total = OrdersTotal();
   int ea_order_Type = -1;
   double ea_order_stop_price = 0;
   double ea_order_good_price = 0;

   //ポジションがない場合は新規エントリー判定
   if(total == 0){

      bool openBuy = false;
      bool openSell = false;

//***【新規注文判断↓】***//

      //1本前の確定足のRSIを取得
      double RSI_atai = iRSI(NULL,0,RSI_KIKAN,PRICE_CLOSE,1);

      //RSIが買い水準を下回ったらBUY
      if(RSI_atai < RSI_KAI){
         openBuy = true;

      //RSIが売り水準を上回ったらSELL
      }else if(RSI_atai > RSI_URI){
         openSell = true;
      }

//***【新規注文判断↑】***//

      if(openBuy){
         ea_order_Type = OP_BUY;
      }else if(openSell){
         ea_order_Type = OP_SELL;
      }

//***【TP/SL判断↓】***//

      //ベーステンプレートの固定pips TP・SLを使用
      if(openBuy){
         ea_order_stop_price = Ask - SL * PipValue;
         ea_order_good_price = Ask + TP * PipValue;
      }else if(openSell){
         ea_order_stop_price = Bid + SL * PipValue;
         ea_order_good_price = Bid - TP * PipValue;
      }

//***【TP/SL判断↑】***//

      if(ea_order_Type > -1){
         //学習用サンプルではMagicNumber管理を行わないため0
         funcOrder_Send(ea_order_Type,ea_order_stop_price,ea_order_good_price,Lots,Ea_Name,0,0);
      }
   }
}


//★★★★★★★★★★★★★★★★★★★★ ここから下は共通関数 ★★★★★★★★★★★★★★★★★★★★

//+------------------------------------------------------------------+
//|【関数】新規注文関数                                              |
//|【引数】orderType:売買(0=BUY, 1=SELL)                            |
//|【引数】sl:損切り価格  tp:利確価格                               |
//|【引数】lots:取引ロット数                                         |
//|【引数】orderComment:オーダーコメント                             |
//|【引数】magic:MagicNumber                                         |
//|【引数】maxSpreadPoints:許容スプレッド[Point] (0=制限なし)       |
//|【戻値】true=成功 false=失敗                                      |
//+------------------------------------------------------------------+
bool funcOrder_Send(int orderType, double sl, double tp, double lots, string orderComment, int magic, int maxSpreadPoints){

   int ticket = -1;
   double price = 0;
   double spread = 0;
   color clr = clrNONE;

   //最大10回リトライ
   for(int retry=0; retry<10; retry++){

      RefreshRates();
      spread = MarketInfo(Symbol(),MODE_SPREAD);

      //スプレッドチェック
      if(maxSpreadPoints > 0 && spread > maxSpreadPoints){
         Print("スプレッド拡大中(",spread,"ポイント) → 待機中 (リトライ=",retry+1,")");
         Sleep(2000);
         continue;
      }

      //注文価格を取得
      if(orderType == OP_BUY){
         price = Ask;
         clr = clrBlue;
      }else if(orderType == OP_SELL){
         price = Bid;
         clr = clrRed;
      }else{
         Print("funcOrder_Send: 未対応の注文種別=",orderType);
         return false;
      }

      price = NormalizeDouble(price,Digits);

      if(sl > 0) sl = NormalizeDouble(sl,Digits);
      if(tp > 0) tp = NormalizeDouble(tp,Digits);

      ResetLastError();

      ticket = OrderSend(Symbol(),orderType,lots,price,20,sl,tp,orderComment,magic,0,clr);

      if(ticket > 0){
         Print("新規注文成功! チケットNo=",ticket," レート=",price," Lots=",lots," スプレッド=",spread,"ポイント");
         return true;
      }

      int err = GetLastError();
      Print("新規注文失敗 エラーNo=",err," リトライ回数=",retry+1);
      Sleep(2000);
   }

   return false;
}
スポンサーリンク

MT4のiRSI()関数でRSIの値を取得する

MQL4でRSIの値を取得するときは、MT4標準関数のiRSI()を使用します。

今回の使用例:

double RSI_atai = iRSI(NULL,0,RSI_KIKAN,PRICE_CLOSE,1);

iRSI()の主な引数は次の通りです。

引数今回の指定内容
symbolNULL現在のチャートの通貨ペア
timeframe0現在のチャート時間足
periodRSI_KIKANRSIを計算する期間
applied_pricePRICE_CLOSE終値を計算対象に使用
shift11本前の確定足のRSIを取得

今回のEAでは最後の引数を1にして、1本前の確定足のRSIを取得しています。

RSI期間はパラメータのRSI_KIKANから変更できます。

取得したRSIと売買水準を比較する

取得したRSIを、買い水準のRSI_KAIと売り水準のRSI_URIへ比較します。

if(RSI_atai < RSI_KAI){
   openBuy = true;
}else if(RSI_atai > RSI_URI){
   openSell = true;
}

これだけで、RSIが低い水準へ入った場合はBUY、高い水準へ入った場合はSELLというシンプルな逆張り条件を作れます。

RSIを使った売買判定のイメージ

RSI EAのエントリーポイント解説
RSIの水準を使った逆張りエントリーのイメージ
  • RSIが低い水準まで下がった場合にBUY
  • RSIが高い水準まで上がった場合にSELL
  • 1本前の確定足RSIで判定
  • ポジション保有後は固定TP・SLで決済

新規注文は共通関数funcOrder_Send()を使用

新規注文部分には、ベーステンプレートでも使用している共通のfuncOrder_Send()を利用しています。

今回のRSI EAでは注文変更や独自の成行決済を使用しないため、個別EAのソースには実際に使用する新規注文関数だけを掲載しています。

注文関数そのものの仕組みを詳しく確認したい場合は、以下の記事で解説しています。

RSI EAのパラメータ設定

公開版の基本パラメータは次の通りです。

パラメータ初期値内容
Lots0.011回のエントリーで使用するロット数
TP10利確幅(pips)
SL10損切り幅(pips)
RSI_KIKAN10RSIを計算する期間
RSI_KAI30RSIがこの値を下回るとBUY
RSI_URI76RSIがこの値を上回るとSELL

初期設定ではRSI期間10・買い水準30・売り水準76を使用します。

TP・SLはどちらも10pipsで、ベーステンプレートと同じ固定pips方式です。RSI期間や売買水準とあわせて、パラメータから変更できます。

スポンサーリンク

RSI EAのバックテスト結果

今回は、記事内で公開している初期パラメータのままバックテストを行いました。

USDJPY・H1、2025年8月~2026年7月、初期証拠金100万円、FXTFヒストリカルデータを使用しています。

通貨ペア・時間足PF勝率最大DD取引回数
USDJPY H11.2350.22%0.35%910回
MT4 RSI EAをFXTFヒストリカルデータで検証したバックテストレポート
RSI EAのバックテストレポート

テスター設定のスプレッドは5、不整合チャートエラーは0でした。

今回の条件では、PF1.23、勝率50.22%、最大ドローダウン0.35%となりました。

シンプルなRSI逆張りロジックでも、今回の設定では利益を狙える結果となっています。

同じようにMT4でEAのバックテストを行いたい場合は、FXTFのヒストリカルデータを取得してMT4へ取り込む手順を以下の記事で解説しています。

この結果は掲載条件で行ったバックテスト結果です。
将来の利益を保証するものではなく、通貨ペア・期間・スプレッド・パラメータなどによって結果は変わります。

RSI逆張りEAの弱点と改良ポイント

強いトレンドでは逆張りが不利になることがある

強い上昇トレンドではRSIが高い状態、強い下降トレンドではRSIが低い状態が長く続くことがあります。

そのため、RSI水準だけで逆張りすると、トレンド方向に対して早い段階で反対売買してしまう場合があります。

トレンドフィルターを追加する方法

改良する場合は、例えば次のような条件を組み合わせられます。

  • 移動平均線で大きなトレンド方向を確認する
  • ADXでトレンドが強すぎる場面を除外する
  • ボリンジャーバンドとRSIを組み合わせる
  • 稼働時間帯を限定する
  • RSI期間や売買水準を変更して比較する

ただし、条件を追加すれば必ず成績が改善するわけではありません。ロジックを変更した場合は、バックテストで結果を比較してください。

RSI EAのよくある質問

Q. RSIの70・30は必ず使う必要がありますか?

いいえ。70・30は一般的な目安です。今回のサンプルEAでは買い30・売り76を初期値にしていますが、パラメータから変更できます。

Q. iRSI()の最後の引数を1にしているのはなぜですか?

1本前の確定したローソク足のRSIを取得するためです。0を指定すると現在形成中のローソク足のRSIを取得します。

Q. 複数ポジションを持つRSI EAにできますか?

実装は可能ですが、今回のサンプルはベーステンプレートに合わせて1ポジション構成にしています。複数ポジション管理を追加する場合は、ポジション識別や発注間隔なども含めて設計する必要があります。

Q. なぜMagicNumberを使っていないのですか?

RSIの取得や売買判定、ベーステンプレートから変更した箇所を理解しやすくするためです。そのまま利用する場合は、他のEAや手動ポジションと同じ口座で併用せず、EA単独での検証を推奨しています。

Q. コードを書かずにRSI EAを作ることはできますか?

当サイトの無料MT4 EAビルダーを利用できます。画面上でRSIの条件を設定しながらEAを作成できます。

まとめ|iRSI()を使ってRSI EAを作れる

今回のRSI EAでは、MT4 EAベーステンプレートを土台に、iRSI()を使った逆張りエントリーを追加しました。

  • RSIが低い水準ならBUY、高い水準ならSELL
  • iRSI()で1本前の確定足RSIを取得
  • RSI期間・買い水準・売り水準をパラメータ化
  • TP・SLはベーステンプレートの固定pips方式を利用
  • 個別EAでは使用する共通関数だけを掲載
  • ベーステンプレートからの変更箇所をコード内の背景色で確認可能

ベーステンプレートと今回のRSI版を見比べることで、共通部分を残したまま、インジケーター固有の売買条件だけを追加する流れを確認できます。

他の売買ロジックも試したい場合は、EAサンプルコード一覧から移動平均線・MACD・ボリンジャーバンドなどの実装例を確認できます。

コメント

  1. noriさんのアイコン nori より:

    すいませんが、どこでダウンロードできますか?無料でしょうか?有料でしょうか?有料なら、試用版はありますか

    • りょうさんのアイコン りょう より:

      無料ですよー。掲載しているソースコードをコンパイルさえして頂ければ使えます!(コンパイル済みのファイルはこのサイトにはありません)
      コンパイル方法は、https://fx-prog.com/program-eazy2/のページ等に書いているのですがわからなければ質問して頂ければ回答します!

      • noriさんのアイコン nori より:

        ありがとうございました。私は頭が悪いので、上記ページを拝見しても、できません。残念

  2. EA勉強中さんのアイコン EA勉強中 より:

    始めまして。コード等参考にさせていただいています。
    有益な情報を提供いただきありがとうございます。

    本ページで掲載していただいているコードに、
    例えばエントリーから4時間経過後強制クローズさせたい場合は、
    どのようにコードを組めば良いかご教授いただけないでしょうか。

    • りょうさんのアイコン りょう より:

      はじめまして、参考にして頂きありがとうございます!

      時間によるクローズ処理を入れるとすると、94行目(return(0);の上あたり)に入れるといいと思います。入れるコードはこんな感じでOKです。

      if(OrderSelect(0,SELECT_BY_POS,MODE_TRADES)==true){
      //オーダー後10時間を超えた場合(60秒*240で4時間)
      if(TimeCurrent() – OrderOpenTime() > 60*240){
      OrderKekka = OrderClose(OrderTicket(),OrderLots(),Bid,10,Violet);
      }
      }

      • EA勉強中さんのアイコン EA勉強中 より:

        ご連絡いただき、大変恐縮です。

        これからもりょうさんのHPでEAについて勉強させていただきます。
        ありがとうございました。

  3. EA初心者さんのアイコン EA初心者 より:

    始めまして。
    いつもコード等参考に勉強させて頂いております。
    ありがとうございます。

    こちらのRSIのEAは既にポジションがある場合は追加でエントリーしません。
    となっておりますが、シグナルが出るたびに追加でポジションを取るように変更するには
    どのようなコードを組めば良いかご教授いただけないでしょうか。
    よろしくお願い致します。

    • りょうさんのアイコン りょう より:

      はじめまして、参考にして頂きありがとうございます!

      少しコメントではお伝えするのが難しそうだったので、この記事のソースコードを
      複数ポジション取れるようにバージョンアップします。

      すみませんが、もうしばらくお待ちくださいm(__)m

    • りょうさんのアイコン りょう より:

      記事を更新しました。
      以下のパラメータ設定で調整してみてください。

      ・MAX_POSI = 1 ⇒ 最大ポジション数
      ・WAIT_TIME = 30 ⇒ 複数ポジションエントリー待機時間(分)

      ※最大ポジション数を増やすと、同じ場所で何度もエントリーしてしまうので待機時間の設定を付けました

  4. EA初心者さんのアイコン EA初心者 より:

    りょうさん

    こんばんは。
    新しいソースコードとパラメータを早速作ってご教示してくださり
    ありがとうございました。
    こちらのEAを動かしたり、他の記事のEAを参考に勉強させて頂きたいと思います。
    また何か解らない時やコードについて尋ねることがあると思いますが
    どうぞよろしくお願い致します。

タイトルとURLをコピーしました