今回は、MT4のEAサンプルソース(FX用)を公開します。
トレードに使うテクニカル分析はRCIで、逆張りエントリーをしています。
はじめに
RCIはRSIと同じく、買われ過ぎ、売られ過ぎを見るインジケータですが、短期線、中値線、長期線があり少し複雑です。
今回は、買われ過ぎたら売り、売られ過ぎたら買い、という逆張り系の基本通りエントリーしていくサンプルを載せています。
下準備
まず、RCIをEAで使うにはRCIのインジケータが必要です。
ですが、MT4にはRCIのインジケータが初期導入されていませんので、RCIインジケータをMT4に入れていあげる必要があります。
以下の記事からRCIインジケータを準備できますのでご参照下さい。
※すでにRCIのインジケータをMT4に入れておられる方は大丈夫です
上記の準備をしないと、正常にRCIのEAが動きませんのでご注意ください。
EAの仕様
それでは、今回のソースコードのエントリー/決済/パラメータ設定についての仕様を説明します。
エントリータイミング
ロングエントリー
RCIの短期線が(RSI_KAI)を下回り、かつ中期線または長期線が上向きならロングエントリーします。
ショートエントリー
RCIの短期線が(RSI_URI)を上回り、かつ中期線または長期線が下向きならショートエントリーします。
エントリー例
買われ過ぎたら売り、売られ過ぎたら買い、という逆張り系の基本通りの使い方となっています。
決済タイミング
エントリー時の逆指値、指値でのみ管理。
初期値として、指値・逆指値共に20pipsです。(設定で変更可)
その他の仕様
設定値は以下の通りです。
- RCI_KIKAN1 = 9 ⇒ 短期RCIの期間
- RCI_KIKAN2 = 26 ⇒ 中期RCIの期間
- RCI_KIKAN3 = 52 ⇒ 長期RCIの期間
- RCI_VIEW_CNT = 3 ⇒ RCIの表示数(1~3)
- RCI_KAI = -70 ⇒ 短期RCIがいくらになったらロングするか
- RCI_URI = 60 ⇒ 短期RCIがいくらになったらショートするか
- A_SPREAD = 20 ⇒ エントリー時に許容するスプレッドの値です(20 = 2pips)
- Lots = 1 ⇒ ロット数です(0.01=1000通貨)
- SL = 200 ⇒ 損切り幅
- TP = 200 ⇒ 利確幅
既にポジションがある場合は追加でエントリーしません。
新しい足(バー)が出来た際に1度だけ処理を行います。※1時間足の場合だと1時間に1回処理する
EAレポート結果
今回が2018年~2021年という直近の3年間の15分足でバックテスト確認してみました。いくつか最適化して確認していきましたが、RCIは長い期間で中々成績を出すのが難しい感じでした。
ダウンロード
上記のEAファイルになります。
“RCI-EA” をダウンロード 10_RCI.ex4 – 4005 回のダウンロード – 11.51 KBソースコード
以下サンプルソースコードになります。
※丸々コピペでコンパイルできます
//+------------------------------------------------------------------+
//| RCI_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 RCI_KIKAN1 = 9;
input int RCI_KIKAN2 = 26;
input int RCI_KIKAN3 = 52;
input int RCI_VIEW_CNT = 3;
input int RCI_KAI = -70;
input int RCI_URI = 60;
input int A_SPREAD = 20;
input double Lots = 1;
input int SL = 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);
}
//***売買判断箇所***//
//クロス確認
orderPtn=getRciSign(1,0);
//***決済判断箇所***//
//***売買判断箇所***//
total=OrdersTotal();
if(total ==0 && orderPtn > 0)
{
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);
}
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;
}
//+------------------------------------------------------------------+
//|【関数】RCIのクロスを探す
//|
//|【引数】 IN OUT 引数名 説明
//| ---------------------------------------------------------
//| ○ limit どこまで遡るか
//| ○ i 現在のBar位置
//|【戻値】1:ロング 2:ショート 0:何もしない
//|
//|【備考】なし
//+------------------------------------------------------------------+
int getRciSign(int limit,int i)
{
int n;
int sign = 0;
limit = i + limit;
i = i + 1;
for(n=i;n<=limit;n++){
double RCI_atai_TAN_1 = iCustom(NULL, 0, "RCI", RCI_KIKAN1, RCI_KIKAN2,RCI_KIKAN3,RCI_VIEW_CNT,0 , n); //RCI[短期]の値を取得
double RCI_atai_TAN_2 = iCustom(NULL, 0, "RCI", RCI_KIKAN1, RCI_KIKAN2,RCI_KIKAN3,RCI_VIEW_CNT,0 , n+1); //RCI[短期]の1つ過去の値を取得
double RCI_atai_CHU_1 = iCustom(NULL, 0, "RCI", RCI_KIKAN1, RCI_KIKAN2,RCI_KIKAN3,RCI_VIEW_CNT,1 , n); //RCI[中期]の値を取得
double RCI_atai_CHU_2 = iCustom(NULL, 0, "RCI", RCI_KIKAN1, RCI_KIKAN2,RCI_KIKAN3,RCI_VIEW_CNT,1 , n+1); //RCI[中期]の1つ過去の値を取得
double RCI_atai_CHO_1 = iCustom(NULL, 0, "RCI", RCI_KIKAN1, RCI_KIKAN2,RCI_KIKAN3,RCI_VIEW_CNT,2 , n); //RCI[長期]の値を取得
double RCI_atai_CHO_2 = iCustom(NULL, 0, "RCI", RCI_KIKAN1, RCI_KIKAN2,RCI_KIKAN3,RCI_VIEW_CNT,2 , n+1); //RCI[長期]の1つ過去の値を取得
if(RCI_atai_TAN_1 <= RCI_KAI && (RCI_atai_CHU_1 > RCI_atai_CHU_2 || RCI_atai_CHO_1 > RCI_atai_CHO_2))
{
//ロングのサイン
sign=1;
break;
}else if(RCI_atai_TAN_1 >= RCI_URI && (RCI_atai_CHU_1 < RCI_atai_CHU_2 || RCI_atai_CHO_1 < RCI_atai_CHO_2))
{
//ショートのサイン
sign=2;
break;
}
}
return(sign);
}
今回は、RCIの値を確認するgetRciSign()関数を作成し、そこでロングかショートか何もしないかを判定するようにしています。
主な構文
iCustom()
【使用例】 double RCI_atai_TAN_1 = iCustom(NULL, 0, "RCI", 9, 26, 52, 3, 0, 1);
今回は、オリジナルインジケータ扱いなのでiCustom()関数を使用します。
※当ブログでRCIインジケータを作成した前提で解説しています
引数は以下の通りです。
- 引数1・・・通貨ペアです(NULLでチャートの通貨になります)
- 引数2・・・時間軸です(0でチャートの時間軸になります)
- 引数3・・・インジケータ名称(ナビゲーターウィンドウで確認しましょう)
- 引数4・・・短期期間です(9が一般的です)
- 引数5・・・中期期間です(26が一般的です)
- 引数6・・・長期期間です(52が一般的です)
- 引数7・・・RCIの表示本数です
- 引数8・・・取得する値です(0が短期、1が中期、2が長期の値になります)
- 引数9・・・バーシフトです(0で現在の値、1で1つ前ーのバーの時の値です)
引数3のインジケータ名称は、ナビゲータウィンドウで確認しておくと確実です。
引数4~7は設定画面を確認するとすぐわかります。この設定に出ている数だけ引数として渡すと覚えておけば問題ないです。
引数8は取得する値です。短期RCIの値を取得したい場合は0、中期RCIの値を取得したい場合は1、長期RCIの値を取得したい場合は2にします。
iCustom()関数は慣れると、どういった引数にすればいいのかすぐにわかるようになりますのでこの機会に慣れておいて損は無いと思います!
さいごに
以上、RCIを使ったEAのサンプルソースでした。
今回はインジケータを自ら作ってそれをEA側で読み込んでトレードしていくといった、結構しっかりとした形になったので良かったと思います。
(私はiCustom()をよく使ってますが、やっと本領発揮できた感じです)
RCIのインジケータに限らず自作のインジケータや市販のインジケータを使って、EAを作っていくとEA制作の幅がさらに広がりますね!
※ EAのサンプルソースを一覧表にまとめました
※EA作成依頼はこちら
※オンラインレッスンやってます
コメント
はじめまして。
xmのmt4にて、記事を参考に実装したのですが、テスターを実行すると操作履歴に新規注文約定。チケットNO=0 レート:0
のみが複数実行されます。
インジは読めてるようですが、なにが原因でしょうか??
1分足が良くないでしょうか?
ご教示いただけますと幸いです。
宜しくお願い致します。
はじめまして、かわむさん。多分テスターのスプレッド設定が10pips以上になってるような気がします。その場合、許容スプレッド設定(10→20等に変更)を変えるとエントリーしてくれるようになります。
A_SPREAD = 10 ⇒ エントリー時に許容するスプレッドの設定です(10 = 10pips)
りょうさん
返信ありがとうございます。
おっしゃる通りで、MarketInfo(NULL,MODE_SPREAD)とA_SPREADの値により、if文が通っていない状態でした
ありがとうございます。
りょうさん
別件となりますが、ブログ内でRCIとボリンジャーバンドなど、複数のインジを使用したEAの作成は検討されていないでしょうか??
いくつかロジックの案はあるのですが、実装するのは簡単ではないかもと思い、参考記事を探していたのですが、りょうさんのプログラムはまとまりがよく読みやすいので、記載してもらえたら嬉しいなという思いです。
勝手な要望ですが、ご検討いただけますと幸いです。
こんばんは、ありがとうございます。
RCI+他のインジの組み合わせという感じでしょうか?お問合せからでも良いのでロジック案をお伝え頂ければ、検討いたします。