コンテンツにスキップ

【検証#02】MT4のRSIは本当にRSI?

RSI比較スクリプトの実行結果

RSI比較スクリプトの実行結果

この記事の3行まとめ

  • 📊 MT4/MT5の標準RSIは「Wilder's Smoothing」方式(SMMA)を使用
  • 📖 教科書(ワイルダー原典)も実はSMMA方式が正しい
  • ⚠️ 一部チャートソフトの「SMA方式RSI」とは値が異なる

はじめに

この記事は、「とあるMetaTraderの備忘秘録」様のブログ記事を検証・紹介するシリーズの第2弾です。

元ネタ

MT4のRSIは本当にRSI ???
https://fai-fx.hatenadiary.org/entry/20090720/1248018736
(2009年7月20日 公開)

時代背景に関する注意

この記事の元となるブログ記事は2009年頃に公開されたものです。
現在のMQL5/MT5では仕様が変更・改善されている可能性があります。


問題提起:RSIの値がツールによって違う?

RSI(相対力指数)は、J.W.ワイルダーが1978年に考案した人気のオシレーター系指標です。

ところが、MT4/MT5のRSIと他のチャートソフトのRSIを比較すると、微妙に値が違うことがあります。

なぜでしょうか?


RSI計算方式の2つの流派

実は、RSIには主に2つの計算方式が存在します。

計算式の比較

方式 平均化手法 特徴
Cutler's RSI 単純移動平均(SMA) 単純だが反応が鈍い
Wilder's RSI Wilder's Smoothing(SMMA) ワイルダー原典準拠、MT4/MT5採用

RSIの基本式

RSIは以下の式で計算されます:

\[ RSI = 100 - \frac{100}{1 + RS} \]
\[ RS = \frac{平均上昇幅}{平均下落幅} \]

問題は、この「平均」をどう計算するか、です。


Cutler's RSI(SMA方式)

単純移動平均(SMA) を使用:

\[ 平均上昇幅 = \frac{\sum_{i=1}^{N} 上昇幅_i}{N} \]
MQL
// SMA方式(Cutler's RSI)の疑似コード
double sumGain = 0, sumLoss = 0;
for(int i = 0; i < period; i++)
{
    double change = close[i] - close[i+1];
    if(change > 0) sumGain += change;
    else           sumLoss -= change;  // 絶対値
}
double avgGain = sumGain / period;
double avgLoss = sumLoss / period;

Wilder's RSI(SMMA方式)— MT4/MT5標準

Wilder's Smoothing(SMMA) を使用:

\[ 平均上昇幅_t = \frac{平均上昇幅_{t-1} \times (N-1) + 上昇幅_t}{N} \]
MQL
// SMMA方式(Wilder's RSI)の疑似コード
// 初回はSMAで計算
double avgGain = sumGain / period;
double avgLoss = sumLoss / period;

// 2回目以降は前回値を引き継ぐ
avgGain = (prevAvgGain * (period - 1) + currentGain) / period;
avgLoss = (prevAvgLoss * (period - 1) + currentLoss) / period;

Wilder's Smoothing = SMMA

この計算方式は 「平滑移動平均(Smoothed Moving Average)」 とも呼ばれます。
MT5の iMAMODE_SMMA を指定したときと同じ平滑化手法です。


実際の違いを検証

両方式でRSIを計算し、差を確認してみましょう。

検証用スクリプト(MQL5)

MQL
//+------------------------------------------------------------------+
//|                                          RSI_Comparison.mq5      |
//| 「とあるMetaTraderの備忘秘録」様の記事を検証                      |
//| https://fai-fx.hatenadiary.org/entry/20090720/1248018736         |
//+------------------------------------------------------------------+
#property copyright "FXおもしろラボ"
#property link      "https://fx-omoshiro-lab.com/"
#property version   "1.00"
#property script_show_inputs

input int RSI_Period = 14;  // RSI期間

//+------------------------------------------------------------------+
//| Script program start function                                     |
//+------------------------------------------------------------------+
void OnStart()
{
    Print("=== RSI計算方式 比較テスト ===");
    Print("通貨ペア: ", _Symbol, " | 期間: ", RSI_Period);

    // 終値を取得
    double close[];
    ArraySetAsSeries(close, true);
    int copied = CopyClose(_Symbol, PERIOD_CURRENT, 0, RSI_Period + 50, close);
    if(copied < RSI_Period + 50)
    {
        Print("データ不足: ", copied);
        return;
    }

    // 標準RSI(Wilder's/SMMA方式)
    int rsiHandle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
    if(rsiHandle == INVALID_HANDLE)
    {
        Print("RSIハンドル取得失敗");
        return;
    }

    double rsiBuffer[];
    ArraySetAsSeries(rsiBuffer, true);
    CopyBuffer(rsiHandle, 0, 0, 10, rsiBuffer);

    // SMA方式でRSIを自前計算
    double rsiSMA = CalculateRSI_SMA(close, RSI_Period, 0);

    Print("");
    Print("--- 現在のバーでの比較 ---");
    Print("標準RSI (SMMA方式): ", DoubleToString(rsiBuffer[0], 2));
    Print("自前RSI (SMA方式) : ", DoubleToString(rsiSMA, 2));
    Print("差                : ", DoubleToString(MathAbs(rsiBuffer[0] - rsiSMA), 2));
    Print("");

    // 複数バーで比較
    Print("--- 直近10バーの比較 ---");
    Print("Bar | SMMA方式 | SMA方式  | 差");
    Print("----+----------+----------+------");

    for(int i = 0; i < 10; i++)
    {
        double smaRsi = CalculateRSI_SMA(close, RSI_Period, i);
        double diff = MathAbs(rsiBuffer[i] - smaRsi);
        PrintFormat("%3d | %8.2f | %8.2f | %5.2f", 
                    i, rsiBuffer[i], smaRsi, diff);
    }

    IndicatorRelease(rsiHandle);
    Print("");
    Print("=== テスト完了 ===");
}

//+------------------------------------------------------------------+
//| SMA方式でRSIを計算                                                |
//+------------------------------------------------------------------+
double CalculateRSI_SMA(const double &close[], int period, int shift)
{
    double sumGain = 0;
    double sumLoss = 0;

    for(int i = shift; i < shift + period; i++)
    {
        double change = close[i] - close[i + 1];
        if(change > 0)
            sumGain += change;
        else
            sumLoss -= change;  // 絶対値として加算
    }

    double avgGain = sumGain / period;
    double avgLoss = sumLoss / period;

    if(avgLoss == 0)
        return 100.0;

    double rs = avgGain / avgLoss;
    double rsi = 100.0 - (100.0 / (1.0 + rs));

    return rsi;
}

期待される出力例

Text Only
=== RSI計算方式 比較テスト ===
通貨ペア: USDJPY | 期間: 14

--- 現在のバーでの比較 ---
標準RSI (SMMA方式): 54.32
自前RSI (SMA方式) : 51.87
差                : 2.45

--- 直近10バーの比較 ---
Bar | SMMA方式 | SMA方式  | 差
----+----------+----------+------
  0 |    54.32 |    51.87 |  2.45
  1 |    55.10 |    52.34 |  2.76
  ...

なぜ差が出るのか

方式 メモリ効果 過去データの影響
SMA方式 なし 直近N本のみ
SMMA方式 あり 全履歴が徐々に影響

SMMA方式は前回の平均値を引き継ぐため、「メモリ効果」があります。 これにより、過去のすべてのデータが(減衰しながらも)現在の値に影響を与えます。

一方、SMA方式は直近N本のデータだけで計算するため、反応がより敏感です。


どちらが「正しい」のか

ワイルダー原典はSMMA方式

J.W.ワイルダーの著書『New Concepts in Technical Trading Systems』(1978年)では、
SMMA方式(Wilder's Smoothing)が使われています。
したがって、MT4/MT5の実装は原典に忠実です。

ただし、一部のチャートソフトやWebサイトではSMA方式を採用していることがあり、 これが「RSIの値が違う」と感じる原因になります。

実務上の注意点

シナリオ 推奨
MT4/MT5だけで完結する 標準RSIを使えばOK
他ツールと比較したい 計算方式を確認すること
バックテストと本番の一貫性 同じ方式を使い続けることが重要

まとめ

ポイント 内容
問題 RSIの値がツールによって異なる場合がある
原因 SMA方式とSMMA方式の2つの流派が存在
MT4/MT5 SMMA方式(ワイルダー原典準拠)
対策 使用ツールの計算方式を理解しておく

オリジナル記事への謝辞

この記事は「とあるMetaTraderの備忘秘録」様の貴重な知見をもとに、
MQL5での検証と解説を加えたものです。
オリジナル記事に心より感謝いたします。


ソースコードのダウンロード

この記事で紹介したコードをダウンロードできます。

ファイルの種類:スクリプト

保存先: MQL5/Scripts/ フォルダ
使い方: MT5のナビゲーターから「スクリプト」を展開し、チャートにドラッグ&ドロップで実行

02_RSI_Comparison.mq5 をダウンロード


関連用語

この記事で登場した用語は用語集でも解説しています。