EAを作り始めたものの、 「どんなトレードロジックを作ればいいのか分からない」 「最初から複雑に考えてしまう」 と悩んでいませんか?
本記事では、 勝率50%・期待値ほぼゼロのシンプルなEAを出発点にして、 そこからテクニカルを1つずつ追加・最適化していく手順を、 実際のEAコードとバックテスト結果を使って解説します。
「EAのトレード戦略=難しいもの」と感じている方でも、 ロジック設計の考え方が分かる構成になっています。
※ 本記事は「MQL4/MT4の基本操作が分かり、簡単な修正ができる方」向けです。
EAロジック設計は「シンプル」から始める
私も“ひらめき型”ではなく、検証しながら組み立てるタイプです。だからこそ、まずは勝率50%の土台を作り、条件を1つずつ足して改善する手順に落とし込みました。
まず、EAのさわりの部分ですが難しく考え過ぎずシンプルに考えることが重要だと私は思います。
どれぐらいシンプルかと言うと、
①適当にトレードする
②損切り幅、利確幅は同じにする(1ポジション及び固定ロットで考える)
③スプレッドを考慮する
これだけ考えます。これで勝率は50%で利益はプラマイゼロ(正確にはスプレッド分負ける)というトレード戦略が出来上がります。50%理論は以下の記事に詳細を記載していますので良かったら参考にしてみてください。
まずは、勝率50%前後でスプレッド分だけ負けていくような(ベースとなる)EAを作ります。時間足はいくらでもいいですが、私は大体15分足を多用しています。
時間でロングやショートをするサンプルEA
ベースEAのサンプルです。時間(0分/30分ならロング、15分/45分ならショート)でロングかショートを選んでいるので、なぜロングなのか、ショートなのかというテクニカルな根拠は一切存在しません。あと損切り、利確はどちらも20pipsです。
//+------------------------------------------------------------------+
//| STOC_Sample.mq4 |
//| Copyright 2020, mef Software. |
//| https://fx-prog.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, mef Software."
#property link "https://fx-prog.com/"
#property version "1.00"
input int STOP_LOSS = 200;
input int TP = 200;
datetime prevtime;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//---
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
int start()
{
int orderPtn=0; //0:何もしない 1:買い 2:売り
int total=0;
double ea_order_stop_price=0,ea_order_good_price=0; //ストップロスレート,利確レート,エントリーレート
bool OrderKekka;
//---
//新しい足ができた時だけやる
if(Time[0] != prevtime){
prevtime = Time[0];
}else{
return(0);
}
//***売買判断箇所***//
//0分、30分の場合はロング
if(Time[0] % 1800 == 0){
orderPtn=1;
}else{
orderPtn=2;
}
//***売買判断箇所***//
//***決済判断箇所***//
total=OrdersTotal();
if(total ==0 && orderPtn > 0)
{
if(orderPtn == 1)
{
ea_order_stop_price = Ask - STOP_LOSS * Point;
ea_order_good_price = Ask + TP * Point;
}
else if(orderPtn == 2)
{
ea_order_stop_price = Bid + STOP_LOSS * Point;
ea_order_good_price = Bid - TP * Point;
}
//新規注文
OrderKekka = funcOrder_Send(orderPtn - 1,ea_order_stop_price,ea_order_good_price,0,0);
}
return(0);
}
//+------------------------------------------------------------------+
//|【関数】新規注文関数 |
//| |
//|【引数】 ea_order_entry_Type:売買(0:買 1:売) |
//|【引数】 ea_order_stop_price:損切値 ea_order_good_price:利確値 |
//|【引数】 orderComment:オーダーコメント ea_order_MagicNo:マジックNo |
//| |
//|【戻値】True:成功 |
//| |
//|
bool funcOrder_Send(int ea_order_entry_Type, double ea_order_stop_price, double ea_order_good_price,int orderComment,int ea_order_MagicNo)
{
int order_resend_num; // エントリー試行回数
int ea_ticket_res; // チケットNo
int errorcode; // エラーコード
double ea_order_entry_price; // エントリーレート
color order_Color;
bool kekka;
for( order_resend_num = 0; order_resend_num < 10; order_resend_num++ ) { // エントリー試行回数上限:10回
if(MarketInfo(NULL,MODE_SPREAD) < 20){
if(ea_order_entry_Type == OP_BUY){
ea_order_entry_price = Ask; // 現在の買値でエントリー
order_Color = clrBlue;
}else if(ea_order_entry_Type == OP_SELL){
ea_order_entry_price = Bid; // 現在の売値でエントリー
order_Color = clrRed;
}
// FXCMでは新規エントリー時にストップ/リミットを設定出来ない。
ea_ticket_res = OrderSend( // 新規エントリー注文
NULL, // 通貨ペア
ea_order_entry_Type, // オーダータイプ[OP_BUY / OP_SELL]
0.01, // ロット[0.01単位](FXTFは1=10Lot)
ea_order_entry_price, // オーダープライスレート
20, // スリップ上限 (int)[分解能 0.1pips]
ea_order_stop_price, // ストップレート
ea_order_good_price, // リミットレート
orderComment, // オーダーコメント
ea_order_MagicNo, // マジックナンバー(識別用)
0, // オーダーリミット時間
order_Color // オーダーアイコンカラー
);
}
if ( ea_ticket_res == -1) { // オーダーエラー
errorcode = GetLastError(); // エラーコード取得
if( errorcode != ERR_NO_ERROR) { // エラー発生
printf("エラー");
}
Sleep(2000); // 1000msec待ち
RefreshRates(); // レート更新
printf("再エントリー要求回数:%d, 更新エントリーレート:%g",order_resend_num+1 ,ea_order_entry_price);
} else { // 注文約定
Print("新規注文約定。 チケットNo=",ea_ticket_res," レート:",ea_order_entry_price);
Sleep(300); // 300msec待ち(オーダー要求頻度が多過ぎるとエラーになる為)
break;
}
}
return kekka;
}
上記EAの結果はこんな感じです。※アルパリのヒストリカルデータで確認しています

この適当にトレードするEAはもちろんプロフィットファクターもほぼプラマイゼロ、勝率も約50%です。
次に、このベースEAにテクニカル分析を1つ取り入れ勝率を50%より上にしていきます。
EAにテクニカル分析を追加する考え方
今回は例として、オシレータ系のテクニカルでストキャスティクスを追加してみます。
まずは、ストキャスティクスの王道で買われ過ぎたら売る、売られ過ぎたら買うという形にしてみます。
ストキャスティクスを取り入れたEA
先ほどの時間ではなく、ストキャスティクスの値を見て80より大きかったらショート、20より小さかったらロングエントリーするように変更しました。先ほどのベースソースから『売買判断箇所』で囲まれた部分だけ修正したものです。
あと、ストキャスティクスの値は最適化で調整できるように「input int E_KAI = 20」という形で記載しています。
//+------------------------------------------------------------------+
//| STOC_Sample.mq4 |
//| Copyright 2020, mef Software. |
//| https://fx-prog.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, mef Software."
#property link "https://fx-prog.com/"
#property version "1.00"
input int E_KAI = 20;
input int E_URI = 80;
input int STOP_LOSS = 200;
input int TP = 200;
double maisuu=0.01;
datetime prevtime;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//---
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
int start()
{
int orderPtn=0; //0:何もしない 1:買い 2:売り
int total=0;
double ea_order_stop_price=0,ea_order_good_price=0; //ストップロスレート,利確レート,エントリーレート
bool OrderKekka;
//---
//新しい足ができた時だけやる
if(Time[0] != prevtime){
prevtime = Time[0];
}else{
return(0);
}
//***売買判断箇所***//
//ストキャスティクスの値取得
double STOC_atai1 = iStochastic(NULL,0,5,3,3,MODE_EMA,0,0,1);
double STOC_atai2 = iStochastic(NULL,0,5,3,3,MODE_EMA,0,0,2);
//ストキャの値が、E_KAIより下ならロング(ストキャが下に向かっている事)
if(STOC_atai1 < E_KAI && STOC_atai2 > STOC_atai1)
{
orderPtn=1;
}
//ストキャの値が、E_URIより上ならショート(ストキャが上に向かっている事)
else if(STOC_atai1 > E_URI && STOC_atai2 < STOC_atai1)
{
orderPtn=2;
}
else
{
orderPtn=0;
}
//***売買判断箇所***//
//***決済判断箇所***//
total=OrdersTotal();
if(total ==0 && orderPtn > 0)
{
if(orderPtn == 1)
{
ea_order_stop_price = Ask - STOP_LOSS * Point;
ea_order_good_price = Ask + TP * Point;
}
else if(orderPtn == 2)
{
ea_order_stop_price = Bid + STOP_LOSS * Point;
ea_order_good_price = Bid - TP * Point;
}
//新規注文
OrderKekka = funcOrder_Send(orderPtn - 1,ea_order_stop_price,ea_order_good_price,0,0);
}
return(0);
}
//+------------------------------------------------------------------+
//|【関数】新規注文関数 |
//| |
//|【引数】 ea_order_entry_Type:売買(0:買 1:売) |
//|【引数】 ea_order_stop_price:損切値 ea_order_good_price:利確値 |
//|【引数】 orderComment:オーダーコメント ea_order_MagicNo:マジックNo |
//| |
//|【戻値】True:成功 |
//| |
//|
bool funcOrder_Send(int ea_order_entry_Type, double ea_order_stop_price, double ea_order_good_price,int orderComment,int ea_order_MagicNo)
{
int order_resend_num; // エントリー試行回数
int ea_ticket_res; // チケットNo
int errorcode; // エラーコード
double ea_order_entry_price; // エントリーレート
color order_Color;
bool kekka;
for( order_resend_num = 0; order_resend_num < 10; order_resend_num++ ) { // エントリー試行回数上限:10回
if(MarketInfo(NULL,MODE_SPREAD) < 20){
if(ea_order_entry_Type == OP_BUY){
ea_order_entry_price = Ask; // 現在の買値でエントリー
order_Color = clrBlue;
}else if(ea_order_entry_Type == OP_SELL){
ea_order_entry_price = Bid; // 現在の売値でエントリー
order_Color = clrRed;
}
// FXCMでは新規エントリー時にストップ/リミットを設定出来ない。
ea_ticket_res = OrderSend( // 新規エントリー注文
NULL, // 通貨ペア
ea_order_entry_Type, // オーダータイプ[OP_BUY / OP_SELL]
0.01, // ロット[0.01単位](FXTFは1=10Lot)
ea_order_entry_price, // オーダープライスレート
20, // スリップ上限 (int)[分解能 0.1pips]
ea_order_stop_price, // ストップレート
ea_order_good_price, // リミットレート
orderComment, // オーダーコメント
ea_order_MagicNo, // マジックナンバー(識別用)
0, // オーダーリミット時間
order_Color // オーダーアイコンカラー
);
}
if ( ea_ticket_res == -1) { // オーダーエラー
errorcode = GetLastError(); // エラーコード取得
if( errorcode != ERR_NO_ERROR) { // エラー発生
printf("エラー");
}
Sleep(2000); // 1000msec待ち
RefreshRates(); // レート更新
printf("再エントリー要求回数:%d, 更新エントリーレート:%g",order_resend_num+1 ,ea_order_entry_price);
} else { // 注文約定
Print("新規注文約定。 チケットNo=",ea_ticket_res," レート:",ea_order_entry_price);
Sleep(300); // 300msec待ち(オーダー要求頻度が多過ぎるとエラーになる為)
break;
}
}
return kekka;
}
上記EAの結果はこんな感じです。

とりあえず、スプレッド分の損失は補填してくれるようなEAを作る事ができました。
EAを最適化するときのチェックポイント
最適化で検討する
先ほどの結果を見てもわかる通り、現状の設定ではあまり有効なEAではないので、最適化でより良いストキャスティクスの値と損切り、利確幅を確認していきます。
※最適化については以下の記事に詳細を記載していますので、分からない場合は参考にしてみてください

最適化の設定はこんな感じにしてみました。ストキャスティクスがいくらまで下がったらロングがいいのか、ストキャスティクスがいくらまで上がったらショートがいいのか、また損切り、利確幅はいくらがいいのかを最適化で確認していきます。
勝率が高いパターンで良さそうな値
勝率が70%を超え、かつプロフィットファクタも1.10になる設定がありました。
ストキャスティクスの値が13より下になったらロング、90を超えたらショート、損切りは21pipsで利確は9pipsという設定です。結果はこんな感じです。

プログラムは一切変えておらず、設定を少し変えただけです。
設定を少し変えるだけで結構変わりますね!設定の内容としては、ストキャスティクスの値を厳しめに見つつエントリーし、損切り幅を大きめにとり、利確は小さめといった感じです。
勝率は低いけど利確幅は大きい値
勝率は20%前半ですが、プロフィットファクタは1.04の設定も紹介します。
ストキャスティクスの値が17より下になったらロング、73を超えたらショート、損切りは6pipsで利確は22pipsという設定です。結果はこんな感じです。

プロフィットファクタはそんなに高くないです。
が、注目するポイントとしては現在時間に近い方が利益がよく出ています。
この直近の方が利益がでてる方が良い傾向です。
※勝率が高いパターンの方は現在時間は横ばいグラフだったので、リアルタイムだと微妙かも
こんな感じに最適化で確認していくだけで、トレード戦略として有益な情報が結構出てきます。
時間足を検討する
色んな時間足の目線で確認して行く事も重要です。
ストキャスティクスは5分足だと機能するのかしないのか、他の時間足ならどうなるのか等を見ていくと良いヒントが出てきたりします。
5分足の結果

先ほどの高勝率の設定をそのまま使って、5分足で確認してみました。
当然ですが、15分足で確認した程安定はしていない結果となります。
※ただし、5分足で最適化をして確認していくとさらにいいものが見つかるかもしれません
30分足の結果

30分足で最適化してよさそうなものを選びました。プロフィットファクタが1.26と割と良い感じになっています。
トレード回数を15分足よりも減らしていきたい場合、30分足等で最適化して確認するとトレード回数を減らして行く事も可能です。逆にトレード回数を増やしたい場合は、1分足や5分足で調整していく形になります。
通貨を検討する
ここまでは全てドル円通貨で確認しましたが、もちろんユーロドルやポンド円等で確認していき、よりストキャスティクスが効いている通貨を探すのも手です。
私の場合、スプレッドが狭いドル円が主戦場なので通貨を変えて確認していませんが、ポンド円など動きの大きい通貨だと、ドル円よりこのテクニカルがすごく効くとかっていうパターンもあると思うので色々な通貨で確認するのも一つの手です。
注意点として、通貨を検討する場合はポンド円等の場合スプレッドは10とかになってくると思うのでその辺は、そのスプレッド幅を補って行くトレード戦略を立てる必要がでてきます。
※今回はドル円で確認したのでスプレッドは全て2で確認しています
❓ EAロジック設計に関するよくある質問【EA初心者〜中級者向けFAQ】
💬 EAを作り始めたあとに多くの人が悩む「戦略設計・勝率・最適化」について、よくある疑問をQ&A形式でまとめました。
最初から勝てるEAを作る必要はありません。
まずは勝率50%前後で期待値がほぼゼロのシンプルなロジックを作り、そこから改良していく方が再現性の高いEAになります。
はい、十分に意味があります。
勝率50%で損切りと利確が同条件のEAは、ロジックの土台として非常に分かりやすく、どの要素が成績に影響しているかを検証しやすくなります。
基本は1つずつ追加するのがおすすめです。
複数のテクニカルを同時に入れると、どの条件が機能しているのか分からなくなり、カーブフィッティングの原因になります。
直近の期間だけ成績が良く、過去にさかのぼると極端に成績が悪化する場合は、カーブフィッティングの可能性が高いです。
期間をずらしても安定するかを確認することが重要です。
勝率やプロフィットファクターが一番高くなる一点を狙うのではなく、
ある程度広い範囲で安定している設定を選ぶのが安全です。
さいごに
以上が、『EAのトレード戦略の立て方』です。 EAを作る上で押さえるべきポイントは、次の4つです。
- 利益を出せる構造になっているか
- 直近相場でも機能しているか
- 過去相場でも極端に崩れていないか
- カーブフィッティング寄りの処理を入れていないか
EAがうまく作れないと感じたときほど、
ロジックを複雑にし過ぎていないかを見直してください。
勝率50%・期待値ほぼゼロのシンプルなEAから始め、テクニカル分析を1つずつ追加し、時間足・通貨・損切り/利確幅を調整していく。
この手順を守るだけで、「なぜこのEAは勝てているのか/負けているのか」を 自分で説明できるロジック設計ができるようになります。
また、設定変更や最適化を行ったあとは、
必ずビジュアルモードで実際の動きを確認してください。 エントリー位置や決済ポイントを目で追うことで、修正すべき点や無駄な条件が自然と見えてきます。
EA開発で迷ったら、
「シンプルに戻す → 検証する → 1つだけ改善する」
この流れに立ち返ることが、最短ルートです。
🔗 関連記事
- 勝率50%理論とは?FXで「期待値ゼロ」から考えるトレード設計の基本
- EAバックテストの最適化手順|パラメータ調整で見るべきポイントを解説
- EAバックテストのやり方・見方を初心者向けに完全解説
- カーブフィッティングとは?EAが「過去だけ勝つ」原因と見抜き方
✅ 今回のロジックをベースにしたEAサンプルも多数公開中
今回紹介したようなEAの売買ロジック・考え方をベースに、
当サイトではさまざまなFX自動売買EAのサンプルコードを公開しています。
ロジックの違いや設計の考え方を比較しながら、
自分に合ったEA構成を探したい方はぜひチェックしてみてください。
📊 EA運用・検証フェーズに進みたい方へ
今回のような仕組みを理解したうえで、
「実際にどのEAが安定しているのか」、「検証データではどんな差が出ているのか」
を確認したい方は、以下の記事も参考になります。
EA開発初心者向けに、今後も実践的に使えるMQL4関数や実装例を紹介していきます。
気になる機能やロジックがあれば、用途別に整理した関連記事もぜひあわせてご覧ください。











コメント
1分間でどれだけ上下しているのかを探す、EAがないか探しておりましたら、こちらのサイトに行き着きました。
プログラミングが得意ではないですが、拝見させていただいて、EAを選ぶのに参考になりました。
✕1分間でどれだけ上下しているのかを探す、EAがないか探して
○1分間で相場がどれだけ上下?しているのをカウントする、EAがないか探しております。
わかりにくかったので訂正します。これでも伝わらないかもしれません。すみません。
希望としては公開はしてほしくはありません。
『1分間で相場がどれだけ上下?しているのをカウントする』というのは出来高の事ですか?1分足が形成される間に105.410→105.411→105.412→105.411→105.411→105.410→105.409・・・というように値動きが何回起きたかを確認したい場合、MT4のインディケータ(標準搭載)でボリューム→Volumesを1分足チャート上に表示すると1分間に何回値動きがあったかを表示してくれますよ。ただ、それを用いてトレードするEAとなると私はまだ作った事がない&オススメの販売EAもわからないのでお力になれません!
ありがとうございます。
書いたのが、どのページが忘れてしまって遅れてすみません。
ちょっと違います。
始まり→ 上1回→ 上1回→ 下1回→ 同じ1回→下1回 →下1回
105.410→105.411→105.412→105.411→105.411→105.410→105.409・
その1分足の結果
上2回 下3回 同じ1回(カウントなし)
というのを ローソク足の上下に数値で表せないかということです。
すっと観ていて、パターンがあるのではないかと。
それで、検証したら面白いのではないかと
なるほど、上下をカウントして表示するといった感じでしたか!
1分前のデータがカウントできないので現在(MT4とインジを起動してから)からのカウントしか出来ないですけど、作ろうと思えば作れそうです。プライスアクション系のインジケータになりそうですね。ただ、ブローカーによって数値がかなりブレる気もします!