最終更新: 2026年6月
ADX(Average Directional Movement Index)が25以上という条件は、トレンドフォロー型EAの最も基本的なフィルターのひとつだ。しかしADX25だけでは不十分なケースが多い。本稿では「ADX25以上」を起点に、どのような複合条件を組み合わせると実用的なトレンドフォローEAになるかを、MQL5コードと共に解説する。
相場環境の約70%はレンジ相場とも言われる。トレンドフォロー型EAが機能するのはその残り30%のトレンド局面だ。ADXフィルターはこの「30%のトレンド局面を正確に見抜くための道具」として機能する。
Claudeと会話しながらインジケータが作れるhedgrow-fxはこちら
ADX25の数理的根拠——なぜ25が分岐点か
ADX=25という閾値はワイルダーが設定した「トレンドの存在を示す最低基準」だが、統計的な分析から見るとこの数値に明確な根拠がある。
ADXは+DIと−DIの差分から計算されるため、+DIと−DIが完全に同値(方向性ゼロ)のときにADXは0に、一方が他方を大きく上回るほどADXは100に近づく。
実際のFX相場では:
- ADX < 20: 明確な方向性なし(多くのトレンドフォロー戦略で勝率が低下する)
- ADX 20〜25: 弱いトレンドの萌芽(ノイズと区別しにくい)
- ADX ≥ 25: 統計的に「ランダムウォーク」から外れたトレンドが存在する可能性が高い
- ADX ≥ 40: 強いトレンド(ただし過熱の可能性も)
多くの検証レポートで「ADX25以上を条件に追加すると、トレンドフォロー型EAのプロフィットファクターが向上する傾向がある」と報告されているのはこの統計的性質による。
MQL5でのADX25フィルター実装——完全な実装例
//=== 入力パラメーター ===
input int ADXPeriod = 14; // ADX計算期間
input double ADXMinLevel = 25.0; // トレンド判定の最低閾値
input double ADXMaxLevel = 60.0; // 過熱相場の除外閾値
input bool UseADXRising = true; // ADXが上昇中のみ許可するか
input int MAFastPeriod = 20; // 方向確認用MA(短期)
input int MASlowPeriod = 50; // 方向確認用MA(長期)
//=== ハンドル ===
int ADXHandle;
int MAFastHandle, MASlowHandle;
//=== バッファ ===
double ADXMain[], ADXPlusDI[], ADXMinusDI[];
double MAFast[], MASlow[];
int OnInit()
{
ADXHandle = iADX(_Symbol, _Period, ADXPeriod);
MAFastHandle = iMA(_Symbol, _Period, MAFastPeriod, 0, MODE_EMA, PRICE_CLOSE);
MASlowHandle = iMA(_Symbol, _Period, MASlowPeriod, 0, MODE_EMA, PRICE_CLOSE);
if(ADXHandle == INVALID_HANDLE ||
MAFastHandle == INVALID_HANDLE ||
MASlowHandle == INVALID_HANDLE)
return INIT_FAILED;
ArraySetAsSeries(ADXMain, true);
ArraySetAsSeries(ADXPlusDI, true);
ArraySetAsSeries(ADXMinusDI, true);
ArraySetAsSeries(MAFast, true);
ArraySetAsSeries(MASlow, true);
return INIT_SUCCEEDED;
}
//=== ADX値の更新 ===
bool UpdateADX()
{
if(CopyBuffer(ADXHandle, 0, 0, 5, ADXMain) < 5) return false;
if(CopyBuffer(ADXHandle, 1, 0, 5, ADXPlusDI) < 5) return false;
if(CopyBuffer(ADXHandle, 2, 0, 5, ADXMinusDI) < 5) return false;
return true;
}
//=== トレンド条件の判定(ADX25以上) ===
bool IsTrendConditionMet()
{
if(!UpdateADX()) return false;
double adx = ADXMain[0];
// 閾値チェック: 25以上60未満
if(adx < ADXMinLevel || adx > ADXMaxLevel) return false;
// オプション: ADXが上昇中(トレンド強化中)かどうか
if(UseADXRising && (ADXMain[0] <= ADXMain[1])) return false;
return true;
}
//=== 方向性フィルター(MAとDIの方向が一致する場合) ===
bool IsBuyDirection()
{
if(CopyBuffer(MAFastHandle, 0, 0, 3, MAFast) < 3) return false;
if(CopyBuffer(MASlowHandle, 0, 0, 3, MASlow) < 3) return false;
bool diBuyDirection = (ADXPlusDI[0] > ADXMinusDI[0]);
bool maBuyDirection = (MAFast[0] > MASlow[0]);
// +DIが-DIより上で、かつ短期MAが長期MAより上
return (diBuyDirection && maBuyDirection);
}
bool IsSellDirection()
{
if(CopyBuffer(MAFastHandle, 0, 0, 3, MAFast) < 3) return false;
if(CopyBuffer(MASlowHandle, 0, 0, 3, MASlow) < 3) return false;
bool diSellDirection = (ADXMinusDI[0] > ADXPlusDI[0]);
bool maSellDirection = (MAFast[0] < MASlow[0]);
return (diSellDirection && maSellDirection);
}
void OnDeinit(const int reason)
{
IndicatorRelease(ADXHandle);
IndicatorRelease(MAFastHandle);
IndicatorRelease(MASlowHandle);
}
3層フィルター設計——ADX25を核にした複合条件
単純なADX25フィルターを起点に、3層のフィルターを積み上げる設計が実用的だ。
Layer 1: トレンドの「存在」確認(ADX25以上)
bool layer1 = IsTrendConditionMet();
// ADX >= 25.0 AND ADX <= 60.0
Layer 2: トレンドの「方向」確認(DI + MA)
bool layer2Buy = IsBuyDirection(); // +DI > -DI AND MAFast > MASlow
bool layer2Sell = IsSellDirection(); // -DI > +DI AND MAFast < MASlow
Layer 3: エントリータイミング(具体的なトリガー)
// 例: RSIが売られ過ぎから反転(50ライン越え)
int rsiSignal = CheckRSI50Cross();
// 例: ローソク足パターンの確認
bool candlePatternConfirm = CheckBullishCandle();
// 全条件が揃った場合のみエントリー
if(layer1 && layer2Buy && rsiSignal > 0)
{
// 買いエントリー処理
}
この3層設計の論理:
- Layer 1: 「今はトレンド相場か?」
- Layer 2: 「トレンドは上昇・下降どちら?」
- Layer 3: 「今このタイミングでエントリーする根拠は?」
各レイヤーが独立した情報を提供しているため、フィルターの重複(同じ情報を二重に確認する冗長設計)を避けられる。
ADX上限の設定——過熱相場の除外
ADX=25以上を条件にするだけでなく、ADX=60以上を除外する上限設定も検討すべきだ。
input double ADXMaxLevel = 60.0; // 過熱相場の除外閾値
bool IsTrendConditionMet()
{
// ...
if(adx > ADXMaxLevel)
{
// 過熱相場: トレンドの末期である可能性が高い
return false;
}
// ...
}
ADXが極端に高い(60〜80以上)相場では、トレンドがすでに終盤に入っており、逆張りが有効になるケースもある。トレンドフォロー型EAでは、この過熱局面を除外することで「トレンドの末期に飛び乗って損失を出す」パターンを回避できる。
バックテストで見るADX条件の効果
複数の条件組み合わせでバックテストを比較する場合の評価表の設計例:
| 条件 | 年間トレード数 | 勝率 | PF | 最大DD | |------|-------------|------|-----|-------| | フィルターなし | 300 | 48% | 1.05 | 25% | | ADX≥25のみ | 180 | 55% | 1.35 | 18% | | ADX≥25 + MA確認 | 120 | 61% | 1.60 | 14% | | ADX≥25 + MA + RSI | 80 | 65% | 1.80 | 12% |
上の表は概念的な例示であり、実際の数値は戦略と通貨ペアによって大きく異なる。重要なのは「フィルターを追加するほどトレード数が減る一方でシグナル精度が上がる」というトレードオフだ。トレード数が少なすぎると統計的信頼性が低下するため、フィルターの追加には限界がある。
マルチタイムフレームADXフィルター
上位足のADXが25以上の場合のみ、下位足でのエントリーを許可する設計:
input ENUM_TIMEFRAMES HigherTF = PERIOD_H4; // 上位時間足
int ADXHandleHigher;
double ADXMainHigher[];
// OnInit()に追加
ADXHandleHigher = iADX(_Symbol, HigherTF, ADXPeriod);
ArraySetAsSeries(ADXMainHigher, true);
bool IsHigherTFTrending()
{
if(CopyBuffer(ADXHandleHigher, 0, 0, 3, ADXMainHigher) < 3) return false;
return (ADXMainHigher[0] >= ADXMinLevel);
}
// エントリー条件に追加
if(IsHigherTFTrending() && layer1 && layer2Buy && trigger)
{
// 買いエントリー
}
H4足でADX≥25が確認された場合のみM15足でエントリーするという設計は、「大きな流れに沿った方向でのみエントリーする」というトレンドフォローの原則を実装している。
Claudeと会話しながらインジケータが作れるhedgrow-fxはこちら
よくある質問(FAQ)
Q: ADX25フィルターを追加してもバックテスト成績が改善しない場合は? A: まずエントリートリガーを見直してください。ADXフィルターは「どの相場環境でトレードするか」を制御しますが、「どのタイミングでエントリーするか」は別の要素です。フィルターが機能しない場合は、エントリートリガー自体に問題がある可能性があります。
Q: ADXが25を一瞬超えてすぐ下がる「ダマし」にどう対処しますか?
A: ADXが連続してN本(例: 3本)以上25を超えている場合のみトレンド確認とする、という条件を追加することで対応できます。ADXMain[0] >= 25 && ADXMain[1] >= 25 && ADXMain[2] >= 25のような実装になります。
Q: ADX期間14以外を使った場合、25という閾値は変わりますか? A: 一般的にはADX閾値も見直す必要があります。期間が短い場合(7〜10)はADXが20〜22程度でもトレンドを示すケースがあり、長い期間(20〜25)では閾値を28〜30に上げることを検討します。バックテストで確認してください。
Q: ADXフィルターはレンジ相場専用の逆張りEAにも使えますか? A: はい、逆の使い方で機能します。ADX < 20(または25)を条件に「レンジ相場のみでエントリー許可」とする設計です。ただし逆張り戦略自体のリスク管理(損切りの設計)に特に注意が必要です。
著者情報
本記事は金融工学・アルゴリズム取引の実務経験を持つライターが執筆しています。
免責事項: 本記事はFXの教育・情報提供を目的としており、投資勧誘を行うものではありません。FX取引には元本割れリスクがあります。バックテスト結果は将来の運用成果を保証しません。実際の取引は自己責任で行ってください。
