ADX(Average Directional Movement Index)は「トレンドの強さ」
を測る定番のテクニカル指標ですが、実際にチャートに表示すると「今日のADXは23.4」
のような生の数値がそのまま出てくるだけで、それが強いのか弱いのか、
パッと見て判断できないという声をよく聞きます。
一般的には「25以上がトレンド」と言われますが、毎回この基準を覚えて数値と見比べるのは地味に面倒です。
この記事では、ADXの生の数値を「レンジ」
「様子見」
「強いトレンド」という3段階の日本語ラベルに変換し、あわせて上昇/下降の方向まで一目で表示するオリジナルインジケーターの作り方を、
設計の考え方と実際に動くコードで解説します。
設計の考え方: 数値ではなく「状態」を表示する
このインジケーターの設計方針は次の3つです。
- 閾値をハードコードしない: 「25以上がトレンド」という基準は通貨ペアや時間足によって体感が変わるため、inputパラメーターとして外に出し、後から調整できるようにする
- 数値を状態(3段階)に集約する: 生のADX値をそのまま表示するのではなく、「レンジ」「様子見」「強いトレンド」という3つの状態のどれに該当するかを判定してから表示する
- 強さと方向を分けて考える: ADXの主線(MODE_MAIN)は「強さ」しか表さず、上昇/下降どちらのトレンドかは分かりません。方向の判定には+DI/-DIという別の2本の値が必要になるため、この2つを組み合わせて初めて「強い上昇トレンド」のような表示ができます
iADX関数でADXと+DI/-DIを取得する
ADXの主線(強さ)と方向を判定するための+DI/-DIは、
すべて同じ`iADX()`関数からmode引数を変えて取得します。
double iADX( string symbol, //通貨ペア(NULLで現在のチャート) int timeframe, //時間足(0で現在のチャートの時間足) int period, //ADXの計算期間(標準14) int applied_price, //価格の種類(通常PRICE_CLOSE) int mode, //取得する線の種類 int shift //何本前の足を見るか(0=最新、1=1つ前の確定足) );
mode引数には以下を指定します。
- MODE_MAIN(値は0) — ADX主線(トレンドの「強さ」)
- MODE_PLUSDI(値は1) — +DI(上昇方向の勢い)
- MODE_MINUSDI(値は2) — -DI(下降方向の勢い)
double adx = iADX(NULL, 0, 14, PRICE_CLOSE, MODE_MAIN, 1);//ADX主線(1つ前の確定足) double plusDI = iADX(NULL, 0, 14, PRICE_CLOSE, MODE_PLUSDI, 1);//+DI double minusDI= iADX(NULL, 0, 14, PRICE_CLOSE, MODE_MINUSDI, 1);//-DI
`iIchimoku()`と同じく、1つの関数をmode引数で使い分ける設計です。
iATR()等と同様、shift=0は形成中の足になるため、
判定用にはshift=1(直近の確定足)を使います。
ADX値を3段階の状態に変換する
取得したADX値を、inputで指定した2つの閾値(弱いトレンドと強いトレンドの境目)と比較して、
3段階の状態文字列に変換します。
string GetTrendState(double adx, double weakThreshold, double strongThreshold)
{
if(adx < weakThreshold)
return("レンジ(方向感なし)");
if(adx < strongThreshold)
return("様子見(トレンド形成中)");
return("強いトレンド");
}
方向は+DIと-DIの大小関係だけで判定します。
string GetTrendDirection(double plusDI, double minusDI)
{
if(plusDI > minusDI)
return("▲上昇方向");
if(minusDI > plusDI)
return("▼下降方向");
return("方向感なし");
}
状態(強さ)と方向(上昇/下降)を分けて関数化しておくことで、
「レンジのときは方向を表示しない」のような条件分岐もあとから足しやすくなります。
実際に動くコード全体
ここまでの内容をまとめた、ADXの状態と方向をチャート左上に日本語で表示する、
実際にMetaEditorでコンパイルできるインジケーターです。
//+------------------------------------------------------------------+
//| ADXTrendState.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_chart_window
#property indicator_buffers 0
input int ADXPeriod = 14;//ADXの計算期間
input double WeakThreshold = 20.0;//これ未満は「レンジ」とみなす閾値
input double StrongThreshold = 25.0;//これ以上は「強いトレンド」とみなす閾値
//このインジケーターはチャートに線を描かず、値をComment()で表示するだけなので、
//バッファ0個で問題ありません(線を描く場合は1以上が必要です)。
//+------------------------------------------------------------------+
//| ADX値を3段階の状態に変換する |
//+------------------------------------------------------------------+
string GetTrendState(double adx, double weakThreshold, double strongThreshold)
{
if(adx < weakThreshold)
return("レンジ(方向感なし)");
if(adx < strongThreshold)
return("様子見(トレンド形成中)");
return("強いトレンド");
}
//+------------------------------------------------------------------+
//| +DI/-DIの大小関係から方向を判定する |
//+------------------------------------------------------------------+
string GetTrendDirection(double plusDI, double minusDI)
{
if(plusDI > minusDI)
return("▲上昇方向");
if(minusDI > plusDI)
return("▼下降方向");
return("方向感なし");
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
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 adx = iADX(NULL, 0, ADXPeriod, PRICE_CLOSE, MODE_MAIN, 1);
double plusDI = iADX(NULL, 0, ADXPeriod, PRICE_CLOSE, MODE_PLUSDI, 1);
double minusDI = iADX(NULL, 0, ADXPeriod, PRICE_CLOSE, MODE_MINUSDI, 1);
string state = GetTrendState(adx, WeakThreshold, StrongThreshold);
string direction = GetTrendDirection(plusDI, minusDI);
Comment(
"ADX(", ADXPeriod, ")= ", DoubleToString(adx, 1), "\n",
"状態: ", state, "\n",
"方向: ", direction, "\n",
"(+DI=", DoubleToString(plusDI, 1), " / -DI=", DoubleToString(minusDI, 1), ")"
);
return(rates_total);
}
//+------------------------------------------------------------------+
MetaEditorで実際に動かす手順
- MT4の「ツール」→「MetaQuotes Language Editor」でMetaEditorを開く
- 「ファイル」→「新規作成」→「インジケーター」を選び、名前を「ADXTrendState」にして作成する(中身は空のテンプレートで構いません)
- テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
- F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- MT4の「ナビゲーター」パネルからインジケーターを探し、チャートへドラッグ&ドロップする
- チャート左上に「状態: 強いトレンド」「方向: ▲上昇方向」のような表示が出れば成功です
コピペしてコンパイルが通らないときに確認すること
- 拡張子が「.mq4」になっているか
- `GetTrendState()`・`GetTrendDirection()`の2つの関数を、`OnCalculate()`より上(コードの先頭側)に配置しているか(MQL4は呼び出す関数を先に定義しておく必要があります)
- WeakThreshold(既定20)とStrongThreshold(既定25)の大小関係が逆転していないか(WeakThresholdの方が必ず小さい値である必要があります)
実運用でのカスタマイズ例
このインジケーター単体でエントリーを判断するのではなく、既存のEA記事群と組み合わせる使い方が実務的です。
たとえば「状態が強いトレンドのときだけエントリーする」という条件を、
ゴールデンクロスEAのOnTick()冒頭に1行追加するだけで、
レンジ相場でのダマシを減らすフィルターとして機能します。
//EA側での使用例(GetTrendState/GetTrendDirectionを同じファイルにコピーして使う場合) if(GetTrendState(iADX(NULL,0,14,PRICE_CLOSE,MODE_MAIN,1), 20.0, 25.0) != "強いトレンド") return;//強いトレンドでなければ何もしない
まとめ
ADXの生の数値を毎回覚えた閾値と見比べるのではなく、状態(3段階)と方向(上昇/下降)に変換して表示するだけで、
トレンドの強さが一目で分かるインジケーターになります。
閾値をinputで外出ししているため、通貨ペアや時間足に応じて「レンジ」
「強いトレンド」の境目を自分で調整できる点もポイントです。
今回のGetTrendState()・GetTrendDirection()は、
EA側にそのままコピーすればエントリーフィルターとしても使えます。
コメント