MT4言語入門|窓埋めEAの超簡単な自作方法

この記事は約16分で読めます。

MT4言語入門|窓埋めEAの超簡単な自作方法

せっかくMT4(MetaTrader4)を利用するなら、オリジナルのEA(Expert Advisor)やインジケーターを自作してみませんか?

 

今回は、MQL4言語入門として窓埋めEAの自作方法を解説します。

もちろん、いつもどおりの超簡単な自作方法です。すでに出来上がっているサンプルEAのソースコードの一部を書き換えるだけですから。

 

最後あたりでEAの完成品を無料ダウンロードできます。ぜひ読んでいってください。

 

スポンサーリンク

窓埋めとは?

FXでは、土日に市場が閉まることから、前週金曜の終値と月曜朝の始値にギャップ(窓)が開くことがあります。

そして、この窓はだいたい短時間で埋まるのが相場のパターンなので、この窓を埋めようとする相場のパターンを利用してトレードする手法が窓埋めです。

つまり、月曜の朝、市場オープン時にチャートを確認し、もし窓が開いていれば、窓を埋める方向にロングまたはショートの注文を入れるのです。

「窓開け」と呼ばれることもあります。

 

スポンサーリンク

窓埋めとMT4

窓埋めとMT4のシステムトレードは相性がいいです。

まず、窓埋めは売り買いのタイミングがハッキリしているので、簡単にプログラムが組めます

また、私たちには仕事や学校などの生活があるので、毎週毎週、月曜朝にチャートの前で待機しておくというのはキツイです。

その点、MT4なら、日曜の晩にPCのMT4を起ち上げておくだけでOKです。あとはMT4が自動売買してくれるので、私たちは普段どおりに生活できます。

 

あと、相場のパターンとは言っても、窓が開けば即エントリーする戦略だけで勝ち続けることは、実際のところ難しいです(バックテストで確認済み)。

というのも、窓があまりに小さい場合は投資効率が悪すぎるし、窓があまりに大きい場合は埋まる可能性が低いです。また、窓を途中までしか埋めずに反転することもあります。

やはり、新規注文(エントリー)や決裁(エグジット)に何か工夫が必要ですが、こういうときにMT4は便利です

自作EAなら、エントリー時にだまし対策を施すことも、適切な決裁タイミングを見逃さないよう複数の決済ルールを組み合わせることも自由自在です。

さらに、それら工夫の有用性をバックテストで確認できます。

 

スポンサーリンク

窓埋めEA『GapHunter.mq4』の内容

EAの内容は、以下のとおりです。

せっかく自作するのですから、単純な窓埋めEAではなく、エントリーやエグジットに私なりの工夫を施しています(^^)v

  • 基本は、月曜オープン時に 前週金曜の終値>月曜朝の始値 なら新規買い注文を入れ、逆なら新規売り注文を入れる。
  • ただし、窓が大きすぎたり小さすぎればエントリーを見送る。
  • 月曜オープン直後は窓を拡げる方向に動くことが多いので、さらに利ザヤ(利益)を稼ぐ。すなわち、エントリー条件を満たす窓が開いた場合でも、すぐにエントリーするのではなく、さらに数pips拡がるのを待つ。
  • 決裁タイミングを逃さぬよう、3種類の撤退ルールを用意した。すなわち、逆指値(ストップロス)、トレーリングストップ、エントリー後に一定時間経過したら決裁する時間ストップを組み合わせた。

 

スポンサーリンク

MetaEditor の起動

それでは、サンプルコード「MACD Sample.mq4」のソースコードを書き換えて、窓埋めEAを作っていきます。

MT4の「メタクォーツ言語エディタ」をクリックします。

メタエディター起動

 

MeTaEditorが立ち上がったら、画面左側の「Navigater」内のツリーから「Experts」をダブルクリックします。

「Experts」のツリーから「MACD Sample.mq4」をダブルクリックすると、ソースコードが開きます。

MACDサンプル起動

 

スポンサーリンク

オリジナルEA『GapHunter.mq4』の自作

最初に、名前をつけてファイルを保存します。

「MACD Sample.mq4」が開いている状態で、「File」→「Save As…」 をクリックします。

MAC-STOC保存

 

ファイル名を「GapHunter.mq4」と打ち込んで保存します。

それでは、いよいよソースコードを書き換えていきます。

 

パラメーターの変更

カーソルを10行目に持って行きます。

ここでは、売買ロットやテクニカルインジケーターに関するパラメーターが記述されています。これらの数値は、MT4上でユーザーが自由に変更できます。

【変更前】

input double TakeProfit    =50;
input double Lots          =0.1;
input double TrailingStop  =30;
input double MACDOpenLevel =3;
input double MACDCloseLevel=2;
input int    MATrendPeriod =26;

【変更後】

input double Lots            =0.1;
input double TrailingStop    =500;
input double StopLoss        =400;
input double MinGap          =70;
input double MaxGap          =1200;
input double OverGap         =40;
input int ExitBar            =8;
double StopBar;

TrailingStopの値を変更し、不要なパラメーターを削除しました。

新たにストップロス(逆指値)を設定(変数として宣言)し、初期値を400ポイントにする旨を記述しました。

MinGapはエントリーする窓の最小値で、初期値は70ポイントです。

MaxGapはエントリーする窓の最大値で、初期値は1200ポイントです。

上でも書きましたが、窓が小さすぎる場合や大きすぎる場合にはエントリーしません。

ExitBarは時間ストップのパラメーターで、初期値では窓が埋まっていなくても8時間経過で決裁します。

OverGapは窓の大きさ+αの利ザヤで、初期値は40ポイントです。

 

テクニカルインジケーター変数の宣言の変更

カーソルを下に移動させます。

ここでは、テクニカルインジケーターの変数の宣言が記述されています。

【変更前】

void OnTick(void)
{
double MacdCurrent,MacdPrevious;
double SignalCurrent,SignalPrevious;
double MaCurrent,MaPrevious;
int    cnt,ticket,total;

【変更後】

void OnTick(void)
{
double LastDayClose,NewDayOpen,UpGap,DnGap,EntryGap;
int    cnt,ticket,total;

MACDと移動平均線の変数の宣言を削除し、新たに窓埋めの変数の宣言を記述しました。

 

最低利食い幅の記述の削除

カーソルを下に移動させます。

指値(TakeProfit)が10ポイント以下の場合はエントリーしない旨の記述を削除しました。

別にエントリーする窓の最小値を定めているので不要だからです。

if(TakeProfit<10)
{
Print("TakeProfit less than 10");
return;
}

 

テクニカルインジケーター関数の変更

カーソルを下に移動させます。

ここでは、先ほど宣言した変数に、テクニカルインジケーター関数の値を代入する式が記述されています。

【変更前】

//--- to simplify the coding and speed up access data are put into internal variables
MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0);
SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1);
MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0);
MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);

【変更後】

//--- to simplify the coding and speed up access data are put into internal variables
if(DayOfWeek()==1 && Hour()==0)
{
LastDayClose = iClose(NULL,PERIOD_H1,1);
NewDayOpen = iOpen(NULL,PERIOD_H1,0);
}
UpGap = NewDayOpen-LastDayClose;
DnGap = LastDayClose-NewDayOpen; 
EntryGap = (MinGap+OverGap)*Point;

MACDと移動平均線の式を削除し、代わりに窓埋めの式を記述しました。

まず、月曜(DayOfWeek()==1)の朝のオープン時(Hour()==0)であることを確認しています。

LastDayCloseには、前週の金曜の終値が入ります。

NewDayOpenには、月曜朝の始値が入ります。

UpGapには、月曜始値>金曜終値 である場合の窓のサイズ(ポイント)が入ります。

DnGapには、金曜終値>月曜始値 である場合の窓のサイズ(ポイント)が入ります。

EntryGapには、最低でも確保すべき利ザヤ(ポイント)が入ります。

 

買い条件と買い注文の変更

カーソルを下に移動させます。

ここでは、買い条件と買い注文について記述しています。

【変更前】

//--- check for long position (BUY) possibility
if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious && 
   MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious)
{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order opened :",OrderOpenPrice());
}

【変更後】

//--- check for long position (BUY) possibility
if(UpGap<0 && DnGap>MinGap*Point && DnGap<MaxGap*Point) { if(LastDayClose>iHigh(NULL,PERIOD_H1,0) && Ask<(LastDayClose-EntryGap))
{
ticket = OrderSend(Symbol(),OP_BUY,Lots,Ask,3,Ask-StopLoss*Point,LastDayClose,"gap hunter",16384,0,Green);
if(ticket>0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("BUY order opened :",OrderOpenPrice());
StopBar=iBars(NULL,PERIOD_H1);
}

買い条件をすべて書き換えます。

一つ目のif文で、金曜終値>月曜始値 であり、かつ、窓のサイズ条件(最小値と最大値)を満たしているか確認しています。

二つ目のif文で、まだ窓を埋めておらず、かつ、最低利ザヤを確保できるかを確認しています。

これらの条件を満たせば買い注文命令(OrderSend)を出します。このとき、指値(LastDayClose)と逆指値(Ask-StopLoss*Point)も指定しています。

StopBarには、現在のバー数(iBars)が入ります。決裁条件で使います。

 

売り条件と売り注文の変更

カーソルを下に移動させます。

ここでは、売り条件と売り注文について記述しています。

【変更前】

//--- check for short position (SELL) possibility
if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious &&
   MacdCurrent>(MACDOpenLevel*Point) && MaCurrent<MaPrevious)
{
ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,Bid-TakeProfit*Point,"macd sample",16384,0,Red);
if(ticket > 0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("SELL order opened :",OrderOpenPrice());
}

【変更後】

//--- check for short position (SELL) possibility
if(DnGap<0 && UpGap>MinGap*Point && UpGap<MaxGap*Point)
{
if(LastDayClose<iLow(NULL,PERIOD_H1,0) && Bid>(LastDayClose+EntryGap))
{
ticket = OrderSend(Symbol(),OP_SELL,Lots,Bid,3,Bid+StopLoss*Point,LastDayClose,"",16384,0,Red);
if(ticket > 0)
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
Print("SELL order opened :",OrderOpenPrice());
StopBar=iBars(NULL,PERIOD_H1);
}

売り条件をすべて書き換えます。

一つ目のif文で、月曜始値>金曜終値 であり、かつ、窓のサイズ条件(最小値と最大値)を満たしているか確認しています。

二つ目のif文で、まだ窓を埋めておらず、かつ、最低利ザヤを確保できるかを確認しています。

これらの条件を満たせば売り注文命令(OrderSend)を出します。このとき、指値(LastDayClose)と逆指値(Bid+StopLoss*Point)も指定しています。

StopBarには、現在のバー数(iBars)が入ります。決裁条件で使います。

 

買い注文の決済条件の変更

カーソルを下に移動させます。

ここでは、買い注文の決済条件について記述しています。

【変更前】

//--- long position is opened
if(OrderType()==OP_BUY)
{
//--- should it be closed?
if(MacdCurrent>0 && MacdCurrentSignalPrevious && 
MacdCurrent>(MACDCloseLevel*Point))
{

【変更後】

//--- long position is opened
if(OrderType()==OP_BUY)
{
//--- should it be closed?
if(StopBar+ExitBar<iBars(NULL,PERIOD_H1))
{

時間ストップの決済条件に書き換えます。

現在のバー(iBars)が時間ストップ(初期設定ではエントリー後8時間)に達しているかを確認しています。

 

売り注文の決済条件の変更

カーソルを下に移動させます。

ここでは、売り注文の決済条件について記述しています。

【変更前】

else // go to short position
{
//--- should it be closed?
if(MacdCurrent<0 && MacdCurrent>SignalCurrent && 
 MacdPrevious(MACDCloseLevel*Point))
{

【変更後】

else // go to short position
{
//--- should it be closed?
if(StopBar+ExitBar<iBars(NULL,PERIOD_H1))
{

時間ストップの決済条件に書き換えます。

現在のバー(iBars)が時間ストップ(初期設定ではエントリー後8時間)に達しているかを確認しています。

 

ソースコードの書き換えは以上です。

一応、記事の最後あたりに、完成品をダウンロードできるよう置いておきます。

 

スポンサーリンク

ソースコードをコンパイルする

記述し終わったら、「Compile」をクリックします。

記述ミスがなければ、Destrictionに、「0 error(s), 0 warning(s)」と表示されます。

MAC-STOCのコンパイル

 

コンパイルとは、プログラムのソースコードをコンピューターが実行可能な機械語に翻訳することです。

ソースコードに記述ミスがあれば、エラーとなります。

エラーがでた場合は、記述を修正して再びコンパイルしましょう。

 

以下は、よくあるエラーの例です。気を付けましょう。

 

  • 全角で記述している(ソースコードはすべて半角で記述します)
  • 変数の型(”int”や”double”など)が違う
  • カッコ(” { ” や ” } “)が足りない(多い)
  • ” ; ” が抜けている

 

スポンサーリンク

バックテスト

せっかくオリジナルEAが完成したのですから、バックテストしてみましょう。

バックテストのやり方は別記事にまとめています。

 

 

実際にバックテストを行った結果を別記事にまとめています。

なお、窓埋めEAは、移動平均線などでテクニカル分析してるわけではないので、バックテストは5分足でやっても日足でやっても結果は同じ(はず)です

 

 

スポンサーリンク

まとめ|自作EA無料配布

今回は、MQL4言語入門として、窓埋めEAの超簡単な自作方法を解説しました。

もちろん、すでに出来上がっているサンプルEAのソースコードの一部を書き換えるだけの、いつもどおりの超簡単な自作方法です。

思った以上に簡単だったのではないでしょうか?

ぜひあなたの勝てるEA作りの参考にしてください。

 

今回の完成品はこちらからダウンロードできます。
本EAは、あくまでMQL4言語の学習用に無料配布するものです。なので、再配布はやめてください。もし、当サイトを宣伝して頂けたり、下のバナーから『XMTrading』の口座を開設していただけると、みなさんに役立つサイト作りをもっともっと頑張れます(*^▽^*)
タイトルとURLをコピーしました