iMFIは、価格の動きと出来高の両方を使って、

「買われすぎ・売られすぎ」を判定するMQL4の組み込み関数です。

既刊のテクニカルインジケーター関数一覧記事で名前だけは触れていましたが、

このサイトではまだiMFI単独の解説記事がありませんでした。

この記事では、iMFIの引数と戻り値を整理したうえで、

買われすぎ・売られすぎの領域に入った瞬間だけを検知する、

実際に動くインジケーターの作り方を解説します。

この記事で分かること
・iMFIの4つの引数と戻り値の意味
・既刊iRSIとの計算対象の違い(出来高を使うかどうか)
・既刊iOBVと共通するFXでの出来高の注意点
・実際に動くコード全体

設計思想: なぜ出来高込みの指標が必要か

まず、iMFIが既刊のオシレーター系指標と何が違うのかを整理します。

既刊iRSIとの計算対象の違い

RSIは、終値の上げ下げだけを見て、

買われすぎ・売られすぎを判定します。

一方、MFIは出来高も加味するため、

「価格は動いていないのに出来高だけ急増している」ような、

RSIでは見えない変化も反映されます。

指標 使う値 出来高の扱い
iRSI(既刊) 終値の上げ下げ 使わない
iMFI(本記事) 典型価格×出来高 使う(別名「出来高加重RSI」)

MFIはよく「出来高版のRSI」と呼ばれますが、

計算式自体はRSIとは別物です。

既刊iOBVと共通するFXでの出来高の注意点

既刊のiOBV記事で指摘したとおり、

FXにおける出来高(volume)は、

実際の売買量ではなく「ティックボリューム」(値動きの回数)です。

FXでMFIを使う際の注意
・MT4のvolumeは実出来高ではなくティックボリューム
・ブローカーのサーバーを通過した値動きの回数であり、市場全体の出来高ではない
・株式市場のMFIとまったく同じ前提で解釈しないよう注意が必要

この前提を踏まえたうえで、

「普段よりティックの動きが活発かどうか」を測る指標として使います。

iMFI関数の引数と戻り値

公式リファレンス(MQL4 Reference: iMFI)の内容を整理します。

4つの引数の意味

double iMFI(
   string symbol,    // 通貨ペア名(NULLで現在のチャート)
   int    timeframe, // 時間足(0で現在の時間足)
   int    period,     // 計算期間
   int    shift        // 何本前のバーの値を取得するか
);

iRSIと同じく期間を1つ指定するだけのシンプルな構成で、

適用価格を選べない点が特徴です。

MQL5版との違い: 戻り値と出来高の種類の指定

MQL4のiMFIは、値をdoubleで直接返します。

一方、MQL5のiMFI(MQL5 Reference: iMFI)は、

値ではなくインジケーターのハンドル(int)を返します。

MQL5版の追加引数
・applied_volumeという引数が追加されている
・ティックボリュームか実出来高かを明示的に選べる
・MQL4版には無い選択肢で、FXではティックボリューム相当の指定が基本になる

既刊のMQL4→MQL5移行チェックリストと同じ、

テクニカル指標のハンドル方式化という変化点がここにも当てはまります。

サンプルインジケーター: 領域進入を検知する設計

単に値を表示するだけでなく、

買われすぎ・売られすぎの領域に入った瞬間だけを矢印で知らせます。

領域の閾値とクロス判定

一般的に80以上を買われすぎ、

20以下を売られすぎの目安として使います。

前のバーでは領域外、今のバーで領域内に入った瞬間だけを検知します。

ラインバッファと矢印バッファの2本立て

MFIの値そのものをラインで描画しつつ、

領域に進入した瞬間だけ別バッファで矢印を出す構成にしています。

実際に動くコード全体

実際にMetaEditorでコンパイルできる、

MFIラインと領域進入矢印を表示するインジケーターです。

//+------------------------------------------------------------------+
//|                                    MFIZoneEntryIndicator.mq4     |
//|                     Copyright 2026, FX-EA System Project Creator |
//|                        https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FX-EA System Project Creator"
#property link      "https://creator.fx-ea-system-project.com/"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_buffers 3
#property indicator_color1 DodgerBlue
#property indicator_color2 Red
#property indicator_color3 Lime
#property indicator_width2 2
#property indicator_width3 2

input int InpMfiPeriod   = 14;  //MFIの計算期間
input int InpUpperZone   = 80;  //買われすぎの閾値
input int InpLowerZone   = 20;  //売られすぎの閾値

double MfiBuffer[];
double UpperEntryArrow[];
double LowerEntryArrow[];

int OnInit()
  {
   SetIndexBuffer(0, MfiBuffer);
   SetIndexStyle(0, DRAW_LINE);

   SetIndexBuffer(1, UpperEntryArrow);
   SetIndexStyle(1, DRAW_ARROW, EMPTY, 2);
   SetIndexArrow(1, 242);
   SetIndexEmptyValue(1, EMPTY_VALUE);

   SetIndexBuffer(2, LowerEntryArrow);
   SetIndexStyle(2, DRAW_ARROW, EMPTY, 2);
   SetIndexArrow(2, 241);
   SetIndexEmptyValue(2, EMPTY_VALUE);

   IndicatorShortName("MFI Zone Entry Detector");
   return(INIT_SUCCEEDED);
  }

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   int needed = InpMfiPeriod + 2;
   if(rates_total < needed)
      return(0);

   int limit = (prev_calculated == 0) ? rates_total - needed : rates_total - prev_calculated + 1;

   for(int i = limit; i >= 0; i--)
     {
      MfiBuffer[i] = iMFI(NULL, 0, InpMfiPeriod, i);
      UpperEntryArrow[i] = EMPTY_VALUE;
      LowerEntryArrow[i] = EMPTY_VALUE;

      if(i + 1 >= rates_total)
         continue;

      double curMfi  = MfiBuffer[i];
      double prevMfi = iMFI(NULL, 0, InpMfiPeriod, i + 1);

      bool enteredUpper = (prevMfi < InpUpperZone && curMfi >= InpUpperZone);
      bool enteredLower = (prevMfi > InpLowerZone && curMfi <= InpLowerZone);

      if(enteredUpper)
         UpperEntryArrow[i] = curMfi + 5;
      if(enteredLower)
         LowerEntryArrow[i] = curMfi - 5;
     }

   return(rates_total);
  }

MetaEditorでのコンパイル・実行手順

実際にMT4で動かすまでの手順です。

  1. MetaEditorで新規インジケーター「MFIZoneEntryIndicator」を作成し、上のコードを貼り付けてコンパイルする
  2. エラー・警告が0件であることを確認する
  3. サブウィンドウにMFIのラインが0〜100の範囲で表示されることを確認する
  4. 80以上に入った瞬間に赤い矢印、20以下に入った瞬間に緑の矢印が出ることを確認する
  5. InpUpperZone・InpLowerZoneを変えて、矢印の出る頻度が変わることを確認する

よくあるエラーと注意点

実装でつまずきやすいポイントをまとめます。

indicator_minimum/maximumの指定漏れ

MFIは0〜100の範囲で動く指標のため、

サブウィンドウの表示範囲を固定しておくと見やすくなります。

指定を忘れると、

自動スケールでグラフが見づらくなることがあります。

領域の閾値を跨いだ瞬間ではなく値そのもので判定する

「80以上なら売り」のように毎バー判定すると、

同じシグナルが連続して出てしまいます。

本記事のようにクロスした瞬間だけに絞ることをおすすめします。

MQL5移植時にapplied_volumeを指定し忘れる

前述のとおり、MQL5版はapplied_volumeという引数が追加されています。

MQL4からそのまま移植する際は、

この引数の指定を忘れないようにしてください。

既刊のオシレーター系記事との使い分け

似た目的の記事が複数あるため、使い分けを整理します。

記事 使う値 用途
本記事(iMFI) 典型価格×出来高 出来高込みの買われすぎ・売られすぎ判定
iRSI記事(既刊) 終値の上げ下げ 価格だけの買われすぎ・売られすぎ判定
iOBV記事(既刊) 出来高の累積 出来高の傾きからトレンドの裏付けを確認

よくある質問

iMFIについて、よくある疑問に回答します。

iMFIとiRSI、どちらを使うべきですか?

目的によって使い分けます。

価格の動きだけを見たいならiRSI、

出来高(ティックボリューム)の変化も加味したいならiMFIが向いています。

FXでMFIを使う意味はありますか?

前述のとおり、実出来高ではない点は踏まえる必要がありますが、

「普段よりティックの動きが活発な時間帯か」を測る目的では使えます。

株式市場の出来高と同じ意味で解釈しないことが重要です。

このインジケーターをEAのフィルターに使えますか?

使えます。

領域進入の判定部分だけを関数化すれば、

既刊のストキャスティクス逆張りEAと同じ要領でエントリー条件に組み込めます。

【MQL4】iMFI(Money Flow Index)で出来高込みの「買われすぎ・売られすぎ」を判定するインジケーターの作り方:まとめ

iMFIは、既刊iRSIとは違い、

典型価格と出来高の両方を使って買われすぎ・売られすぎを判定する関数です。

既刊iOBVと同じく、

FXのティックボリュームは実出来高ではない点に注意しながら使う必要があります。

MQL5では戻り値がハンドルに変わり、

出来高の種類を選べる引数が増える点も覚えておくと移行時の事故を防げます。

関連記事