iADX関数は、ADX(平均方向性指数)の値をMQL5プログラムから取得する関数です。ADXは「いま相場にトレンドがあるか・どれくらい強いか」を 0〜100 で表すトレンド系の指標で、方向そのものは示しません。方向は同時に得られる +DI と -DI の2本で判断します。この記事では、iADXの構文と「ハンドル+CopyBufferの2段階」、そしてコピーしてすぐ動く4つのサンプル(3本の取得・トレンドの強さ判定・+DI/-DIクロス+ADXフィルター・順張りの最小EA)を丁寧に解説します。
iADX(ADX・平均方向性指数)とは
ADXは、トレンドの強さだけを 0〜100 で表します。上か下かの方向は教えてくれません。方向は、上昇の勢いを表す +DI と、下降の勢いを表す -DI の2本で読みます。一般に ADXが25以上でトレンドあり・20以下でレンジ(方向感なし)と見ます。さらに +DIが-DIより上なら上昇優勢・下なら下降優勢。MQL5では iADX() でこの3本(ADX・+DI・-DI)をまとめて取得します。
MQL5のインジケーターは「①
OnInit() でハンドルを作る → ② OnTick() で CopyBuffer() により値を取り出す」の2段階です(詳しくは iMAの記事 を参照)。ADXは線が3本=バッファが3つ(0=ADX / 1=+DI / 2=-DI)あります。
iADX() の構文と引数
int iADX(
string symbol, // 通貨ペア(_Symbol で現在のペア)
ENUM_TIMEFRAMES period, // 時間足(PERIOD_CURRENT 等)
int adx_period // 期間(一般的に 14)
);
戻り値はハンドル(整数のID)です。引数は iStochastic などより少なく、期間ひとつだけ。バッファ番号は 0=ADX(メイン・強さ)、1=+DI、2=-DI の3本です。
サンプル①:ADX・+DI・-DI の3本を取得して表示する
ADX(14) の現在値(3本)をチャート左上に表示します。
コピペOK
int adxHandle = INVALID_HANDLE;
int OnInit()
{
// ① ハンドルを1回だけ作る(期間14)
adxHandle = iADX(_Symbol, PERIOD_CURRENT, 14);
if(adxHandle == INVALID_HANDLE)
{
Print("iADXハンドルの作成に失敗: ", GetLastError());
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
void OnTick()
{
double adx[], plusDI[], minusDI[];
ArraySetAsSeries(adx, true); // [0]を最新足にそろえる
ArraySetAsSeries(plusDI, true);
ArraySetAsSeries(minusDI, true);
// ② 3本それぞれを、バッファ番号を指定して取り出す
if(CopyBuffer(adxHandle, 0, 0, 2, adx) < 2) return; // 0=ADX
if(CopyBuffer(adxHandle, 1, 0, 2, plusDI) < 2) return; // 1=+DI
if(CopyBuffer(adxHandle, 2, 0, 2, minusDI) < 2) return; // 2=-DI
Comment("ADX = ", DoubleToString(adx[0], 1),
" +DI = ", DoubleToString(plusDI[0], 1),
" -DI = ", DoubleToString(minusDI[0], 1));
}
void OnDeinit(const int reason)
{
IndicatorRelease(adxHandle); // 後始末
}
サンプル②:トレンドの強さと向きを判定する
確定した足の値で「トレンドあり/レンジ」を判定し、ある場合は+DI・-DIで向きを見ます。形成中の足ではなく確定足で、新しい足ができた時だけチェックします。
コピペOK
input double InpTrend = 25.0; // これ以上でトレンドあり
input double InpRange = 20.0; // これ以下でレンジ
datetime lastBar = 0;
void OnTick()
{
datetime t = iTime(_Symbol, PERIOD_CURRENT, 0);
if(t == lastBar) return; // 新しい足の時だけ
lastBar = t;
double adx[], plusDI[], minusDI[];
ArraySetAsSeries(adx, true);
ArraySetAsSeries(plusDI, true);
ArraySetAsSeries(minusDI, true);
if(CopyBuffer(adxHandle, 0, 0, 2, adx) < 2) return;
if(CopyBuffer(adxHandle, 1, 0, 2, plusDI) < 2) return;
if(CopyBuffer(adxHandle, 2, 0, 2, minusDI) < 2) return;
double a = adx[1]; // 直近の確定足のADX
if(a >= InpTrend)
{
bool up = (plusDI[1] > minusDI[1]); // +DIが上なら上昇優勢
Print("トレンドあり(ADX=", DoubleToString(a, 1), "):",
up ? "上昇優勢" : "下降優勢");
}
else if(a <= InpRange)
{
Print("レンジ(ADX=", DoubleToString(a, 1), ")");
}
}
サンプル③:+DIと-DIのクロス+ADXフィルターでシグナル
方向は+DIと-DIのクロスで取り、ADXが一定以上(トレンドが強い)ときだけ有効にします。これで「方向感のないレンジでのダマシ」を減らせます。確定足の [1] と [2] を比較します。
コピペOK
double adx[], plusDI[], minusDI[];
ArraySetAsSeries(adx, true);
ArraySetAsSeries(plusDI, true);
ArraySetAsSeries(minusDI, true);
if(CopyBuffer(adxHandle, 0, 0, 3, adx) < 3) return; // ADX [1],[2]
if(CopyBuffer(adxHandle, 1, 0, 3, plusDI) < 3) return; // +DI [1],[2]
if(CopyBuffer(adxHandle, 2, 0, 3, minusDI) < 3) return; // -DI [1],[2]
bool strong = (adx[1] >= 25.0); // トレンドが強い
// +DIが-DIを下から上抜け+トレンド強=買いシグナル
bool buySignal = (plusDI[2] <= minusDI[2] && plusDI[1] > minusDI[1] && strong);
// -DIが+DIを下から上抜け+トレンド強=売りシグナル
bool sellSignal = (minusDI[2] <= plusDI[2] && minusDI[1] > plusDI[1] && strong);
if(buySignal) Print("買いシグナル(+DI×-DI上抜け・ADX強)");
if(sellSignal) Print("売りシグナル(-DI×+DI上抜け・ADX強)");
サンプル④:ADX順張りで売買する最小EA
サンプル③の買いシグナルでエントリーし、-DIが+DIを上抜けたら(向きが反転)決済する、動く最小EAです。CTrade を使います。
コピペOK(デモ口座で動作確認用)
#include <Trade\Trade.mqh>
CTrade trade;
int adxHandle;
datetime lastBar = 0;
input double InpLot = 0.10;
int OnInit()
{
adxHandle = iADX(_Symbol, PERIOD_CURRENT, 14);
if(adxHandle == INVALID_HANDLE) return(INIT_FAILED);
trade.SetExpertMagicNumber(20260627);
return(INIT_SUCCEEDED);
}
void OnTick()
{
datetime t = iTime(_Symbol, PERIOD_CURRENT, 0);
if(t == lastBar) return;
lastBar = t;
double adx[], plusDI[], minusDI[];
ArraySetAsSeries(adx, true);
ArraySetAsSeries(plusDI, true);
ArraySetAsSeries(minusDI, true);
if(CopyBuffer(adxHandle, 0, 0, 3, adx) < 3) return;
if(CopyBuffer(adxHandle, 1, 0, 3, plusDI) < 3) return;
if(CopyBuffer(adxHandle, 2, 0, 3, minusDI) < 3) return;
bool buySignal = (plusDI[2] <= minusDI[2] && plusDI[1] > minusDI[1] && adx[1] >= 25.0);
bool exitLong = (minusDI[1] > plusDI[1]); // 向きが下に反転したら決済
if(buySignal && PositionsTotal() == 0)
trade.Buy(InpLot, _Symbol);
if(exitLong)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket) &&
PositionGetString(POSITION_SYMBOL) == _Symbol)
trade.PositionClose(ticket);
}
}
}
void OnDeinit(const int reason)
{
IndicatorRelease(adxHandle);
}
損切り(SL)・利確(TP)・スプレッド確認・資金管理は入っていません。実運用にはこれらの安全装置が必須です。まずはデモ口座で動きを確認してください。
iADXを使うときの注意・落とし穴
ADXが高くても、それが上昇なのか下降なのかは分かりません。強さはADX・方向は+DI/-DIと役割を分けて読みます。「ADXが上がった=買い」は誤りです。
ADXはトレンドが進んでから上がってくる遅行系です。レンジからトレンドへ変わる初動は取りにくく、ADXが上がりきった頃には終盤、ということもあります。エントリーの号砲ではなく順張りの「やってよい/ダメ」フィルターとして使うのが無難です。
ハンドルは
OnInit() で1回だけ/CopyBuffer() の戻り値を必ずチェック/ArraySetAsSeries(配列, true) を忘れない。iADX特有として、0=ADX・1=+DI・2=-DI を取り違えないこと。
まとめ
iADX()はADXのハンドルを返す。値はCopyBuffer()で取り出す- バッファは 0=ADX(強さ) / 1=+DI / 2=-DI(方向) の3つ
- 一般に ADX25以上でトレンド・20以下でレンジ。確定足で・新バー時のみ判定する
- 方向は +DIと-DIのクロスで取り、ADXが強いときだけ有効にするとダマシが減る(サンプル③)
- ADXは遅行する。号砲ではなく順張りのフィルターとして使うのが無難
