ADXの数値を「レンジ」

「様子見」

「強いトレンド」の3段階で表示するインジケーターを作ってチャートに表示してみたものの、

結局その表示を見ながら手動でエントリーするなら、判定ロジックをそのままEAに組み込んでしまった方が早いのではないか——そう思った人向けの記事です。

この記事では、ADXが一定の閾値以上(強いトレンド)のときだけ、

+DI/-DIの大小関係で上昇・下降どちらの方向かを判定して自動で順張りエントリーするEAの作り方を、

設計の考え方と実際に動くコードで解説します。

設計の考え方: ADXは「強さ」しか教えてくれない

ADXの主線(MODE_MAIN)は「トレンドがどれだけ強いか」

という強さの指標であり、上昇トレンドなのか下降トレンドなのかという方向の情報は含んでいません。

そのため、ADXの値だけを見てエントリー方向を決めることはできず、

方向の判定には別の値である+DI(MODE_PLUSDI)・-DI(MODE_MINUSDI)を組み合わせる必要があります。

このEAのエントリー条件は、次の2つをどちらも満たした場合だけです。

①ADX(強さ)が閾値(ADXThreshold)以上 → レンジ相場ではなく、明確なトレンドが出ていると判断する
②+DIと-DIの大小関係(方向) → +DIが-DIより大きければ上昇方向、-DIが+DIより大きければ下降方向と判断する

「①強さで絞り込んでから、②方向で判定する」という2段階にすることで、

レンジ相場でのダマシエントリーを減らしつつ、強いトレンドが出た方向へ素直に乗る、

という順張り戦略になります。

iADX関数でADXと+DI/-DIを同時に取得する

iADX関数の記事で解説した通り、ADXの主線と+DI/-DIは、

すべて同じ`iADX()`関数からmode引数を変えて取得します。

double iADX(
   string symbol,        //通貨ペア(NULLで現在のチャート)
   int    timeframe,     //時間足(0で現在のチャートの時間足)
   int    period,        //ADXの計算期間(標準14)
   int    applied_price, //価格の種類(通常PRICE_CLOSE)
   int    mode,          //MODE_MAIN=0(強さ)/MODE_PLUSDI=1(+DI)/MODE_MINUSDI=2(-DI)
   int    shift          //何本前の足を見るか(0=最新、1=1つ前の確定足)
   );

EAでは、形成中の足(shift=0)を見ると値が確定前に変動してしまいエントリー判定がブレるため、

1つ前の確定足(shift=1)を使います。

実際に動くコード全体

ポジション重複防止(自分のマジックナンバーのポジションを持っている間は新規エントリーしない)と損切り設定を含めた、

実際にMetaEditorでコンパイルできるEAです。

//+------------------------------------------------------------------+
//|                                        ADXTrendFollowingEA.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

input int    ADXPeriod    = 14;//ADXの計算期間
input double ADXThreshold = 25.0;//これ以上を「強いトレンド」とみなす閾値
input double Lots         = 0.1;//ロット数
input int    StopLoss     = 200;//損切り(pips)
input int    TakeProfit   = 200;//利確(pips)
input int    Slippage     = 3;//スリッページ
input int    MagicNumber  = 20260911;//マジックナンバー

//+------------------------------------------------------------------+
//| このEA(マジックナンバー)のポジションを保有しているか判定する        |
//+------------------------------------------------------------------+
bool HasPosition()
  {
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         continue;
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
         return(true);
     }
   return(false);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                              |
//+------------------------------------------------------------------+
void OnTick()
  {
   //既にポジションを持っている場合は新規エントリーしない
   if(HasPosition())
      return;

   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);

   //①ADXが閾値未満(レンジ相場)なら何もしない
   if(adx < ADXThreshold)
      return;

   int ticket = -1;

   //②+DIが-DIより大きければ上昇方向へ順張り
   if(plusDI > minusDI)
     {
      ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage,
                          Ask - StopLoss * Point,
                          Ask + TakeProfit * Point,
                          "ADX Trend Long", MagicNumber, 0, Red);
      if(ticket < 0)
         Print("買い注文に失敗しました。エラーコード=", GetLastError());
     }
   //②-DIが+DIより大きければ下降方向へ順張り
   else if(minusDI > plusDI)
     {
      ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage,
                          Bid + StopLoss * Point,
                          Bid - TakeProfit * Point,
                          "ADX Trend Short", MagicNumber, 0, Blue);
      if(ticket < 0)
         Print("売り注文に失敗しました。エラーコード=", GetLastError());
     }
  }
//+------------------------------------------------------------------+
Copy

MetaEditorで実際に動かす手順

  1. MT4の「ツール」→「MetaQuotes Language Editor」でMetaEditorを開く
  2. 「ファイル」→「新規作成」からウィザードで「Expert Advisor(テンプレートを使用)」を選び、名前を「ADXTrendFollowingEA」にして作成する(あとの画面は「次へ」を数回押して「完了」まで進めれば構いません)
  3. テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
  4. F7キー(またはコンパイルボタン)でコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
  5. 「表示」→「ストラテジーテスター」でExpert Advisorに「ADXTrendFollowingEA」を選び、通貨ペアと期間を指定してバックテストで動作を確認する
  6. デモ口座でのフォワードテストを経てから、本番運用を検討してください

コピペしてコンパイルが通らない・想定通りエントリーしないときに確認すること

  • 拡張子が「.mq4」になっているか
  • ADXThreshold(既定25.0)を極端に低い値にしていないか(低すぎるとレンジ相場でも頻繁にエントリーしてしまいます)
  • OrderSend失敗時にエラーコード130(Invalid stops)が出た場合、StopLoss・TakeProfitの値をブローカーの最小ストップ距離より大きくしてください
  • バックテストで一度もエントリーしない場合、対象期間・通貨ペアでADXThresholdを一時的に下げて動作自体を確認してから、実際の閾値に戻すとデバッグしやすくなります

実運用する前に確認しておきたいこと

このEAは「ADXの強さ×+DI/-DIの方向」という2つの条件だけで売買する、

学習用にシンプルへ作った例です。

実際の口座で稼働させる前に、次の点を確認してください。

  • ADXが閾値を超えた直後はトレンド転換の初動と紛らわしいダマシが起きやすく、連続して損切りになるケースがある
  • ロット数(Lots)は口座残高に対して過大にならないよう調整する
  • バックテストの結果は過去データに基づくものであり、将来の相場でも同じ成績になるとは限らない

まずはデモ口座、または少額のロットでのフォワードテストを行ってから、

本番運用を検討してください。

まとめ

ADXの主線は「強さ」しか表さないため、EAのエントリー条件に使うには+DI/-DIによる方向判定と組み合わせる必要があります。

この記事では「ADXが閾値以上」を強いトレンドの条件、「+DI/-DIの大小関係」

を方向の条件として2段階で判定し、既存のEA記事群と同じくポジション重複防止・損切り設定まで含めて実装しました。

閾値(ADXThreshold)を調整することで、通貨ペアや時間足に応じたエントリー頻度の調整も可能です。

関連記事