MT4 EAの作り方|ADXで順張りEAを作る方法

MT4 ADX EAの作り方|DIクロスで順張り判定するMQL4サンプル
EAサンプル・ノウハウ
記事内に商品プロモーションを含む場合があります
スポンサーリンク

MT4(MQL4)でADXを使ったEAを作る場合は、iADX()を使ってADX本体・+DI・-DIの値を取得できます。
この記事では、ADXでトレンドの強さを確認しながら、+DIと-DIのクロスでエントリーするシンプルな順張りEAを作成します。

実際にコンパイル・バックテストまで行ったMQL4ソースコードを掲載し、iADX()の使い方やパラメータ設定、バックテスト結果もあわせて確認します。

📘 この記事で解説する内容
  • ADX・+DI・-DIを使ったEAの売買ルール
  • MQL4のiADX()の使い方
  • ADX EAの無料サンプルコード
  • ADX期間・しきい値などのパラメータ設定
  • デフォルト設定と最適化後のバックテスト結果

ADX EAの仕様

項目内容
使用インジケーターADX(Average Directional Index)
取得関数iADX()
買い条件ADXがしきい値以上 + +DIが-DIを上抜け
売り条件ADXがしきい値以上 + -DIが+DIを上抜け
判定タイミング新しい足が確定したタイミング
決済TP / SL
初期ADX期間14
初期ADXしきい値25
MagicNumber使用しない学習用サンプル

ADXとは?EAで使うポイント

ADXは、相場のトレンドの強さを見るために使われるテクニカル指標です。

ADX自体は上昇・下降の方向を直接示すものではないため、このEAでは方向判定に+DIと-DIを組み合わせます。

  • ADX:トレンドの強さを見る
  • +DI:上方向の動きを見る
  • -DI:下方向の動きを見る

なお、「ADXが25以上なら必ず強いトレンド」といった絶対的な基準ではありません。本記事ではEAの初期設定として25を使用しています。

MT4のADXそのものの表示方法・デフォルト設定・+DI / -DIの見方については、以下の記事で詳しく解説しています。

ADX EAのエントリーロジック

今回のEAでは、確定した2本のローソク足から+DIと-DIのクロスを判定し、最新確定足のADXがしきい値以上の場合だけエントリーします。

買いエントリー

  • 最新確定足のADXが設定したしきい値以上
  • 2本前では +DI < -DI
  • 1本前では +DI > -DI

つまり、ADXで一定以上のトレンド強度を確認しながら、+DIが-DIを上抜けしたタイミングでBUYします。

売りエントリー

  • 最新確定足のADXが設定したしきい値以上
  • 2本前では -DI < +DI
  • 1本前では -DI > +DI

こちらは逆に、-DIが+DIを上抜けしたタイミングでSELLします。

⚠️ ADXのしきい値について

本サンプルでは初期値を25にしていますが、25以上なら必ずトレンド相場になるという意味ではありません。
ADXの値は通貨ペア・時間足・期間によって変化するため、EAで利用する場合はバックテストしながら調整してください。

ベーステンプレートからの変更点

今回のADX EAは、当サイトで公開しているMT4 EAベーステンプレートを元に作成しています。

  • ADX_KIKANでADX期間を設定
  • ADX_ENTRY_SIKIIでエントリーに使うADXしきい値を設定
  • iADX()でADX・+DI・-DIを取得
  • 確定足の+DI / -DIクロスを新規注文条件に追加
  • 決済はベーステンプレートと同じTP / SLを使用

ADX EAをダウンロード

今回使用したADX EAはこちらからダウンロードできます。

📥 ADXのEAをダウンロード

▶ ADX EAのパラメータ設定を確認する

💡 コードを書かずにEAを作ってみたい方へ
当サイトのMT4 EAビルダーでは、ADX / DIを使った売買条件も設定できます。
サンプルEAとはロジックや生成コードが異なる場合がありますが、EA作成の仕組みを試す用途にも利用できます。

▶ 無料MT4 EAビルダーを使ってみる

ADX EAのMQL4サンプルコード

今回バックテストしたADX EAの全ソースコードです。

コードの見方
強調部分が、ベーステンプレートへ追加したADXパラメータと売買判定です。
ADX・+DI・-DIは、形成中の足ではなく1本前と2本前の確定足から取得しています。
//+------------------------------------------------------------------+
//|                                                       29_ADX.mq4 |
//|                                Copyright © 2020-2026 ぷろぐらむFX |
//|                                             https://fx-prog.com/ |
//+------------------------------------------------------------------+

#property copyright "Copyright © 2020-2026 ぷろぐらむFX"
#property link      "https://fx-prog.com/"
#property version   "1.00"
#property strict

input double Lots = 0.01;
input int TP = 100;
input int SL = 100;

//***【パラメータ設定↓】***//
input int ADX_KIKAN = 14;              //ADX期間
input int ADX_ENTRY_SIKII = 25;        //ADXしきい値
//***【パラメータ設定↑】***//

string Ea_Name = WindowExpertName();
double PipValue;
datetime prevtime;

int OnInit(){
   if(Digits == 3 || Digits == 5){
      PipValue = Point * 10;
   }else{
      PipValue = Point;
   }
   return(INIT_SUCCEEDED);
}

void OnTick(){
   if(Time[0] != prevtime){
      prevtime = Time[0];
   }else{
      return;
   }

   int total = OrdersTotal();
   int ea_order_Type = -1;
   double ea_order_stop_price = 0;
   double ea_order_good_price = 0;

   if(total == 0){
      bool openBuy = false;
      bool openSell = false;

      //***【新規注文判断↓】***//
      double ADX_1 = iADX(NULL,0,ADX_KIKAN,PRICE_CLOSE,MODE_MAIN,1);
      double PlusDI_1 = iADX(NULL,0,ADX_KIKAN,PRICE_CLOSE,MODE_PLUSDI,1);
      double MinusDI_1 = iADX(NULL,0,ADX_KIKAN,PRICE_CLOSE,MODE_MINUSDI,1);

      double PlusDI_2 = iADX(NULL,0,ADX_KIKAN,PRICE_CLOSE,MODE_PLUSDI,2);
      double MinusDI_2 = iADX(NULL,0,ADX_KIKAN,PRICE_CLOSE,MODE_MINUSDI,2);

      if(ADX_1 >= ADX_ENTRY_SIKII && PlusDI_2 < MinusDI_2 && PlusDI_1 > MinusDI_1){
         openBuy = true;
      }else if(ADX_1 >= ADX_ENTRY_SIKII && MinusDI_2 < PlusDI_2 && MinusDI_1 > PlusDI_1){
         openSell = true;
      }
      //***【新規注文判断↑】***//

      if(openBuy){
         ea_order_Type = OP_BUY;
      }else if(openSell){
         ea_order_Type = OP_SELL;
      }

      //***【TP/SL判断↓】***//
      if(openBuy){
         ea_order_stop_price = Ask - SL * PipValue;
         ea_order_good_price = Ask + TP * PipValue;
      }else if(openSell){
         ea_order_stop_price = Bid + SL * PipValue;
         ea_order_good_price = Bid - TP * PipValue;
      }
      //***【TP/SL判断↑】***//

      if(ea_order_Type > -1){
         funcOrder_Send(ea_order_Type,ea_order_stop_price,ea_order_good_price,Lots,Ea_Name,0,0);
      }
   }
}


//★★★★★★★★★★★★★★★★★★★★ ここから下は共通関数 ★★★★★★★★★★★★★★★★★★★★

//+------------------------------------------------------------------+
//|【関数】新規注文関数                                              |
//|【引数】orderType:売買(0=BUY, 1=SELL)                            |
//|【引数】sl:損切り価格  tp:利確価格                               |
//|【引数】lots:取引ロット数                                         |
//|【引数】orderComment:オーダーコメント                             |
//|【引数】magic:MagicNumber                                         |
//|【引数】maxSpreadPoints:許容スプレッド[Point] (0=制限なし)       |
//|【戻値】true=成功 false=失敗                                      |
//+------------------------------------------------------------------+
bool funcOrder_Send(int orderType, double sl, double tp, double lots, string orderComment, int magic, int maxSpreadPoints){

   int ticket = -1;
   double price = 0;
   double spread = 0;
   color clr = clrNONE;

   for(int retry=0; retry<10; retry++){

      RefreshRates();
      spread = MarketInfo(Symbol(),MODE_SPREAD);

      if(maxSpreadPoints > 0 && spread > maxSpreadPoints){
         Print("スプレッド拡大中(",spread,"ポイント) → 待機中 (リトライ=",retry+1,")");
         Sleep(2000);
         continue;
      }

      if(orderType == OP_BUY){
         price = Ask;
         clr = clrBlue;
      }else if(orderType == OP_SELL){
         price = Bid;
         clr = clrRed;
      }else{
         Print("funcOrder_Send: 未対応の注文種別=",orderType);
         return false;
      }

      price = NormalizeDouble(price,Digits);

      if(sl > 0) sl = NormalizeDouble(sl,Digits);
      if(tp > 0) tp = NormalizeDouble(tp,Digits);

      ResetLastError();

      ticket = OrderSend(Symbol(),orderType,lots,price,20,sl,tp,orderComment,magic,0,clr);

      if(ticket > 0){
         Print("新規注文成功! チケットNo=",ticket," レート=",price," Lots=",lots," スプレッド=",spread,"ポイント");
         return true;
      }

      int err = GetLastError();
      Print("新規注文失敗 エラーNo=",err," リトライ回数=",retry+1);
      Sleep(2000);
   }

   return false;
}
スポンサーリンク

MQL4のiADX()でADX・+DI・-DIを取得する

MQL4では、MT4標準のADXを取得するためにiADX()を使用します。

今回のEAでは、ADX本体だけでなく、+DIと-DIも同じiADX()から取得しています。

double ADX_1 = iADX(NULL,0,ADX_KIKAN,PRICE_CLOSE,MODE_MAIN,1);
double PlusDI_1 = iADX(NULL,0,ADX_KIKAN,PRICE_CLOSE,MODE_PLUSDI,1);
double MinusDI_1 = iADX(NULL,0,ADX_KIKAN,PRICE_CLOSE,MODE_MINUSDI,1);

iADX()の引数

引数今回の指定意味
symbolNULL現在のチャートの通貨ペア
timeframe0現在のチャートの時間足
periodADX_KIKANADXの計算期間
applied_pricePRICE_CLOSE計算に使用する価格
modeMODE_MAINなどADX・+DI・-DIのどの値を取得するか
shift1 / 2何本前のバーを取得するか

MODE_MAIN・MODE_PLUSDI・MODE_MINUSDIの違い

  • MODE_MAIN:ADX本体
  • MODE_PLUSDI:+DI
  • MODE_MINUSDI:-DI

今回のEAでは、MODE_MAINでトレンドの強さを確認し、MODE_PLUSDIとMODE_MINUSDIの位置関係から売買方向を判定します。

また、shiftには1と2を指定し、形成途中の0番足ではなく確定したローソク足だけを使ってクロスを判定しています。

ADX EAのトレードイメージ

MT4 ADX EAのトレードイメージ|ADXとDIクロスで売買判定

チャート上では、ADXが設定したしきい値を満たしている場面で、+DIと-DIのクロスを確認してエントリーします。

  • ADXがしきい値以上
  • +DIが-DIを上抜け → BUY
  • -DIが+DIを上抜け → SELL
  • エントリー後はTP / SLで決済

新規注文は共通関数を使用

売買条件を満たした後の注文処理には、当サイトのベーステンプレートと同じfuncOrder_Send()を使用しています。

注文関数そのものの仕組みや、変更・決済注文を含む共通関数については以下の記事で解説しています。

ADX EAのパラメータ設定

公開しているサンプルEAの初期値は以下の設定です。

パラメータ初期値内容
Lots0.01取引ロット数
TP100利確幅(pips)
SL100損切り幅(pips)
ADX_KIKAN14ADXの計算期間
ADX_ENTRY_SIKII25エントリーを許可するADXしきい値

公開コードでは、ADXでよく使われる期間14と、EAの基準値として25を初期設定にしています。ただし、通貨ペアや時間足によって適した設定は変わります。

スポンサーリンク

ADX EAのバックテスト結果

今回のソースコードを、FXTFのUSDJPYヒストリカルデータでバックテストしました。

デフォルト設定のバックテスト

まずは公開しているソースコードの初期値をそのまま使用しています。

項目内容
通貨ペアUSDJPY-cd
時間足M15
期間2024/08/23~2026/07/30
モデル始値のみ
スプレッド5
初期証拠金1,000,000円
Lots0.01
TP / SL100 / 100
ADX期間14
ADXしきい値25
純益PF勝率最大DD取引数
+40,540.37円1.3056.87%9,953.99円
(0.99%)
313回
MT4 ADX EAのバックテスト結果|USDJPY M15

デフォルト設定でも、今回のM15・約2年間の検証ではPF1.30、純益+40,540円となりました。

時間足による違いにも注意

同じ初期パラメータをH1で確認したところ、今回の検証期間ではPF0.90・純益-10,143円・198取引でした。
同じADXロジックでも時間足によって結果は大きく変わるため、実際に使用する時間足でのバックテストが重要です。

パラメータを最適化した場合

同じM15・同じ検証期間でTP / SL・ADX期間・しきい値を調整したところ、以下の設定が良好な結果となりました。

パラメータデフォルト最適化後
TP100140
SL10070
ADX期間1412
ADXしきい値2523
純益PF勝率最大DD取引数
+61,629.84円1.4943.09%8,870.38円
(0.84%)
311回
MT4 ADX EAの最適化後バックテスト結果|USDJPY M15

最適化後は勝率自体は43.09%まで下がっていますが、TP140 / SL70と利益幅を大きくしたことで、今回の期間ではPF1.49・純益+61,629円まで改善しました。

⚠️ 最適化結果の見方

この最適化設定は、上記バックテスト期間のデータを使って調整した結果です。
別期間・別通貨・将来の相場でも同じ成績になることを意味するものではありません。最適化値を利用する場合も、別期間で再検証してください。

ADX EAの弱点・注意点

  • ADXだけでは方向は分からない
    ADXはトレンド強度を見る指標のため、今回のEAでは+DI / -DIで方向を判断しています。
  • DIクロスは往復しやすい場面がある
    方向感の弱い相場では+DIと-DIが短期間で交差し、エントリーが増える場合があります。
  • 時間足によって結果が変わる
    今回の検証ではM15がプラスだった一方、同じ初期値のH1ではマイナスとなりました。
  • しきい値25は絶対的な基準ではない
    ADX期間やしきい値は、通貨ペア・時間足・相場環境に応じて調整が必要です。
  • 最適化のしすぎに注意
    特定期間へ合わせすぎると、別期間で成績が崩れる可能性があります。
  • MagicNumber管理は行っていない
    学習用サンプルのため、他のEAと同時運用する場合は注文管理の追加が必要です。

ADX EAのよくある質問

MQL4でADXの値を取得するにはどうすればいいですか?

MQL4ではiADX()を使用します。MODE_MAINでADX本体、MODE_PLUSDIで+DI、MODE_MINUSDIで-DIを取得できます。

ADXが25以上なら必ずエントリーした方がいいですか?

いいえ。25は今回のサンプルEAで使用している初期しきい値です。ADXの値は時間足や通貨ペアによって変わるため、バックテストしながら調整してください。

なぜiADX()のshiftに0ではなく1と2を使うのですか?

形成途中の0番足ではなく、確定済みの1本前と2本前の値からDIクロスを判定するためです。これにより、足が確定する前の値の変化を売買条件に使わない構成にしています。

ADX EAはどの時間足で使うのが良いですか?

今回のUSDJPY検証ではM15でプラスとなりましたが、同じ設定でもH1ではマイナスでした。特定の時間足が常に有利とは限らないため、利用する通貨ペアと時間足で個別にバックテストしてください。

最適化後のTP140・SL70・ADX12・しきい値23をそのまま使えばいいですか?

今回の検証期間では良好でしたが、同じ期間のデータを使って最適化した結果です。別期間や別通貨でも有効とは限らないため、そのまま実運用するのではなく追加検証してください。

まとめ|iADX()を使えばADX・DIをEAへ組み込める

今回は、MQL4のiADX()を使ってADX・+DI・-DIを取得し、DIクロスで売買するMT4 EAを作成しました。

  • ADXでトレンドの強さを確認
  • +DI / -DIのクロスで売買方向を判断
  • 確定足だけを使ってエントリー判定
  • デフォルト設定のM15検証ではPF1.30
  • 最適化後は今回の期間でPF1.49

ADXは単独で売買方向を決める指標ではありませんが、+DI / -DIと組み合わせることで、EAのエントリー条件としてシンプルに実装できます。

ほかのインジケーターを使ったEAサンプルも公開しています。ロジック比較やMQL4学習には、EAサンプル一覧も参考にしてください。

コメント

タイトルとURLをコピーしました