今回は、MT4のEAサンプルソース(FX用)を公開します。
トレードに使うテクニカル分析はエンベロープ(Envelopes)で、順張りエントリーをしています。
はじめに
エンベロープは移動平均線のほぼ延長線のインジケータなので、とてもシンプルです。移動平均線からの離れ具合を確認できるので、初心者向けオススメのインジケータとなっています。
今回、以下では順張り目線でエントリーしていくサンプルを載せています。
EAの仕様
それでは、今回のソースコードのエントリー/決済/パラメータ設定についての仕様を説明します。
エントリータイミング
ロングエントリー
エンベロープ(上線)の値よりローソク足の終値が上だった場合、ロングエントリーします。
今回は、シンプルにこの条件のみで判断しています。
ショートエントリー
エンベロープ(下線)の値よりローソク足の終値が下だった場合、ショートエントリーします。
今回は、シンプルにこの条件のみで判断しています。
エントリー例
青赤の実線(エントリー用エンベロープ)の上抜けでロングエントリー、下抜けでショートエントリーしています。
あと、後述しますが点線(決済用エンベロープ)を超えて戻ると決済する感じです。
決済タイミング
今回は、エントリー用エンベロープの値の他に、決済用エンベロープの値を設けています。エントリー用エンベロープの値よりも、決済用エンベロープの値の方を小さくしています。
ロング中
決済用エンベロープ(上線)の値よりローソク足の終値が下だった場合、ロングポジションを決済します。
ショート中
決済用エンベロープ(下線)の値よりローソク足の終値が上だった場合、ショートポジションを決済します。
その他の仕様
設定値は以下の通りです。
- MA_Atai = 20 ⇒ ベースとなる移動平均線の値です
- MA_Syubetu = 1 ⇒ ベースとなる移動平均線の種別です(1でEMA)
- MA_HIdou = 1 ⇒ ベースとなる移動平均線の種別の表示移動です
- Tekiyou = 0 ⇒ 適用価格です(0でクローズ値)
- Hensa = 0.34 ⇒ エントリー用エンベロープ値の偏差です
- Hensa_uri = 0.08 ⇒ 決済用エンベロープ値の偏差です
- A_SPREAD = 20 ⇒ エントリー及び決済時に許容するスプレッドの値です(20 = 2pips)
- Lots = 0.01 ⇒ ロット数です(0.01=1000通貨)
- SL = 2000 ⇒ ストップロスまでのポイントです(1000=100pips)
既にポジションがある場合は追加でエントリーしません。
新しい足(バー)が出来た際に1度だけ処理を行います。※1時間足の場合だと1時間に1回処理する
EAレポート結果
2012年~2021年の期間の1時間足でバックテスト確認してみました。エンベロープ等の値は最適化で良い値を選んだのですが、いつものように2005年からで確認すると中々良いプロフィットファクターになりませんでした。
約9年間で総取引数が1200近くなので、年間130ちょっとの取引です。単純にエントリー時のみエンベロープ値を使うだけだと中々良い感じにならなかったので、決済時にもエンベロープ値を使う感じにしましたが、体感的にはめちゃくちゃ有効っていう感じでもないです。
ダウンロード
上記のEAファイルになります。
“エンベロープEA” をダウンロード 6_EnveLopes.ex4 – 2142 回のダウンロード – 14.98 KBソースコード
以下サンプルソースコードになります。
※丸々コピペでコンパイルできます
//+------------------------------------------------------------------+
//| ENVELOPES_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 MA_Atai = 20;
input int MA_Syubetu = 1; // 0 = sma, 1 = ema, 2 = smma, 3 = lwma
input int MA_HIdou = 1;
input int Tekiyou = 0; // 0 = Close, 1 = Open, 2 = High, 3 = Low
input double Hensa = 0.34;
input double Hensa_uri = 0.08;
input int A_SPREAD = 20;
input double Lots = 0.01;
input int SL = 2000;
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 ENV_ATAI_U = iEnvelopes(NULL,0,MA_Atai,MA_Syubetu,MA_HIdou,Tekiyou,Hensa,MODE_UPPER,MA_HIdou);
double ENV_ATAI_M = iEnvelopes(NULL,0,MA_Atai,MA_Syubetu,MA_HIdou,Tekiyou,Hensa,MODE_MAIN,MA_HIdou);
double ENV_ATAI_L = iEnvelopes(NULL,0,MA_Atai,MA_Syubetu,MA_HIdou,Tekiyou,Hensa,MODE_LOWER,MA_HIdou);
//----エンベロープの決済判断値を取得
double ENV_ATAI_UK = iEnvelopes(NULL,0,MA_Atai,MA_Syubetu,MA_HIdou+1,Tekiyou,Hensa_uri,MODE_UPPER,MA_HIdou);
double ENV_ATAI_LK = iEnvelopes(NULL,0,MA_Atai,MA_Syubetu,MA_HIdou+1,Tekiyou,Hensa_uri,MODE_LOWER,MA_HIdou);
//ローソク足のクローズ値情報を取得しておく
double rosokuValueClose = iClose(NULL, 0, MA_HIdou);
//エンベロープの値よりローソク足の終値が上だった場合、ロング
if(ENV_ATAI_U < rosokuValueClose)
{
orderPtn=1;
}
//エンベロープの値よりローソク足の終値が上だった場合、ショート
else if(ENV_ATAI_L > rosokuValueClose)
{
orderPtn=2;
}
else
{
orderPtn=0;
}
//***売買判断箇所***//
OrderKekka = OrderSelect(0,SELECT_BY_POS,MODE_TRADES);
//エンベロープの決済判断値よりローソク足の終値が下だった場合、決済(ロング時)
if(OrderType() == OP_BUY && ENV_ATAI_UK > rosokuValueClose){
OrderKekka = funcOrder_Close();
}
//エンベロープの決済判断値よりローソク足の終値が上だった場合、決済(ショート時)
else if(OrderType() == OP_SELL && ENV_ATAI_LK < rosokuValueClose){
OrderKekka = funcOrder_Close();
}
//***決済判断箇所***//
total=OrdersTotal();
if(total == 0 && orderPtn > 0)
{
if(orderPtn == 1)
{
ea_order_stop_price = Ask - SL * Point;
ea_order_good_price = Ask + SL * Point;
}
else if(orderPtn == 2)
{
ea_order_stop_price = Bid + SL * Point;
ea_order_good_price = Bid - SL * 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;
}
//+------------------------------------------------------------------+
//|【関数】決済関数
//|
//|【引数】 なし
//|
//|【戻値】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;
}
主な構文
iEnvelopes()
【使用例】 double ENV_ATAI_L = iEnvelopes(NULL, 0, 21, 1, 1, PRICE_CLOSE, 0.2,MODE_LOWER, 0);
今回は、エンベロープの値を取得できるiEnvelopes()関数を使っています。
引数は以下の通りです。
- 引数1・・・通貨ペアです(NULLでチャートの通貨になります)
- 引数2・・・時間軸です(0でチャートの時間軸になります)
- 引数3・・・ベースとなる移動平均線の値です(20で20移動平均線、25で25移動平均線になります)
- 引数4・・・ベースとなる移動平均線の種別です(0 = sma, 1 = ema, 2 = smma, 3 = lwma)
- 引数5・・・ベースとなる移動平均線の種別の表示移動です
- 引数6・・・適用価格です(PRICE_CLOSEでクローズ値)
- 引数7・・・偏差です
- 引数8・・・モードです(MODE_MAIN:中心線, MODE_UPPER:上線, MODE_LOWER:下線)
- 引数9・・・バーシフトです(0で現在の値、1で1つ前ーのバーの時の値です)
基本的に、3~8を触るような設定ですね!3~8の設定はMT4のEnvelopes設定画面上で見るとイメージしやすいです。
4:種別(移動平均線)は、以下4種類です。
- 単純移動平均線:MODE_SMA 0
- 指数移動平均線:MODE_EMA 1
- 平滑移動平均線:MODE_SMMA 2
- 線形加重移動平均線:MODE_LWMA 3
6:適用価格は、9種類ありますが主に使うのは以下4種類だと思います。
- 終値:PRICE_CLOSE 0
- 始値:PRICE_OPEN 1
- 高値:PRICE_HIGH 2
- 安値:PRICE_LOW 3
8:バーシフトは過去のEnvelopes値をとりたい場合変更します(0:最新バーの位置、1:1つ前のバーの位置)
さいごに
以上、エンベロープを使ったEAのサンプルソースでした。
今回は順張りEAとなりましたが、逆張りでもまた試してみたいなと思います。
※ EAのサンプルソースを一覧表にまとめました
※オンラインレッスンやってます
コメント