「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を同一口座で管理するためのMagicNumberによるポジション識別などは、あえて実装していません。
新規エントリーの判定にはOrdersTotal()を使用しているため、口座内に他の注文が存在すると新規エントリーしません。
また、決済条件を追加した場合も、このテンプレート単体では他EAや手動ポジションを細かく識別する構成にはしていません。
そのため、そのまま利用する場合は他のEAや手動取引と同じ口座で併用せず、EA単独で検証する方法を推奨します。
複数EAの同時運用やMagicNumber管理、入力値チェックなど、より実運用向けの共通機能が必要な場合は、後半で紹介するMT4 EAビルダーも利用できます。
MT4 EAテンプレートの無料ソースコード
以下が今回使用するベーステンプレートの完全ソースコードです。
個別EAを作成するときは、コード内にある
【パラメータ設定】、
【新規注文判断】、
【TP/SL判断】、
【決済注文判断】
の4か所を中心に変更します。
移動平均線・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テンプレートのよくある質問
ベーステンプレートには注文処理やTP・SLなどの基本構造が入っていますが、BUY・SELLの売買条件は入っていません。実際に売買するには、新規注文判断へエントリー条件を追加する必要があります。
この学習用テンプレートではMagicNumberによるポジション管理を行っていません。そのため、そのまま使用する場合は他のEAや手動ポジションと同じ口座で併用せず、EA単独での検証を推奨しています。
変更できます。初期状態では固定pipsですが、【TP/SL判断】部分を書き換えることで、移動平均線やATRなどを基準にした独自のTP・SLへ変更できます。
はい。新規注文時にTP・SLを設定するEAであれば、【決済注文判断】へ条件を追加しなくても利用できます。反対シグナルなどで途中決済したい場合だけ、決済条件を追加します。
できます。例えば移動平均線とADXなど、複数の判定条件を新規注文判断へ追加し、すべての条件を満たした場合だけBUY・SELLする構成にできます。
ベーステンプレートはMQL4コードを自分で編集しながらEAの仕組みを学ぶためのものです。EAビルダーは画面上で条件を設定してEAを生成でき、MagicNumberや入力値チェックなど、より実運用を想定した共通処理も自動で追加されます。
まとめ
今回公開したMT4 EAベーステンプレートには、EAを作るうえで共通して使う新規注文・変更注文・決済処理などをあらかじめ用意しています。
- 売買ロジックを追加してEAを作成できる
- 標準では固定pipsのTP・SLを利用
- ロジックに合わせてTP・SLを変更可能
- 新規注文・変更注文・全決済を共通関数化
- 4つの変更ポイントを中心に個別EAへカスタマイズできる
- MagicNumber管理は入れず、仕組みを確認しやすい構成
まずこのベーステンプレートの構造を確認し、その後、各EAサンプルの「ベーステンプレートからの変更点」とコード内で背景色が付いた部分を見比べると、MQL4でEAを組み立てる流れを理解しやすくなります。
次に別の売買ロジックを試したい場合は、EAサンプルコード一覧から各インジケーターの実装例を確認できます。









コメント