【検証#02】MT4の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は以下の式で計算されます:
問題は、この「平均」をどう計算するか、です。
Cutler's RSI(SMA方式)¶
単純移動平均(SMA) を使用:
// 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) を使用:
// 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の iMA で MODE_SMMA を指定したときと同じ平滑化手法です。
実際の違いを検証¶
両方式でRSIを計算し、差を確認してみましょう。
検証用スクリプト(MQL5)¶
//+------------------------------------------------------------------+
//| 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;
}
期待される出力例¶
=== 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のナビゲーターから「スクリプト」を展開し、チャートにドラッグ&ドロップで実行
関連用語¶
この記事で登場した用語は用語集でも解説しています。