上位足のトレンドを確認したくて、

`mtf-ma.md`で紹介したようなMTF移動平均線インジケーターを導入したものの、

線が増えすぎてチャートが見づらくなった、ということはないでしょうか。

上位足の情報を知る方法は、ラインを重ねて描くだけではありません。

この記事では、上位足のトレンド方向を「上昇」「下降」「レンジ」の3状態に判定し、

チャートの端に文字と色だけのパネルで知らせるインジケーターの作り方を解説します。

この記事で分かること
・mtf-ma.mdとの設計方針の違い
・上位足のトレンド方向を3状態で判定する考え方
・iMA()で上位足の値を取得する方法
・文字と色のパネルを表示する実装コード

このインジケーターで分かること・mtf-ma.mdとの違い

まず、既刊の`mtf-ma.md`と本記事の設計方針の違いを整理します。

mtf-ma.mdは上位足の移動平均線を「重ねて描く」方式

`mtf-ma.md`で紹介したインジケーターは、

上位足の移動平均線を、下位足チャートの値動きに重ねて描く方式です。

線の形そのものから上位足の動きを読み取れる反面、

複数の時間足を重ねるとチャートが線だらけになりやすい、という弱点があります。

本記事は上位足の状態を「文字と色のパネル」で知らせる方式

本記事のインジケーターは、

チャートに新しい線を描き足すのではなく、

チャートの端に固定表示する文字パネルで、上位足の状態だけを知らせます。

どちらを選ぶべきか

細かい値動きの形まで見たいなら`mtf-ma.md`のライン方式、

「今は上位足が上昇中か」だけを一目で確認したいなら本記事のパネル方式が向いています。

上位足のトレンド方向をどう判定するか

次に、トレンド方向の判定ロジックを考えます。

短期MAと長期MAの位置関係で判定する考え方

既刊`perfect-order.md`等でも使われている、

短期の移動平均線が長期の移動平均線より上にあれば上昇、

下にあれば下降、という古典的な考え方をそのまま利用します。

「上昇」「下降」「どちらでもない(レンジ)」の3状態にする

短期と長期の差がわずかな場合、上昇・下降のどちらかに断定すると、

実際には方向感のない相場を「トレンド」と誤認してしまいます。

そこで、差が一定の幅(point数)を超えない場合は、

「レンジ」として扱う3状態の判定にします。

判定にヒステリシス(数値の余白)を持たせる理由

補足
・閾値ちょうどで上昇/下降/レンジが頻繁に切り替わる現象をチャタリングと呼びます
・InpRangeThresholdPointsで余白を持たせ、ちらつきを抑えます

iMA関数で上位足の値を取得する

判定の元になる上位足のMA値を取得する方法を確認します。

iMA()のシグネチャ(既刊ima.mdからの再掲)

double iMA(
   string symbol,       //通貨ペア(NULLで現在の通貨ペア)
   int    timeframe,    //時間足(0で現在の時間足)
   int    ma_period,    //MAの平均期間
   int    ma_shift,     //MAシフト
   int    ma_method,    //平均化メソッド(MODE_SMA等)
   int    applied_price,//適用価格(PRICE_CLOSE等)
   int    shift          //何本前の値を取得するか
   );

`timeframe`に現在のチャートより大きい、

時間足の定数(`PERIOD_H4`等)を渡すだけで、

上位足のMA値をそのまま取得できます。

timeframeに現在足より小さい値を指定しないよう注意する

この関数自体は下位足の値を指定しても動作しますが、

本記事の目的は「上位足」の確認であるため、

`OnInit()`の時点で、

現在の時間足以上が指定されているかをチェックしておくと安全です。

パネル表示に使うオブジェクト関数

判定結果をチャート上に表示する方法を確認します。

OBJ_LABELとObjectSetStringで文字を表示する

`OBJ_LABEL`は、チャートの座標ではなく、

画面上の固定位置に文字を表示するオブジェクトです。

`ObjectSetString()`で表示する文字列を、いつでも書き換えられます。

状態に応じて色を変える

`ObjectSetInteger(…, OBJPROP_COLOR, …)`で、

上昇なら緑、下降なら赤、レンジなら灰色、というように状態ごとに色を切り替えます。

実際に動くサンプルコード

上位足のトレンド方向を判定し、パネルに表示するインジケーターです。

//+------------------------------------------------------------------+
//|                                        MtfTrendPanel.mq4          |
//|                     Copyright 2026, FX-EA System Project Creator |
//|                        https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property strict
#property indicator_chart_window

input int    InpHigherTimeframe       = PERIOD_H4; //上位足
input int    InpFastPeriod            = 20;        //短期MA期間
input int    InpSlowPeriod            = 50;        //長期MA期間
input double InpRangeThresholdPoints  = 50;         //レンジ判定の余白(point)

string PanelName = "MtfTrendPanel";

string TimeframeLabel(int tf)
  {
   switch(tf)
     {
      case PERIOD_M15: return("15分足");
      case PERIOD_M30: return("30分足");
      case PERIOD_H1:  return("1時間足");
      case PERIOD_H4:  return("4時間足");
      case PERIOD_D1:  return("日足");
      default:         return("上位足");
     }
  }

int OnInit()
  {
   if(InpHigherTimeframe < _Period)
     {
      Alert("上位足は現在のチャートの時間足以上を指定してください");
      return(INIT_PARAMETERS_INCORRECT);
     }

   ObjectCreate(0, PanelName, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, PanelName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, PanelName, OBJPROP_XDISTANCE, 10);
   ObjectSetInteger(0, PanelName, OBJPROP_YDISTANCE, 20);
   ObjectSetInteger(0, PanelName, OBJPROP_FONTSIZE, 14);

   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   ObjectDelete(0, PanelName);
  }

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[])
  {
   double fastMA = iMA(_Symbol, InpHigherTimeframe, InpFastPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
   double slowMA = iMA(_Symbol, InpHigherTimeframe, InpSlowPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
   double diffPoints = (fastMA - slowMA) / _Point;

   string text;
   color  clr;

   if(diffPoints > InpRangeThresholdPoints)
     {
      text = TimeframeLabel(InpHigherTimeframe) + ": 上昇";
      clr  = clrLimeGreen;
     }
   else if(diffPoints < -InpRangeThresholdPoints)
     {
      text = TimeframeLabel(InpHigherTimeframe) + ": 下降";
      clr  = clrOrangeRed;
     }
   else
     {
      text = TimeframeLabel(InpHigherTimeframe) + ": レンジ";
      clr  = clrGray;
     }

   ObjectSetString(0, PanelName, OBJPROP_TEXT, text);
   ObjectSetInteger(0, PanelName, OBJPROP_COLOR, clr);

   return(rates_total);
  }

`OnCalculate()`は新しいティックのたびに呼ばれるため、

パネルの表示も上位足の状態に合わせてリアルタイムに書き換わります。

MetaEditorでのコンパイル・表示手順

  1. MetaEditorで新規カスタムインジケーター「MtfTrendPanel」を作成し、上のコードを貼り付けてコンパイルする
  2. 1時間足以下のチャートにドラッグ&ドロップで適用する
  3. チャート左上に「4時間足: 上昇」のようなパネルが表示されることを確認する
  4. `InpHigherTimeframe`・`InpRangeThresholdPoints`の値を変え、表示が切り替わる様子を確認する

よくあるエラーと注意点

実際に使う前に確認しておきたい注意点をまとめます。

上位足を現在足より小さく指定すると初期化に失敗する

注意
・下位足を指定するとOnInit()がエラーで止まります
・あくまで『今見ているチャートより大きい時間足』を指定する前提の設計です

新しいバーが確定するまでパネルが更新されない誤解

`iMA()`はリアルタイムの値も取得できるため、

実際には上位足の確定前でも、ティックが来るたびにパネルの文字・色は更新されます。

「バーが確定するまで変わらない」という誤解をしないよう注意してください。

よくある質問

上位足のトレンドパネルについて、よく検索される疑問に回答します。

複数の上位足を同時に表示することはできますか?

できます。`PanelName`を時間足ごとに分け、

パネルの`Y`座標(`OBJPROP_YDISTANCE`)をずらして複数個作成すれば、

4時間足・日足など複数の判定を並べて表示できます。

EAの発注条件にも組み込めますか?

はい。パネル表示と同じ判定ロジック(短期MAと長期MAの差)を関数化すれば、

EAの`OnTick()`内でそのままフィルター条件として使えます。

mtf-ma.mdと両方入れても競合しませんか?

競合しません。`mtf-ma.md`はラインを描くインジケーター、

本記事はオブジェクトラベルのみのインジケーターのため、

同じチャートに両方適用しても表示が干渉することはありません。

【MQL4】上位足のトレンド方向をパネルで表示するインジケーターの作り方(mtf-ma.mdとの違い):まとめ

上位足の情報を知る方法は、ラインを重ねて描くだけではありません。

短期MAと長期MAの差を3状態(上昇・下降・レンジ)に判定し、

文字と色のパネルで知らせることで、

チャートを線だらけにせずに上位足の状態を一目で確認できます。

関連記事