今回はMT4の自動売買用EAサンプルソース(FX用)を、プログラミング初心者の方向けに解説しています。
トレードに使うテクニカル分析はRSIで、逆張りエントリーをしています。
はじめに
RSIはとてもシンプルなので、サンプルソースも至って単純な形です。一応RSIの有効性も含め確認しておこうと思います。
今回、以下ではRSIの値を見ながら上げ過ぎで売り、下げ過ぎで買いエントリーしていくサンプルを載せています。
EAの仕様
それでは、今回のソースコードのエントリー/決済/パラメータ設定についての仕様を説明します。
エントリータイミング
ロングエントリー
RSIが(RSI_KAI)を下回ったらロングエントリーします。
ショートエントリー
RSIが(RSI_URI)を上回ったらショートエントリーします。
エントリー例

買われ過ぎたら売り、売られ過ぎたら買い、という逆張り系の基本通りの使い方となっています。
決済タイミング
エントリー時の逆指値、指値でのみ管理。
初期値として、指値は10pipsで逆指値は17.5pipsです。
その他の仕様
設定値は以下の通りです。
- RSI_KIKAN = 19 ⇒ RSIの期間
- input int RSI_KAI = 23 ⇒ RSIの値がいくらになったらロングするか
- input int RSI_URI = 71 ⇒ RSIの値がいくらになったらショートするか
- A_SPREAD = 20 ⇒ エントリー時に許容するスプレッドの値です(20 = 2pips)
- Lots = 1 ⇒ ロット数です(0.01=1000通貨)
- input int SL = 175 ⇒ 損切り幅
- input int TP = 100 ⇒ 利確幅
- input int MAX_POSI = 1 ⇒ 最大ポジション数
- input int WAIT_TIME = 30 ⇒ 複数ポジションエントリー待機時間(分)
「最大ポジション数」の設定を2以上にすると、似たようなタイミングでポジションを連続エントリーしてしまうので、「複数ポジションエントリー時待機分」を設定してください。この設定で次回エントリーを設定分だけ見送ります。
新しい足(バー)が出来た際に1度だけ処理を行います。※1時間足の場合だと1時間に1回処理する
EAレポート結果

今回は少し趣向を変えて2020年~2021年という直近の1年間の1分足でバックテスト確認してみました。いくつか最適化して確認していきましたが、RSIは何故か大きな時間足よりも1分足でトレードする方が結果が出やすかったのがすこし意外でした。
ダウンロード
上記のEAファイルになります。
“RSI-EA” をダウンロード 9_RSI.ex4 – 3753 回のダウンロード – 11.29 KBソースコード
以下サンプルソースコードになります。
※丸々コピペでコンパイルできます
//+------------------------------------------------------------------+
//| RSI_TEST.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 RSI_KIKAN = 19;
input int RSI_KAI = 23;
input int RSI_URI = 71;
input int A_SPREAD = 10;
input double Lots = 1;
input int SL = 175;
input int TP = 100;
input int MAX_POSI = 1;
input int WAIT_TIME = 30;
// ===== グローバル変数 =====
datetime lastOrderTime = 0; // 最後にエントリーしたバーの時間
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 RSI_atai = iRSI(NULL, 0, RSI_KIKAN, PRICE_CLOSE, 0); //RSIの値を取得
//RSI買い判断
if(RSI_atai < RSI_KAI)
{
//ロングエントリー
orderPtn=1;
}
//RSI売り判断
else if(RSI_atai > RSI_URI)
{
//ショートエントリー
orderPtn=2;
}
else
{
//エントリーしない
orderPtn=0;
}
//***売買判断箇所***//
//***決済判断箇所***//
total=OrdersTotal();
// 発注間隔(分)
int minInterval = WAIT_TIME * 60;
if(total < MAX_POSI && orderPtn > 0)
{
if(TimeCurrent() - lastOrderTime >= minInterval)
{
if(orderPtn == 1)
{
ea_order_stop_price = Ask - SL * Point;
ea_order_good_price = Ask + TP * Point;
}
else if(orderPtn == 2)
{
ea_order_stop_price = Bid + SL * Point;
ea_order_good_price = Bid - TP * Point;
}
//新規注文
OrderKekka = funcOrder_Send(orderPtn - 1,ea_order_stop_price,ea_order_good_price,0,0);
// 発注処理...
lastOrderTime = TimeCurrent();
}
}
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) < A_SPREAD){
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]
Lots, // ロット[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;
}
主な構文
iRSI()
【使用例】 double RSI_atai = iRSI(NULL, 0, 14, PRICE_CLOSE, 0);
今回は、RSIの値を取得できるiRSI()関数を使っています。
引数は以下の通りです。
- 引数1・・・通貨ペアです(NULLでチャートの通貨になります)
- 引数2・・・時間軸です(0でチャートの時間軸になります)
- 引数3・・・期間です(14がデフォルトです)
- 引数4・・・適用価格です(PRICE_CLOSEでクローズ値)
- 引数5・・・バーシフトです(0で現在の値、1で1つ前ーのバーの時の値です)
基本的に、3ぐらいしか触らなさそうな設定ですね。
さいごに
以上、RSIを使ったEAのサンプルソースでした。
RSIは単体で使うことはあんまり無いかもしれないですが、分スキャルピング感覚なら単体で使えるかもしれない?と思いました。

Quant analyzer(クオンツアナライザー)を使って確認してみると、5分以内の短期トレードで最も利益を上げれている事がわかります。この内容だと4時間を超えるポジションは強制的に決済してもいいかもしれないですね。
✅ 他にも多数のEAサンプルを公開中!
今回紹介した内容以外にも、当サイトではさまざまなFX自動売買EAのサンプルコードを提供しています。
自分に合った戦略のEAを見つけたい方は、ぜひチェックしてみてください。
EA開発初心者向けに、今後も実践的なMQL4関数を紹介していきます。
気になる機能やロジックがあれば、ぜひ他の記事もあわせてご覧ください!
コメント
すいませんが、どこでダウンロードできますか?無料でしょうか?有料でしょうか?有料なら、試用版はありますか
無料ですよー。掲載しているソースコードをコンパイルさえして頂ければ使えます!(コンパイル済みのファイルはこのサイトにはありません)
コンパイル方法は、https://fx-prog.com/program-eazy2/のページ等に書いているのですがわからなければ質問して頂ければ回答します!
ありがとうございました。私は頭が悪いので、上記ページを拝見しても、できません。残念
始めまして。コード等参考にさせていただいています。
有益な情報を提供いただきありがとうございます。
本ページで掲載していただいているコードに、
例えばエントリーから4時間経過後強制クローズさせたい場合は、
どのようにコードを組めば良いかご教授いただけないでしょうか。
はじめまして、参考にして頂きありがとうございます!
時間によるクローズ処理を入れるとすると、94行目(return(0);の上あたり)に入れるといいと思います。入れるコードはこんな感じでOKです。
if(OrderSelect(0,SELECT_BY_POS,MODE_TRADES)==true){
//オーダー後10時間を超えた場合(60秒*240で4時間)
if(TimeCurrent() – OrderOpenTime() > 60*240){
OrderKekka = OrderClose(OrderTicket(),OrderLots(),Bid,10,Violet);
}
}
ご連絡いただき、大変恐縮です。
これからもりょうさんのHPでEAについて勉強させていただきます。
ありがとうございました。
始めまして。
いつもコード等参考に勉強させて頂いております。
ありがとうございます。
こちらのRSIのEAは既にポジションがある場合は追加でエントリーしません。
となっておりますが、シグナルが出るたびに追加でポジションを取るように変更するには
どのようなコードを組めば良いかご教授いただけないでしょうか。
よろしくお願い致します。
はじめまして、参考にして頂きありがとうございます!
少しコメントではお伝えするのが難しそうだったので、この記事のソースコードを
複数ポジション取れるようにバージョンアップします。
すみませんが、もうしばらくお待ちくださいm(__)m
記事を更新しました。
以下のパラメータ設定で調整してみてください。
・MAX_POSI = 1 ⇒ 最大ポジション数
・WAIT_TIME = 30 ⇒ 複数ポジションエントリー待機時間(分)
※最大ポジション数を増やすと、同じ場所で何度もエントリーしてしまうので待機時間の設定を付けました
りょうさん
こんばんは。
新しいソースコードとパラメータを早速作ってご教示してくださり
ありがとうございました。
こちらのEAを動かしたり、他の記事のEAを参考に勉強させて頂きたいと思います。
また何か解らない時やコードについて尋ねることがあると思いますが
どうぞよろしくお願い致します。