【MQL4入門】iRSI関数の使い方を徹底解説!RSIを使ったEA開発の基本とサンプルコード

【初級編】MQLプログラミング基礎

RSI(Relative Strength Index)は、FXトレーダーなら一度は使ったことがあるほど人気のテクニカル指標です。「買われすぎ」「売られすぎ」を数値で判断できるため、逆張りトレードの根拠として非常に重宝します。

MQL4では、iRSI関数を使うことで、たった1行のコードでRSIの値を取得できます。この記事では、iRSI関数のパラメータの意味から、実際に動作する逆張りEAのサンプルコードまで、初心者にもわかりやすく徹底解説します!

RSIとは?基本をおさらい

RSI(相対力指数)は、一定期間の値動きにおける「上昇幅」と「下降幅」の比率から、相場の過熱感を0〜100の数値で表すオシレーター系指標です。

RSIの一般的な判断基準

  • RSI ≧ 70:買われすぎ → 売りシグナルの候補
  • RSI ≦ 30:売られすぎ → 買いシグナルの候補
  • RSI = 50付近:方向感なし(中立)

計算に使う期間は14が最も一般的で、MetaTraderのデフォルト設定でも14が使われています。期間を短くすると感度が高くなりダマシも増え、長くすると滑らかになりますがシグナルが遅れる傾向があります。

iRSI関数の書式とパラメータ

MQL4でRSIの値を取得するには、iRSI関数を使います。書式は以下のとおりです。

double iRSI(
    string symbol,        // 通貨ペア名
    int    timeframe,     // 時間足
    int    period,        // RSIの計算期間
    int    applied_price, // 適用価格
    int    shift          // シフト(何本前の足か)
);

各パラメータの詳細

パラメータ 説明 よく使う値
symbol string 通貨ペア名。NULLで現在のチャートの通貨ペア NULL, Symbol()
timeframe int 時間足を指定する定数 0(現在の時間足)
period int RSIの計算期間 14
applied_price int 計算に使う価格の種類 PRICE_CLOSE
shift int 何本前の足のRSI値を取得するか 0, 1

時間足定数の一覧

定数名 意味
PERIOD_CURRENT 0 現在のチャートの時間足
PERIOD_M1 1 1分足
PERIOD_M5 5 5分足
PERIOD_M15 15 15分足
PERIOD_M30 30 30分足
PERIOD_H1 60 1時間足
PERIOD_H4 240 4時間足
PERIOD_D1 1440 日足
PERIOD_W1 10080 週足
PERIOD_MN1 43200 月足

適用価格定数の一覧

定数名 意味
PRICE_CLOSE 0 終値(最も一般的)
PRICE_OPEN 1 始値
PRICE_HIGH 2 高値
PRICE_LOW 3 安値
PRICE_MEDIAN 4 中央値((高値+安値)/2)
PRICE_TYPICAL 5 典型価格((高値+安値+終値)/3)
PRICE_WEIGHTED 6 加重終値((高値+安値+終値+終値)/4)

基本的な使い方

まずは最もシンプルなiRSI関数の呼び出し方を見てみましょう。

void OnTick()
{
    // 現在の足(確定前)のRSI値を取得
    double rsi_current = iRSI(NULL, 0, 14, PRICE_CLOSE, 0);

    // 1本前の足(確定済み)のRSI値を取得
    double rsi_prev = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);

    // ログに出力して確認
    Print("RSI(現在): ", rsi_current, " / RSI(1本前): ", rsi_prev);
}

ここで重要なのがshiftパラメータの使い分けです。

  • shift=0:現在形成中のローソク足のRSI値。ティックごとに値が変わる(未確定値
  • shift=1:1本前の確定済みローソク足のRSI値。その足が閉じた後は変化しない(確定値

EAのエントリー判断では、shift=1(確定値)を基準に使うのが一般的です。未確定の値で判断すると、ローソク足が確定する前にシグナルが出たり消えたりして、誤ったエントリーにつながる可能性があります。

実践!RSI逆張りEAのサンプルコード

ここからは、RSIの「売られすぎ→反転上昇」で買い、「買われすぎ→反転下降」で売るという逆張りロジックのEAを作ってみましょう。単にRSIが閾値を超えているかどうかだけでなく、「閾値を下から上に(または上から下に)抜けた瞬間」を検知するテクニックを使います。

//+------------------------------------------------------------------+
//|                                              RSI_Reversal_EA.mq4 |
//|                        RSI逆張りEAサンプル                         |
//+------------------------------------------------------------------+
#property strict

// === 入力パラメータ ===
input int    RSI_Period      = 14;           // RSI計算期間
input double RSI_UpperLevel  = 70.0;         // 買われすぎライン
input double RSI_LowerLevel  = 30.0;         // 売られすぎライン
input double LotSize         = 0.01;         // ロットサイズ
input int    StopLoss_Pips   = 50;           // ストップロス(pips)
input int    TakeProfit_Pips = 100;          // テイクプロフィット(pips)
input int    MagicNumber     = 12345;        // マジックナンバー

// === グローバル変数 ===
datetime lastBarTime = 0; // 新しい足の検出用

//+------------------------------------------------------------------+
//| Expert initialization function                                     |
//+------------------------------------------------------------------+
int OnInit()
{
    Print("RSI逆張りEA 起動 - Period:", RSI_Period,
          " Upper:", RSI_UpperLevel, " Lower:", RSI_LowerLevel);
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                               |
//+------------------------------------------------------------------+
void OnTick()
{
    // --- 新しい足が確定したときだけ処理を行う ---
    if(Time[0] == lastBarTime)
        return;
    lastBarTime = Time[0];

    // --- 既にポジションを持っていたらエントリーしない ---
    if(CountMyOrders() > 0)
        return;

    // --- RSI値を取得 ---
    double rsi1 = iRSI(NULL, 0, RSI_Period, PRICE_CLOSE, 1); // 1本前(確定)
    double rsi2 = iRSI(NULL, 0, RSI_Period, PRICE_CLOSE, 2); // 2本前(確定)

    // --- pipsをポイントに変換(5桁/3桁ブローカー対応)---
    double point = Point;
    if(Digits == 3 || Digits == 5)
        point = Point * 10;

    double sl, tp;

    // === 買いエントリー条件 ===
    // RSIが「売られすぎライン」を下から上に抜けた瞬間
    if(rsi2 < RSI_LowerLevel && rsi1 >= RSI_LowerLevel)
    {
        sl = Ask - StopLoss_Pips * point;
        tp = Ask + TakeProfit_Pips * point;

        int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, sl, tp,
                               "RSI Buy", MagicNumber, 0, clrBlue);
        if(ticket > 0)
            Print("買いエントリー成功 RSI(2本前):", rsi2, " RSI(1本前):", rsi1);
        else
            Print("買いエントリー失敗 Error:", GetLastError());
    }

    // === 売りエントリー条件 ===
    // RSIが「買われすぎライン」を上から下に抜けた瞬間
    if(rsi2 > RSI_UpperLevel && rsi1 <= RSI_UpperLevel)
    {
        sl = Bid + StopLoss_Pips * point;
        tp = Bid - TakeProfit_Pips * point;

        int ticket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, 3, sl, tp,
                               "RSI Sell", MagicNumber, 0, clrRed);
        if(ticket > 0)
            Print("売りエントリー成功 RSI(2本前):", rsi2, " RSI(1本前):", rsi1);
        else
            Print("売りエントリー失敗 Error:", GetLastError());
    }
}

//+------------------------------------------------------------------+
//| 自分のEAのポジション数をカウント                                     |
//+------------------------------------------------------------------+
int CountMyOrders()
{
    int count = 0;
    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
                count++;
        }
    }
    return count;
}

サンプルコードの4つのポイント

① 新しい足の検出で無駄な処理を防止

Time[0] == lastBarTime のチェックにより、新しいローソク足が確定したタイミングでのみエントリー判断を行います。ティックごとに何度もオーダーを送るのを防ぎ、安定した動作を実現します。

② RSIの「クロス」で瞬間を捉える

単に「RSIが30以下」だけでエントリーすると、RSIが30以下にいる間ずっとシグナルが出続けてしまいます。そこで、2本前のRSI(rsi2)と1本前のRSI(rsi1)を比較し、閾値を「抜けた瞬間」だけを検知しています。

// 例:売られすぎラインを下から上に抜けた瞬間
if(rsi2 < RSI_LowerLevel && rsi1 >= RSI_LowerLevel)

この条件は「2本前はまだ30未満だったが、1本前で30以上に回復した」ことを意味します。つまり、売られすぎの状態から反転し始めた瞬間にエントリーできるわけです。

③ MagicNumberでEAを識別

MagicNumberを設定することで、複数のEAを同時に稼働させてもポジションの管理が混乱しません。CountMyOrders()関数では、通貨ペアとMagicNumberの両方が一致するポジションだけをカウントしています。

④ 5桁ブローカー対応のpips変換

近年のFXブローカーの多くは5桁(3桁)の価格表示を採用しています。Digits == 5の場合はPoint * 10として、pips単位の指定が正しく反映されるようにしています。

iRSI関数を使うときの注意点

shift=0の値は未確定

先ほども触れましたが、shift=0で取得できるRSIの値はティックごとに変化します。エントリー判断に使う場合は、基本的にshift=1以上の確定値を使いましょう。

マルチタイムフレーム分析への応用

iRSI関数の第2引数(timeframe)を変えることで、現在のチャートとは異なる時間足のRSI値も取得できます。

// 現在のチャートが5分足でも、日足のRSIを取得できる
double rsi_daily = iRSI(NULL, PERIOD_D1, 14, PRICE_CLOSE, 1);

// 4時間足のRSI
double rsi_h4 = iRSI(NULL, PERIOD_H4, 14, PRICE_CLOSE, 1);

例えば「日足のRSIが50以上のときだけ、短期足で買いエントリーする」といったフィルターとして活用できます。

チャート上のRSIインジケーターとの値一致

iRSI関数で取得した値は、MetaTrader上でRSIインジケーターを表示したときの値と同じパラメータを指定すれば一致します。値がずれる場合は、計算期間や適用価格の設定が異なっていないか確認してみてください。

まとめ

この記事では、MQL4のiRSI関数について、基本から実践まで解説しました。ポイントを振り返りましょう。

  • iRSI関数は5つの引数(通貨ペア、時間足、期間、適用価格、シフト)を指定してRSI値を取得する
  • エントリー判断にはshift=1(確定値)を使うのが基本
  • RSIの閾値を「抜けた瞬間」を検知するには、2本分のRSI値を比較する
  • timeframeパラメータを活用すればマルチタイムフレーム分析も簡単
  • MagicNumber管理や5桁ブローカー対応など、実運用を意識した実装が大切

RSIは非常にシンプルな指標ですが、移動平均線やボリンジャーバンドなど他のインジケーターと組み合わせることで、より精度の高いEAに発展させることができます。まずは今回のサンプルコードをベースに、ストラテジーテスターで動作を確認するところから始めてみてください!