移動平均線のクロスでEA(自動売買システム)を作成する方法を解説!サンプルコードも!

ザフナーラボブログ

この記事では移動平均線のクロスでEA(自動売買システム)を作成する方法を解説いたします!

サンプルコードもありますので、MT4のEAを初めて作成するという初心者の方にもおすすめです。

移動平均線のクロスで売買するEA(2MA Cross EA.mq4)を具体例として、MetaTrader4(MT4)におけるEAの具体的な作成方法について解説します。

「2MA Cross EA.mq4」の具体的な売買ロジックは、以下のとおりです。

  • ゴールデン(デッド)クロスで買い(売り)エントリーする。
  • 買い(売り)ポジションはデッド(ゴールデン)クロスで決済する。
  • エントリー及び決済は、クロスが確定した後に初めて形成されるバーの始値で行う。
  • エントリー及び決済は成行注文で行う。
  • 保有ポジション数は1つ(ドテン売買)。

1.全体像

MT4でEAを作成するには、以下の手順に従ってプログラムを記述していくことになります。

  1. #property命令を記述する。
  2. 変数の宣言を行う。
  3. 関数の定義を行う。
  4. OnInit()関数内にEAの初期設定を記述する。
  5. OnTick()関数内に具体的な売買ロジックを記述する。

以下の完成ソースコードを見ながらこの記事を進めてください。

2MA-Crodss-EAのソースコードをダウンロード

2.#property命令の記述

「2MA Cross EA.mq4」においては、以下のように記述して、著作権と関連HPのURL等を指定しています。

サンプルコード


#property strict

#property copyright"詳解MT4"

#property link"https://mt4-traders.com"

#property命令の詳細については「こちら」を参照してください。

3.変数の宣言

⑴ 変数とは

変数とは、数値などを格納するためのメモリ領域に名前を付けたものです。

変数の詳細については「こちら」を参照してください。

⑵ 具体例

「2MA Cross EA.mq4」における変数の宣言に関する部分のコードについて解説します。

2MA-Crodss-EAのソースコードをダウンロード

ア 「//」とは

「//」とは、プログラムにコメント(注釈や説明など)を記述するために使用されるものです。

「//」が記述された行は、その行の文末までがコメントとして処理され、プログラムには一切影響を与えません。

 コメントを2行以上にわたって記述したい場合には、コメントにする部分を「/*」と「*/」で囲みます。

サンプルコード

//この部分がコメントとなる。
/*この部分が
    コメントとなる。*/

イ inputとは

「input」を付けて変数を宣言すると、当該変数をEAのパラメーターとして取り扱うことができるようになります。

具体的には、「input」を付けると、EAをチャートに適用した際に表示されるダイアログボックスにおける「パラメーターの入力」タブに、当該変数が表示されるようになります。

なお、上に示した具体例のように、「input」を付けて宣言した変数の後に、「//」を付けて任意の文言を記述すると、当該文言が表示されるようになります。

ウ 各変数の意味

「2MA Cross EA.mq4」において宣言した各変数の意味は、以下のとおりです。

  • Magic
    マジックナンバー(=EAを識別する整数値)を格納します。
  • FMA_Period
    短期移動平均線の計算期間を格納します。
  • SMA_Period
    長期移動平均線の計算期間を格納します。
  • MA_Mode
    使用する移動平均線の種類を示す整数値を格納します。
  • Applied_Price
    移動平均線の計算に使用する価格データの種類を示す整数値を格納します。
  • Lots
    取引するロットサイズを格納します。
    MT4では、通常、1ロットは10万通貨を意味します。
  • Slippage
    許容スリッページ数を格納します。
  • Comments
    エントリー注文に付加するコメントを格納します。
    コメントは、「ターミナルウィンドウ」の「取引」タブで確認することができます。
  • FMA_1
    1本前のバーの短期移動平均線の値を格納します。
  • FMA_2
    2本前のバーの短期移動平均線の値を格納します。
  • SMA_1
    1本前のバーの長期移動平均線の値を格納します。
  • SMA_2
    2本前のバーの長期移動平均線の値を格納します。
  • Ticket
    エントリー注文が約定した際に、ポジションに付される整数値(=チケット番号)を格納します。
  • Adjusted_Slippage
    AdjustSlippage()関数によって調整された許容スリッページ数を格納します。
  • Bar_Time
    バーの形成開始時刻を格納します。
  • Closed
    決済注文が約定したか否かの結果を格納します。
    約定した場合は「true」を、約定しなかった場合は「false」を格納します。

4.関数の定義

⑴ 関数とは

関数とは、一定の処理を実行する流れをひとまとめにしたものです。

関数の詳細については「こちら」を参照してください。

⑶ 具体例

「2MA Cross EA.mq4」においては、以下のように記述して、AdjustSlippage()関数を定義しています。

サンプルコード

//関数の定義
int AdjustSlippage(string Currency,int Slippage_Pips)
{
 int Calculated_Slippage = 0;
 
 int Symbol_Digits = (int)MarketInfo(Currency,MODE_DIGITS);
 
 if(Symbol_Digits == 2 || Symbol_Digits == 4)
   {
    Calculated_Slippage = Slippage_Pips;
   }
 else if(Symbol_Digits == 3 || Symbol_Digits == 5)
        {
         Calculated_Slippage = Slippage_Pips * 10;
        }
        
 return(Calculated_Slippage);
}

5.初期設定の記述

⑴ OnInit()とは

OnInit()とは、MQL4であらかじめ定義されている関数で、EAをチャートに適用した際に、1度だけ実行されるものです。

OnInit()関数は、以下のように記述して使用します。

サンプルコード

int OnInit()
{
  一度だけ実行される処理内容
  return(INIT_SUCCEEDED);
}

OnInit()関数は、EAをチャートに適用した後、最初に一度だけ実行されるものなので、同関数内には、EAの初期設定など、一度だけ実行されれば足りる事項を記述します。

 なお、OnInit()関数の使用は任意なので、これを必要としない場合には、記述する必要はありません。

⑵ 具体例

「2MA Cross EA.mq4」においては、許容スリッページ数の調整を行うAdjustSlippage()関数を使用しますが、同関数は、EAをチャートに適用した際に、最初に初期設定として1度だけ実行されれば足りるものなので、OnInit()関数内に以下のように記述します。

サンプルコード


int OnInit()
{
  Adjusted_Slippage =
  AdjustSlippage(Symbol(),Slippage);

  return(INIT_SCCEEDED);
}

6.具体的な売買ロジックの記述

⑴ OnTick()とは

OnTick()とは、MQL4であらかじめ定義されている関数で、ティックごとに実行されるものです。

OnTick()関数は、ティックごとに実行されるものなので、同関数内には、具体的な売買ロジックを記述します。

OnTick()関数は、以下のように記述して使用します。

サンプルコード

void OnTick()
{
   具体的な売買ロジック
}

⑵ EAを始値のみで実行させる

「2MA Cross EA.mq4」は、ゴールデンクロス又はデッドクロスが完成してから、その直後のバーの始値でエントリー又は決済を行います。

したがって、「2MA Cross EA.mq4」は、始値の時点でのみ稼働すれば足りるということになります。

そこで、「2MACross EA.mq4」では、以下のように記述して、EAを始値のみで稼働させるようにしています。

サンプルコード


//始値か否かのチェック
if(Bar_Time == Time[0])
  {
   return;
  }
else if(Bar_Time != Time[0])
       {
        Bar_Time = Time[0];
       }

ア Time[]とは

Time[]とは、各バーの形成開始時刻を格納しているdatetime型の配列です。

  • Time[]の詳細については「こちら」を参照してください。
  • 配列の詳細については「こちら」を参照してください。

イ 具体例の解釈

2014年4月1日00:00:00にEAの稼働を開始した場合を具体例として、上記プログラムがどのように動作して、EAが始値のみで稼働されることになるのかを解説します。

  1. EAの稼働開始時点(1ティック目)
    ・Bar_Timeには「0」が格納されている。
    ・Time[0]には「2014/4/1/00:00:00」が格納されている。
    ・「Bar_Time≠Time[0]」
    Bar_Timeに「2014/4/1/00:00:00」が代入されたうえで、売買ロジックが実行される。
  2. EA稼働後2ティック目から「2014/4/1/01:00:00」まで
    ・Bar_Timeには「2014/4/1/00:00:00」が格納されている。
    ・Time[0]には「2014/4/1/00:00:00」が格納されている。
    ・「Bar_Time=Time[0]」。
    retrun;が実行され、売買ロジックに至る前にプログラムは終了する。
  3. EAが稼働してから2本目のバーが形成される時点
    ・Bar_Timeには「2014/4/1/00:00:00」が格納されている。
    ・Time[0]には「2014/4/1/01:00:00」が格納されている。
    ・「Bar_Time≠Time[0]」
    Bar_Timeに「2014/4/1/01:00:00」が代入されたうえで、売買ロジックが実行される。
  4. 以降は、上記2.~3.のロジックが繰り返されることになるので、EAは始値の時点でのみ、売買ロジックが実行されることになる。

⑶ インジケーターの値を計算する

「2MA Cross EA.mq4」のように、売買の条件にインジケーターの値を使うEAの場合には、売買ロジックに入る前に、インジケーターの値を計算するコードを記述しておく必要があります。

「2MA Cross EA.mq4」においては、以下のように記述して、インジケーター(移動平均線)の値を計算しています。

サンプルコード



//インジケーターの値の計算
FMA_1 = iMA(Symbol(),0,FMA_Period,0,MA_Mode,
            Applied_Price,1);
FMA_1 = NormalizeDouble(FMA_1,Digits);
FMA_2 = iMA(Symbol(),0,FMA_Period,0,MA_Mode,
            Applied_Price,2);
FMA_2 = NormalizeDouble(FMA_2,Digits);
SMA_1 = iMA(Symbol(),0,SMA_Period,0,MA_Mode,
            Applied_Price,1);
SMA_1 = NormalizeDouble(SMA_1,Digits);
SMA_2 = iMA(Symbol(),0,SMA_Period,0,MA_Mode,
            Applied_Price,2);
SMA_2 = NormalizeDouble(SMA_2,Digits);

ア iMA()とは

iMA()とは、MQL4であらかじめ定義されている関数で、移動平均線の値を算出するものです。

イ NormalizeDouble()とは

NormalizeDouble()とは、MQL4であらかじめ定義されている関数で、特定の値(浮動小数点)を指定した小数点以下の桁数で四捨五入するものです。

⑷ 保有ポジションを決済する

「2MA Cross EA.mq4」では、エントリーするロジックよりも、保有ポジションを決済するロジックを先に記述しています。

これは、以下の理由によります。

  1. リスク管理
    FX取引におけるレート変動によるリスクは、ポジションを保有し続けることによって生じること、及び、プログラムはコードを記述した順に実行されることから、エントリー処理よりもクローズ処理を先に記述することによって、その逆の場合よりも、速やかに保有ポジションを決済して、リスクを回避することができます。
  2. 速やかにエントリーする
    「2MA Cross EA.mq4」のように、ドテン売買を行うシステムの場合、ポジションを保有している限り、新たにエントリーすることはできないので、速やかなエントリーを可能とするためには、エントリー処理よりもクローズ処理を先に記述しておくことが必要となります。

ア 決済条件

「2MA Cross EA.mq4 」における決済条件を記述したコードの解釈を示すと、以下のようになります。

  • 買いポジションの決済条件
    2本前のバーの短期移動平均線の値が2本前のバーの長期移動平均線の値以上
    かつ
    1本前のバーの短期移動平均線の値が1本前のバーの長期移動平均線の値よりも小さい
    かつ
    チケット番号が正(=ポジションを保有している。)
  • 売りポジションの決済条件
    2本前のバーの短期移動平均線の値が2本前のバーの長期移動平均線の値以下
    かつ
    1本前のバーの短期移動平均線の値が1本前のバーの長期移動平均線の値よりも大きい
    かつ
    チケット番号が正(=ポジションを保有している。)

イ OrderClose()とは

OrderClose()とは、MQL4であらかじめ定義されている関数で、保有ポジションを決済する注文を出すものです。

OrderClose()関数の詳細については「こちら」を参照してください。

ウ チケット番号を初期化する

OrderClose()関数によって正常にポジションが決済された場合には、保有ポジションに付されていたチケット番号を「0」に初期化します。

⑸ エントリーする

ア エントリー条件

「2MA Cross EA.mq4」におけるエントリー条件を記述したコードの解釈を示すと、以下のようになります。

  • 買いエントリーの条件
    2本前の短期移動平均線の値が2本前の長期移動平均線の値以下
    かつ
    1本前の短期移動平均線の値が1本前の長期移動平均線の値よりも大きい
    かつ
    ポジションを保有していない
  • 売りエントリーの条件
    2本前の短期移動平均線の値が2本前の長期移動平均線の値以上
    かつ
    1本前の短期移動平均線の値が1本前の長期移動平均線の値よりも小さい
    かつ
    ポジションを保有していない

なお、OrdersTotal()とは、MQL4であらかじめ定義されている関数で、現に保有しているポジションと、待機注文の合計数を返すものです。

OrdersTotal()関数の詳細については「こちら」を参照してください。

イ OrderSend()とは

OrderSend()とは、MQL4であらかじめ定義されている関数で、注文を出すために使用するものです。

OrderSend()関数の詳細については「こちら」を参照してください。