MT4で「トレンドが出ているかどうか」を判定したくて`iADX()`のリファレンスを調べても、
公式ドキュメントには`MODE_MAIN`・`MODE_PLUSDI`・`MODE_MINUSDI`という3つの定数が並んでいるだけで、
「結局どれを使えば方向まで分かるのか」がすぐには分かりません。
ADXという指標名から「上か下かを教えてくれる指標」だと誤解したまま実装してしまう人も少なくありません。
この記事では、`iADX()`関数の3つのバッファ(MODE_MAIN/MODE_PLUSDI/MODE_MINUSDI)がそれぞれ何を表すのか、
パラメーターとshift引数の意味、そして「ADX主線だけではトレンドの方向は分からない」
という実務上の落とし穴を、実際にMetaEditorでコンパイルできるサンプルコードとあわせて解説します。
なお、ADXの生数値を「レンジ/様子見/強いトレンド」のような日本語ラベルに変換して表示する応用インジケーターは別記事([ADXの数値をそのまま見ていませんか?](https://creator.fx-ea-system-project.com/mt4-indicator/adx-strength-indicator/))で扱っています。
この記事は状態変換の一歩手前、`iADX()`という関数そのものの使い方に絞って解説します。
ADXは「強さ」しか表さない指標
ADX(Average Directional Movement Index、
平均方向性指数)は、J.ウェルズ・ワイルダーが考案したトレンド系指標で、
「トレンドがどれだけ強く出ているか」を0〜100の数値で表します。
ここで見落とされがちなのが、ADXの主線(ADX Main Line)は上昇トレンドと下降トレンドを区別しないという点です。
ADX主線が同じ40という数値でも、それが強い上昇トレンドなのか強い下降トレンドなのかは、
主線の値だけでは判断できません。
方向を判定するには、ADXと同時に計算される+DI(Plus Directional Indicator、
上昇方向の勢い)と-DI(Minus Directional Indicator、
下降方向の勢い)という別の2本の値が必要です。
MT4では、この3つの値(ADX主線・+DI・-DI)をすべて`iADX()`という1つの関数から、
mode引数を変えて取得します。
iADX関数の書式
double iADX( string symbol, //通貨ペア(NULLで現在のチャート) int timeframe, //時間足(0で現在のチャートの時間足) int period, //ADXの計算期間(標準14) int applied_price, //価格の種類(通常PRICE_CLOSE) int mode, //取得するバッファの種類 int shift //何本前の足を見るか(0=最新、1=1つ前の確定足) );
`iMA()`や`iATR()`と同じ「symbol, timeframe, …パラメーター…, shift」
という並びですが、`applied_price`(計算に使う価格の種類)と`mode`(3つのバッファのどれを取得するか)という2つの引数が挟まる点が異なります。
`applied_price`は通常`PRICE_CLOSE`を指定します(ADXの計算方法上、
他の価格種別を指定しても計算式は高値・安値・終値を内部で使うため、
実務上はPRICE_CLOSE固定で問題ありません)。
mode引数で3つのバッファを使い分ける
mode引数には、以下のいずれかの定数を指定します。
- MODE_MAIN(値は0) — ADX主線(トレンドの「強さ」。方向は表さない)
- MODE_PLUSDI(値は1) — +DI(上昇方向の勢い)
- MODE_MINUSDI(値は2) — -DI(下降方向の勢い)
3つとも同じ`period`・`applied_price`で計算されますが、
呼び出しはmode引数を変えて3回行う必要があります。
double adx = iADX(NULL, 0, 14, PRICE_CLOSE, MODE_MAIN, 1); //ADX主線 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()`が5本の線を1つの関数のmode引数で使い分ける設計だったのと同じ考え方です。
「ADXという名前の指標なのに、なぜ+DI/-DIまで同じ関数から取得するのか」
と疑問に思うかもしれませんが、これはADX自体の計算過程で+DI/-DIを内部的に使っているため、
MT4側もこの3つをセットの指標として扱っているからです。
shift引数の考え方
`shift`は`iMA()`や`iATR()`と同じく「何本前の確定足を見るか」
を指定します。
`shift=0`は形成中の足(まだ確定していない最新の値)を返すため、
値がティックのたびに変化します。
EAやインジケーターの判定に使う場合は、`shift=1`(直近に確定した1本前の足)を指定するのが安全です。
実務上の注意点: ADX単体では方向が分からない
ここが最も誤解されやすいポイントです。
「ADXが25を超えたらトレンド発生」という基準だけでエントリー判定を組むと、
上昇トレンドでも下降トレンドでも同じように「トレンド発生」と判定されてしまいます。
ADX主線(MODE_MAIN)は「強さ」の指標であり、「方向」の指標ではないためです。
方向まで判定したい場合は、+DIと-DIの大小関係を見る必要があります。
+DIが-DIを上回っていれば上昇方向の勢いが強く、逆であれば下降方向の勢いが強いと判断できます。
mql-coverage-gap.mdの備考にもある通り、この「ADXで強さを絞り込み、
他の指標で方向を確認する」という使い方は、パーフェクトオーダー系のエントリー条件(移動平均線の並び順で方向を判定するEA)と特に相性が良いという指摘があります。
ADXだけでエントリーの可否を決めるのではなく、「ADXが閾値を超えている(=トレンドが強い)ときだけ、
パーフェクトオーダー等の方向判定ロジックを有効にする」というフィルターとしての使い方が実務的です。
実際に動くコード全体
ここまでの内容をまとめた、ADX主線と+DI/-DIの3つの値をチャート左上に表示する、
実際にMetaEditorでコンパイルできるインジケーターです。
強さ(ADX)と方向(+DI/-DIの大小関係)を別々の行で表示し、
両者が独立した情報であることが分かるようにしています。
//+------------------------------------------------------------------+
//| iADXValues.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の計算期間
//このインジケーターはチャートに線を描かず、値をComment()で表示するだけなので、
//バッファ0個で問題ありません(線を描く場合は1以上が必要です)。
//+------------------------------------------------------------------+
//| 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 direction = "方向感なし";
if(plusDI > minusDI)
direction = "▲上昇方向の勢いが優勢";
else if(minusDI > plusDI)
direction = "▼下降方向の勢いが優勢";
Comment(
"[強さ] ADX(", ADXPeriod, ")= ", DoubleToString(adx, 1), "\n",
"[方向] +DI= ", DoubleToString(plusDI, 1), " / -DI= ", DoubleToString(minusDI, 1), "\n",
"判定: ", direction, "\n",
"(ADX主線はあくまで「強さ」であり、方向の判定には+DI/-DIの比較が必要です)"
);
return(rates_total);
}
//+------------------------------------------------------------------+
MetaEditorで実際に動かす手順
- MT4の「ツール」→「MetaQuotes Language Editor」でMetaEditorを開く
- 「ファイル」→「新規作成」→「インジケーター」を選び、名前を「iADXValues」にして作成する(中身は空のテンプレートで構いません)
- テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
- F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- MT4の「ナビゲーター」パネルからインジケーターを探し、チャートへドラッグ&ドロップする
- チャート左上に「[強さ] ADX(14)= 27.3」「[方向] +DI= 24.1 / -DI= 15.8」のような表示が出れば成功です
コピペしてコンパイルが通らないときに確認すること
- 拡張子が「.mq4」になっているか
- mode引数の定数名(MODE_MAIN・MODE_PLUSDI・MODE_MINUSDI)のスペルミスがないか(1文字でも違うと未定義識別子としてコンパイルエラーになります)
- ADXの値が常に0で表示される場合、チャートを開いた直後で`ADXPeriod`分の過去データがまだ読み込まれていない可能性があります。しばらく待つか、通貨ペアの履歴データをダウンロードし直してください
まとめ
`iADX()`は1つの関数をmode引数(MODE_MAIN/MODE_PLUSDI/MODE_MINUSDI)で使い分けることで、
ADX主線と+DI/-DIの3つの値を取得できます。
最も注意すべき点は、ADX主線が表すのは「トレンドの強さ」だけであり、
「方向」は+DI/-DIの大小関係を別途比較しないと分からないということです。
今回のコードで取得した3つの値は、そのままADXが一定値以上のときだけ他のロジック(パーフェクトオーダー等)を有効にするフィルター条件として、
EA側に組み込めます。
ADXの値を状態ラベルに変換して表示するインジケーターの作り方は、
関連記事のADX応用編で扱っています。
コメント