MT4 EAテンプレート|無料配布&カスタマイズ解説【MQL4初心者向け】

mt4-ea-template-mql4-customize
EAサンプル・ノウハウ
記事内に商品プロモーションを含む場合があります
スポンサーリンク

「MT4でEAを作りたいけれど、どこから書き始めればいいのか分からない」
そんな方に向けて、この記事ではMQL4でEAを作るためのベーステンプレートを無料公開します。

新規注文・TP/SL・決済処理など、EAで共通して使う基本部分をあらかじめ用意しているため、
売買ロジックや必要なパラメータを追加することで、さまざまなEAへカスタマイズできます。

当サイトで公開している移動平均線・RSI・MACD・ボリンジャーバンドなどのEAサンプルも、基本的にこのテンプレートを土台として、各ロジックに必要な部分を追加・変更する考え方で作成しています。

📘 このテンプレートでできること

  • 売買ロジックを追加してオリジナルEAを作る
  • 固定pipsのTP・SLを設定する
  • 独自のTP・SL計算へ差し替える
  • 反対シグナルなどの決済条件を追加する
  • 新規注文・変更注文・全決済の共通関数を利用する

MT4 EAベーステンプレートの仕様

今回公開する00_BASE.mq4の基本仕様は次の通りです。

項目内容
対応MT4 / MQL4
ポジション数口座内に注文がない場合のみ新規エントリー
判定タイミング新しいローソク足ができたとき
標準TP固定pips
標準SL固定pips
MagicNumber管理なし(学習用テンプレートのため)
pips補正3桁・5桁ブローカーに対応
新規注文funcOrder_Send()
注文変更funcOrder_Modify()
決済funcOrder_CloseAll()

このEAテンプレートを使う前の注意点

このテンプレートは、EAの基本構造や売買ロジックの組み込み方を学びやすくすることを優先しています。
複数EAを同一口座で管理するためのMagicNumberによるポジション識別などは、あえて実装していません。

新規エントリーの判定にはOrdersTotal()を使用しているため、口座内に他の注文が存在すると新規エントリーしません。

また、決済条件を追加した場合も、このテンプレート単体では他EAや手動ポジションを細かく識別する構成にはしていません。
そのため、そのまま利用する場合は他のEAや手動取引と同じ口座で併用せず、EA単独で検証する方法を推奨します。

複数EAの同時運用やMagicNumber管理、入力値チェックなど、より実運用向けの共通機能が必要な場合は、後半で紹介するMT4 EAビルダーも利用できます。

MT4 EAテンプレートの無料ソースコード

以下が今回使用するベーステンプレートの完全ソースコードです。

個別EAを作成するときは、コード内にある
【パラメータ設定】、
【新規注文判断】、
【TP/SL判断】、
【決済注文判断】
の4か所を中心に変更します。

💡 このコードがEAサンプルのベースです
移動平均線・RSI・MACD・ボリンジャーバンドなどの個別EA記事では、このテンプレートから追加・変更した主な行を背景色で強調しています。
//+------------------------------------------------------------------+
//|                                                      00_BASE.mq4 |
//|                                Copyright © 2020-2026 ぷろぐらむFX |
//|                                             https://fx-prog.com/ |
//|                                                                  |
//| 使い方:                                                         |
//| 「パラメータ設定」「新規注文判断」「TP/SL判断」「決済注文判断」に |
//| 必要なロジックを追加してEAを作成します。                         |
//+------------------------------------------------------------------+

#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;                    //利確(pips)
input int SL = 100;                    //損切り(pips)


//***【パラメータ設定↓】***//

// ここに個別EAで使用するパラメータを追加してください。

//***【パラメータ設定↑】***//


string Ea_Name = WindowExpertName();   //EA名称をオーダーコメントに使用
double PipValue;                       //ブローカー桁数に対応したPoint補正
datetime prevtime;                     //ローソク足時間保持用


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){

   //3桁・5桁ブローカーのpips補正
   if(Digits == 3 || Digits == 5){
      PipValue = Point * 10;
   }else{
      PipValue = Point;
   }

   return(INIT_SUCCEEDED);
}


//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
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;


//***【新規注文判断↓】***//

// BUY・SELL条件を追加してください。
// 条件成立時に openBuy または openSell を true にします。

//***【新規注文判断↑】***//


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


//***【TP/SL判断↓】***//

      //標準では固定pipsのTP・SL
      //個別EAで独自の決済価格を使う場合は、この部分を差し替えます。

      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){
         //学習用テンプレートではMagicNumber管理を行わないため0
         funcOrder_Send(ea_order_Type,ea_order_stop_price,ea_order_good_price,Lots,Ea_Name,0,0);
      }


   //===============================================================
   // ポジションがある場合:決済判定
   //===============================================================
   }else{

      bool closeBuy = false;
      bool closeSell = false;


//***【決済注文判断↓】***//

// 決済シグナルを使う場合は条件を追加してください。
// 条件成立時に closeBuy または closeSell を true にします。
// TP・SLだけで決済するEAの場合は何も追加しません。

//***【決済注文判断↑】***//


      if(closeBuy){
         ea_order_Type = OP_BUY;
      }else if(closeSell){
         ea_order_Type = OP_SELL;
      }


      if(ea_order_Type > -1){
         //MagicNumber管理を行わないため全MagicNumberを対象
         funcOrder_CloseAll(ea_order_Type,-1,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;

   //最大10回リトライ
   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;
}


//+------------------------------------------------------------------+
//|【関数】変更注文関数                                              |
//|【引数】ticket:修正対象のチケットNo                              |
//|【引数】sl:新しい損切り価格  tp:新しい利確価格                   |
//|【引数】maxSpreadPoints:許容スプレッド[Point] (0=制限なし)       |
//|【戻値】true=成功 false=失敗                                      |
//+------------------------------------------------------------------+
bool funcOrder_Modify(int ticket, double sl, double tp, int maxSpreadPoints){

   double spread = 0;

   //注文選択
   if(!OrderSelect(ticket,SELECT_BY_TICKET)){
      Print("funcOrder_Modify: OrderSelect失敗 ticket=",ticket," エラー=",GetLastError());
      return false;
   }

   //現在チャートと異なる通貨は変更しない
   if(OrderSymbol() != Symbol()){
      Print("funcOrder_Modify: シンボル不一致 ",OrderSymbol(),"≠",Symbol());
      return false;
   }

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

   //最大10回リトライ
   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;
      }

      ResetLastError();

      bool result = OrderModify(ticket,OrderOpenPrice(),sl,tp,0,clrNONE);

      if(result){
         Print("変更注文成功! チケットNo=",ticket," 新SL=",sl," 新TP=",tp," スプレッド=",spread,"ポイント");
         return true;
      }

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

   return false;
}


//+------------------------------------------------------------------+
//|【関数】全決済関数                                                |
//|【引数】orderType:-1=すべて 0=BUYのみ 1=SELLのみ                 |
//|【引数】magic:対象MagicNumber (-1=全MagicNumber)                  |
//|【引数】maxSpreadPoints:許容スプレッド[Point] (0=制限なし)       |
//|【戻値】true=全成功 false=一部失敗あり                            |
//+------------------------------------------------------------------+
bool funcOrder_CloseAll(int orderType, int magic, int maxSpreadPoints){

   bool allSuccess = true;

   //後ろから順番に処理
   for(int i=OrdersTotal()-1; i>=0; i--){

      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) continue;

      //現在チャートと異なる通貨は対象外
      if(OrderSymbol() != Symbol()) continue;

      //MagicNumber指定がある場合
      if(magic != -1 && OrderMagicNumber() != magic) continue;

      int type = OrderType();

      //成行BUY・SELL以外は対象外
      if(type != OP_BUY && type != OP_SELL) continue;

      //BUY・SELL指定
      if(orderType == OP_BUY && type != OP_BUY) continue;
      if(orderType == OP_SELL && type != OP_SELL) continue;
      if(orderType != -1 && orderType != OP_BUY && orderType != OP_SELL) continue;

      int ticket = OrderTicket();
      double lots = OrderLots();
      bool result = false;

      //最大10回リトライ
      for(int retry=0; retry<10; retry++){

         RefreshRates();

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

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

         double closePrice = 0;
         color clr = clrNONE;

         if(type == OP_BUY){
            closePrice = Bid;
            clr = clrBlue;
         }else{
            closePrice = Ask;
            clr = clrRed;
         }

         closePrice = NormalizeDouble(closePrice,Digits);
         ResetLastError();

         result = OrderClose(ticket,lots,closePrice,20,clr);

         if(result){
            Print("クローズ成功! チケットNo=",ticket," ロット=",lots," クローズ価格=",closePrice," スプレッド=",spread,"ポイント");
            break;
         }

         int err = GetLastError();
         Print("クローズ失敗 ticket=",ticket," エラーNo=",err," リトライ=",retry+1);
         Sleep(2000);
      }

      if(!result) allSuccess = false;
   }

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

EAテンプレートで変更する4か所

個別のEAを作成するときは、基本的に次の4か所を変更します。

変更箇所追加する内容
パラメータ設定MA期間・RSI水準など、そのEA固有の設定値
新規注文判断BUY・SELLのエントリー条件
TP/SL判断標準の固定pips、またはロジック固有のTP・SL
決済注文判断反対シグナル決済など。TP・SLのみの場合は追加不要

1. パラメータ設定を追加する

個別EAで使用する設定値は、【パラメータ設定】の間へ追加します。

//***【パラメータ設定↓】***//

// ここに個別EAで使用するパラメータを追加してください。

//***【パラメータ設定↑】***//

例えば移動平均線EAでは、短期MA期間・中期MA期間・MA種別などを追加します。

//***【パラメータ設定↓】***//

input int FasterMA = 21;      //短期移動平均線期間
input int MediumMA = 84;      //中期移動平均線期間
input int MAMode = 1;         //0=SMA 1=EMA 2=SMMA 3=LWMA
input int SL_GOSA = 6;        //中期MAからSLまでの距離(pips)

//***【パラメータ設定↑】***//

2. 新規注文判断を追加する

BUY・SELLの売買条件は、【新規注文判断】の間へ追加します。

//***【新規注文判断↓】***//

// BUY・SELL条件を追加してください。
// 条件成立時に openBuy または openSell を true にします.

//***【新規注文判断↑】***//

例えばBUY条件が成立した場合はopenBuy = true;、SELL条件が成立した場合はopenSell = true;とします。

その後の共通処理でOP_BUYまたはOP_SELLへ変換され、新規注文関数へ渡されます。

具体的な売買ロジックは、それぞれのEAサンプル記事で「ベーステンプレートからの変更点」とあわせて解説しています。

3. TP・SLを必要に応じて変更する

ベーステンプレートでは、初期状態で固定pipsのTP・SLを使用します。

//***【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判断↑】***//

ロジックに合わせて独自のTP・SLを使う場合は、この部分を差し替えます。

例えば移動平均線EAでは、固定pipsのTP・SLを使用せず、中期MAを基準にSLを設定し、SLまでの値幅と1:1になる位置へTPを設定できます。

4. 必要なら決済注文判断を追加する

反対シグナルなどでポジションを決済したい場合は、【決済注文判断】へ条件を追加します。

//***【決済注文判断↓】***//

// 決済シグナルを使う場合は条件を追加してください。
// 条件成立時に closeBuy または closeSell を true にします.

//***【決済注文判断↑】***//

BUYポジションを決済する条件が成立した場合はcloseBuy = true;、SELLポジションを決済する場合はcloseSell = true;とします。

TP・SLだけで決済するEAでは、この部分へ条件を追加する必要はありません。

テンプレートに含まれる共通注文関数

ベーステンプレートには、EA開発でよく使う3つの注文関数をあらかじめ用意しています。

関数役割
funcOrder_Send()新規BUY・SELL注文を送信
funcOrder_Modify()既存注文のSL・TPを変更
funcOrder_CloseAll()BUY・SELLまたは対象ポジションを決済

各関数には、注文失敗時のリトライ処理や、必要に応じて利用できるスプレッドチェックも含まれています。

また、価格・SL・TPについてはNormalizeDouble()を使い、通貨ペアの桁数に合わせた値へ補正してから注文処理を行います。

注文関数そのものの仕組みを詳しく確認したい場合は、以下の記事で解説しています。

スポンサーリンク

ベーステンプレートからEAを作る実例

このベーステンプレートを実際にカスタマイズした例として、移動平均線EAを公開しています。

移動平均線EAでは、テンプレートへMAクロスの売買判定を追加し、標準の固定TP・SLを中期MA基準の決済方式へ変更しています。

個別EAの記事では、ベーステンプレートから変更した内容を簡潔な箇条書きで整理し、さらに完全ソースコード内の変更・追加部分を背景色で強調しています。

テンプレートと完成したEAを見比べることで、「共通部分は残し、ロジック固有の部分だけを追加・変更する」というEAの作り方を確認できます。

そのほかの移動平均線・RSI・MACD・ボリンジャーバンドなどのEAサンプルも、EAサンプルコード一覧から確認できます。

コードを書かずにEAを作りたい場合

ベーステンプレートを自分で編集する方法のほか、当サイトの無料MT4 EAビルダーを利用して、画面上で条件を設定しながらEAを作成する方法もあります。

EAビルダーは、今回のようなEAの基本構造をベースにしながら、
MagicNumberによるポジション識別・入力値チェック・ロット管理など、
学習用テンプレートより実運用を想定した共通処理を追加してEAを生成します。

使い分けの目安
・MQL4の仕組みを理解しながらEAを作りたい → ベーステンプレート
・条件を選びながらコードを書かずにEAを作りたい → MT4 EAビルダー
・独自ロジックや複雑な仕様を実装したい → EA作成代行・仕様相談

MT4 EAテンプレートのよくある質問

Q. このテンプレートだけでEAとして動きますか?

ベーステンプレートには注文処理やTP・SLなどの基本構造が入っていますが、BUY・SELLの売買条件は入っていません。実際に売買するには、新規注文判断へエントリー条件を追加する必要があります。

Q. MagicNumberには対応していますか?

この学習用テンプレートではMagicNumberによるポジション管理を行っていません。そのため、そのまま使用する場合は他のEAや手動ポジションと同じ口座で併用せず、EA単独での検証を推奨しています。

Q. TP・SLは変更できますか?

変更できます。初期状態では固定pipsですが、【TP/SL判断】部分を書き換えることで、移動平均線やATRなどを基準にした独自のTP・SLへ変更できます。

Q. 決済条件を追加しなくても使えますか?

はい。新規注文時にTP・SLを設定するEAであれば、【決済注文判断】へ条件を追加しなくても利用できます。反対シグナルなどで途中決済したい場合だけ、決済条件を追加します。

Q. 複数のインジケーターを組み合わせることもできますか?

できます。例えば移動平均線とADXなど、複数の判定条件を新規注文判断へ追加し、すべての条件を満たした場合だけBUY・SELLする構成にできます。

Q. EAビルダーとの違いは何ですか?

ベーステンプレートはMQL4コードを自分で編集しながらEAの仕組みを学ぶためのものです。EAビルダーは画面上で条件を設定してEAを生成でき、MagicNumberや入力値チェックなど、より実運用を想定した共通処理も自動で追加されます。

まとめ

今回公開したMT4 EAベーステンプレートには、EAを作るうえで共通して使う新規注文・変更注文・決済処理などをあらかじめ用意しています。

  • 売買ロジックを追加してEAを作成できる
  • 標準では固定pipsのTP・SLを利用
  • ロジックに合わせてTP・SLを変更可能
  • 新規注文・変更注文・全決済を共通関数化
  • 4つの変更ポイントを中心に個別EAへカスタマイズできる
  • MagicNumber管理は入れず、仕組みを確認しやすい構成

まずこのベーステンプレートの構造を確認し、その後、各EAサンプルの「ベーステンプレートからの変更点」とコード内で背景色が付いた部分を見比べると、MQL4でEAを組み立てる流れを理解しやすくなります。

次に別の売買ロジックを試したい場合は、EAサンプルコード一覧から各インジケーターの実装例を確認できます。

コメント

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