この記事では移動平均線のクロスでEA(自動売買システム)を作成する方法を解説いたします!
サンプルコードもありますので、MT4のEAを初めて作成するという初心者の方にもおすすめです。
移動平均線のクロスで売買するEA(2MA Cross EA.mq4)を具体例として、MetaTrader4(MT4)におけるEAの具体的な作成方法について解説します。
「2MA Cross EA.mq4」の具体的な売買ロジックは、以下のとおりです。
- ゴールデン(デッド)クロスで買い(売り)エントリーする。
- 買い(売り)ポジションはデッド(ゴールデン)クロスで決済する。
- エントリー及び決済は、クロスが確定した後に初めて形成されるバーの始値で行う。
- エントリー及び決済は成行注文で行う。
- 保有ポジション数は1つ(ドテン売買)。
1.全体像
MT4でEAを作成するには、以下の手順に従ってプログラムを記述していくことになります。
- #property命令を記述する。
- 変数の宣言を行う。
- 関数の定義を行う。
- OnInit()関数内にEAの初期設定を記述する。
- OnTick()関数内に具体的な売買ロジックを記述する。
以下の完成ソースコードを見ながらこの記事を進めてください。
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」における変数の宣言に関する部分のコードについて解説します。
ア 「//」とは
「//」とは、プログラムにコメント(注釈や説明など)を記述するために使用されるものです。
「//」が記述された行は、その行の文末までがコメントとして処理され、プログラムには一切影響を与えません。
コメントを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);
}
- AdjustSlippage()関数の詳細については「こちら」を参照してください。
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型の配列です。
イ 具体例の解釈
2014年4月1日00:00:00にEAの稼働を開始した場合を具体例として、上記プログラムがどのように動作して、EAが始値のみで稼働されることになるのかを解説します。
- 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」が代入されたうえで、売買ロジックが実行される。 - 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;が実行され、売買ロジックに至る前にプログラムは終了する。 - 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」が代入されたうえで、売買ロジックが実行される。 - 以降は、上記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であらかじめ定義されている関数で、特定の値(浮動小数点)を指定した小数点以下の桁数で四捨五入するものです。
- NormalizeDouble()関数の詳細については「こちら」を参照してください。
⑷ 保有ポジションを決済する
「2MA Cross EA.mq4」では、エントリーするロジックよりも、保有ポジションを決済するロジックを先に記述しています。
これは、以下の理由によります。
- リスク管理
FX取引におけるレート変動によるリスクは、ポジションを保有し続けることによって生じること、及び、プログラムはコードを記述した順に実行されることから、エントリー処理よりもクローズ処理を先に記述することによって、その逆の場合よりも、速やかに保有ポジションを決済して、リスクを回避することができます。 - 速やかにエントリーする
「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()関数の詳細については「こちら」を参照してください。