今回は、MT4のEAサンプルソース(FX用)を公開します。
トレードに使うテクニカル分析は一目均衡表で、順張りエントリーをしています。
はじめに
私自身、裁量トレードでも一目均衡表は使ったことが無く、何だか難しそうなインジケータだなと思っていたのですが、実際使ってみるととてもシンプルでエントリーサインとしても使えそうだなと思いましたのでサンプルを作りました。
今回は、三役好転(三役逆転)でエントリー、三役好転(三役逆転)状態が解消されたら決済するサンプルを載せています。
一目均衡表のおさらい
◎5本の線の内容
①転換線 =(過去9日間の最高値+最安値)÷2
②基準線 =(過去26日間の最高値+最安値)÷2
③先行スパン1 =(転換線+基準線)÷2を26日将来に描画
④先行スパン2 =(過去52日間の最高値+最安値)÷2を26日将来に描画
⑤遅行スパン = 終値を26日過去にずらして描画
◎三役好転(三役逆転)
A.転換線が基準線を上抜けたとき
B.遅行スパンがローソク足を上抜けたとき
C.ローソク足が雲を上抜けたとき
※A~Cが全て一致した場合は三役好転で買いサイン
(三役逆転はこの逆バージョン)
EAの仕様
それでは、今回のソースコードのエントリー/決済/パラメータ設定についての仕様を説明します。
エントリータイミング
ロングエントリー
①転換線が基準線を上抜けたとき(Tenkansen > Kijunsen)
②遅行スパンがローソク足を上抜けたとき(ChikouSpan > iHigh(NULL,0,27))
③ローソク足が雲を上抜けたとき(SenkouSpanA > iClose(NULL,0,1) && SenkouSpanB > iClose(NULL,0,1))
※こちらは独断と偏見でローソク足の実体判定にしています、実体ではなくヒゲも含めたい場合、iClose()をiHigh()にして判断してください
上記の内容を満たした場合、ロングエントリーします。
ショートエントリー
①転換線が基準線を下抜けたとき(Tenkansen < Kijunsen)
②遅行スパンがローソク足を下抜けたとき(ChikouSpan < iHigh(NULL,0,27))
③ローソク足が雲を下抜けたとき(SenkouSpanA < iClose(NULL,0,1) && SenkouSpanB < iClose(NULL,0,1))
※こちらは独断と偏見でローソク足の実体判定にしています、実体ではなくヒゲも含めたい場合、iClose()をiLow()にして判断してください
上記の内容を満たした場合、ショートエントリーします。
決済タイミング
ロングポジションを持っており、三役好転状態が解消されたら決済。また、ショートポジションを持っており、三役逆転状態が解消されたら決済。
その他の仕様
設定値は以下の通りです。
- A_SPREAD = 20 ⇒ エントリー及び決済時に許容するスプレッドの値です(20 = 2pips)
- Lots = 0.01 ⇒ ロット数です(0.01=1000通貨)
既にポジションがある場合は追加でエントリーしません。
新しい足(バー)が出来た際に1度だけ処理を行います。※1時間足の場合だと1時間に1回処理する
指値、逆指値は設定していません。
EAレポート結果
2005年~2020年の期間の1時間足でバックテスト確認してみました。いい感じのプラスになりました。エントリータイミングも決済タイミングも一目均衡表しか使っていないので、一目均衡表は相場に対して十分有効だと思います。
ダウンロード
上記のEAファイルになります。
“一目均衡表EA” をダウンロード 3_Ichimoku.ex4 – 2157 回のダウンロード – 14.07 KBソースコード
以下サンプルソースコードになります。
※丸々コピペでコンパイルできます
//+------------------------------------------------------------------+
//| Ichimoku.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 A_SPREAD = 20;
input double Lots = 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,ea_order_entry_price=0; //ストップロスレート,利確レート,エントリーレート
//---
//新しい足ができた時だけやる
if(Time[0] != prevtime){
prevtime = Time[0];
}else{
return(0);
}
//***一目均衡表の値取得***//
double Tenkansen = iCustom(NULL,0,"Ichimoku",9,26,52,0,1);
double Kijunsen = iCustom(NULL,0,"Ichimoku",9,26,52,1,1);
double SenkouSpanA = iCustom(NULL,0,"Ichimoku",9,26,52,2,1);
double SenkouSpanB = iCustom(NULL,0,"Ichimoku",9,26,52,3,1);
double ChikouSpan = iCustom(NULL,0,"Ichimoku",9,26,52,4,27);
//***売買判断箇所***//
//△三役好転△
if(Tenkansen > Kijunsen && SenkouSpanA < iClose(NULL,0,1) && SenkouSpanB < iClose(NULL,0,1) && ChikouSpan > iHigh(NULL,0,27)){
orderPtn = 1;
}
//▼三役逆転▼
else if(Tenkansen < Kijunsen && SenkouSpanA > iClose(NULL,0,1) && SenkouSpanB > iClose(NULL,0,1) && ChikouSpan < iLow(NULL,0,27)){
orderPtn = 2;
}else{
orderPtn = 0;
}
//***決済判断箇所***//
total=OrdersTotal();
if(total == 1 ){
bool OrderKekka = OrderSelect(0,SELECT_BY_POS,MODE_TRADES);
if(OrderType() == OP_BUY && (orderPtn == 0 || orderPtn == 2)){
OrderKekka = funcOrder_Close();
}
if(OrderType() == OP_SELL && (orderPtn == 0 || orderPtn == 1)){
OrderKekka = funcOrder_Close();
}
}
//***エントリー箇所***//
else if(total == 0 && orderPtn > 0)
{
ea_order_stop_price = 0;
ea_order_good_price = 0;
//新規注文
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:成功 False:失敗
//|
//|
bool funcOrder_Send(int ea_order_entry_Type, double ea_order_stop_price, double ea_order_good_price,string orderComment,int ea_order_MagicNo)
{
int order_resend_num; // エントリー試行回数
int ea_ticket_res; // チケットNo
double ea_order_entry_price; // エントリーレート
color order_Color;
bool kekka;
kekka=false;
for( order_resend_num = 0; order_resend_num < 10; order_resend_num++ ) { // エントリー試行回数上限:10回
//スプレッドが1銭未満の場合のみ新規注文する(2銭未満にしたい場合は20にする)
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;
}
ea_ticket_res = OrderSend( // 新規エントリー注文
NULL, // 通貨ペア
ea_order_entry_Type, // オーダータイプ[OP_BUY / OP_SELL]
Lots, // ロット数
ea_order_entry_price, // オーダープライスレート
20, // スリッページ
ea_order_stop_price, // ストップレート
ea_order_good_price, // リミットレート
orderComment, // オーダーコメント
ea_order_MagicNo, // マジックナンバー
0, // オーダーリミット時間
order_Color // オーダーアイコンカラー
);
if ( ea_ticket_res == -1) {
Print("エントリー失敗 エラーNo=",GetLastError()," リトライ回数=",order_resend_num+1);
Sleep(5000); // msec待ち
RefreshRates(); // レート更新
} else { // 注文約定
Print("新規注文約定。 レート:",ea_order_entry_price," チケットNo=",ea_ticket_res," オーダーマジックNo=",ea_order_MagicNo);
Sleep(500); // 500msec待ち
kekka=true;
break;
}
}else{
Print("スプレッド拡大中(銭)=",MarketInfo(NULL,MODE_SPREAD) / 10," リトライ回数=",order_resend_num+1);
Sleep(5000); // msec待ち
RefreshRates(); // レート更新
}
}
return kekka;
}
//+------------------------------------------------------------------+
//|【関数】決済関数
//|
//|【引数】 なし
//|
//|【戻値】True:成功 False:失敗
//|
//|
bool funcOrder_Close()
{
bool kekka,OrderKekka;
int total,order_resend_num;
double ea_order_entry_price; // エントリーレート
color order_Color;
kekka=false;
for(order_resend_num = 0; order_resend_num < 100; order_resend_num++ ) {
if(MarketInfo(NULL,MODE_SPREAD) < A_SPREAD){
total=OrdersTotal();
if(total >0 && OrderSelect(0,SELECT_BY_POS,MODE_TRADES)==true){
if(OrderType() == OP_BUY){
ea_order_entry_price = Bid; // 現在の売値で決済
order_Color = clrLightBlue;
}else if(OrderType() == OP_SELL){
ea_order_entry_price = Ask; // 現在の買値で決済
order_Color = clrLightPink;
}
OrderKekka = OrderClose(OrderTicket(),OrderLots(),ea_order_entry_price,10,order_Color);
if(OrderKekka==false){
Print("決済失敗 エラーNo=",GetLastError()," リトライ回数=",order_resend_num+1);
RefreshRates();
Sleep(1000);
}else{
Print("決済注文約定。 レート=",ea_order_entry_price);
kekka=true;
break;
}
}
}else{
Print("スプレッド拡大中(銭)=",MarketInfo(NULL,MODE_SPREAD) / 10," リトライ回数=",order_resend_num+1);
Sleep(5000); // msec待ち
RefreshRates(); // レート更新
}
}
return kekka;
}
26本前の値が最新となりますので、26本目の値を今回は見るようにしています。
(遅行スパンなので当たり前ですが、一応今回のサンプルソースを作る前に気になったところでしたので・・・)
主な構文
iCustom()
【使用例】 iCustom(NULL,0,"Ichimoku",9,26,52,0,1)
今回も、おなじみiCustom()関数で一目均衡表の値を取得しています。
引数は以下の通りです。
- 通貨ペア(NULLで当該通貨)
- 時間軸(0で当該時間軸)
- インジケータ名称(一目均衡表を使う場合”Ichimoku”でOKです)
- 転換線の値です(デフォルト設定の9でOKです)
- 基準線の値です(デフォルト設定の26でOKです)
- 先行スパンBの値です(デフォルト設定の52でOKです)
- 取得する値(0:転換線 1:基準線 2:先行スパン1 3:先行スパン2 4:遅行スパン)
- バーシフト
サンプルソースから基本的に値を変更する事は無いと思います。
さいごに
以上、一目均衡表を使ったEAのサンプルソースでした。
今回は1時間足以外は微妙な感じでしたが、
・決済タイミングの見直し
等をおこなえば、プラス収支に持っていけるんではないかと思います。
※ MT4・EAが使えるFX会社のおすすめ
※ EAのサンプルソースを一覧表にまとめました
コメント
いつもお世話になっております。
コンパイルしたところ、88行目にエラーが発生しているとの事でコンパイルできない状態です。
エラーメッセージは、
「’OrderKekka’ – undeclared identifier」
となります。
何が原因なのでしょうか?
#property strictを宣言していると発生する感じでした。
OrderKekkaが宣言されていませんっていうエラーメッセージですが、別のif文内で宣言しているので、#property strictを宣言してないとコンパイル時にエラーになりませんでした。
『bool OrderKekka』をif文の外で宣言してあげると問題は解消されます!
ありがとうございます。
コンパイルできました!
一目均衡表を使用して裁量トレードしています。
私のトレードルールは簡単なので、EA を使おうと思って勉強しているのですが、実際にコード乗ってるの少ないので助かります。
ちなみに、一目均衡表の先行スパンと指数移動平均のゴールデンクロスでトレードするEAを作ろうとしているのですが、難易度高いのでしょうか?
うま太郎さん
一目均衡表の先行スパンと指数移動平均のゴールデンクロスでトレードするEAですが、iMA()関数で指数移動平均線の値を取得して比較するだけなので難易度は高くないですよ。