『新メタトレ入門本』EAのサンプルプログラム
『新MT4対応 FXメタトレーダープログラミング入門』(新メタトレ入門本)連動企画です。
今回は、本書の第4章「エキスパートアドバイザー(EA)のプログラミング」「4-4 EAのサンプルプログラム」についてです。
【目次】
第1章 メタトレーダーの紹介
第2章 スクリプトのプログラミング
第3章 カスタム指標のプログラミング
第4章 エキスパートアドバイザー(EA)のプログラミング
4-1 新規ファイルの作成
4-2 EAの基本プログラム
4-3 ストラテジーテスターによるEAの動作確認
4-4 EAのサンプルプログラム
4-5 EAのデバッグ
4-6 ストラテジーテスターによるEAの最適化
4-7 EAの自動売買のためのプログラミング
本書アップデート情報
このセクションでは、本書内容のアップデートはありません。
関連するMT5情報
このセクションでは、いくつかのパターンのEAのサンプルプログラムを紹介しています。ただし、MT5で動作させるには、コードを修正する必要があります。修正の必要な箇所は、「EAの基本プログラム」の記事で示したとおりです。
ここでは、修正するポイントのみを簡単に説明しておきます。
移動平均を使った順張りEA
サンプルプログラムex2_ea.mq4では、移動平均線を2本利用します。どちらもiMA()を使って作成しますが、期間が異なるので、別々の指標ハンドルとして指標の初期化を行います。
指標用配列も二つ使うので、それぞれ時系列配列に設定しておきます。
int hFastMA, hSlowMA; //移動平均の指標ハンドル
double BufFastMA[], BufSlowMA[]; //移動平均用配列
//初期化関数
int OnInit()
{
//テクニカル指標の初期化
hFastMA = iMA(_Symbol, 0, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
hSlowMA = iMA(_Symbol, 0, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
//時系列配列に設定
ArraySetAsSeries(BufFastMA, true);
ArraySetAsSeries(BufSlowMA, true);
return(INIT_SUCCEEDED);
}
また、1本前と2本前の指標値が必要なので、各指標ハンドルを使って3個の指標値を配列にコピーし、対応する変数に代入します。
//ティック時実行関数
void OnTick()
{
CopyBuffer(hFastMA, 0, 0, 3, BufFastMA);
CopyBuffer(hSlowMA, 0, 0, 3, BufSlowMA);
//1本前の移動平均
double FastMA1 = BufFastMA[1];
double SlowMA1 = BufSlowMA[1];
//2本前の移動平均
double FastMA2 = BufFastMA[2];
double SlowMA2 = BufSlowMA[2];
:
:
注文関数の部分は、基本プログラムと同様に修正します。
カスタム指標を使ったEA
サンプルプログラムex3_ea.mq4は、ex2_ea.mq4の短期移動平均をカスタム指標ex10_indに置き換えたものです。
MQL5でカスタム指標を呼び出す関数もiCustom()ですが、書式がMQL4と異なります。以下のようにMQL4のiCustom()の最後の二つの引数を省いたものとなっています。
int iCustom(
string symbol, // 銘柄名
ENUM_TIMEFRAMES period, // 期間
string name // フォルダ/カスタム指標名
... // 指標入力パラメータのリスト
);
したがって、ex2_ea.mq4を修正したex2_ea.mq5で、「hFastMA」の初期化のところを次のように書き換えるだけでOKです。
hFastMA = iCustom(_Symbol, 0, "ex10_ind", MomPeriod, MaxMom);
ボリンジャーバンドを使った逆張りEA
サンプルプログラムex4_ea.mq4では、使用するテクニカル指標はボリンジャーバンド一つですが、指標値として上位ラインと下位ラインの2本、さらに、終値の配列が必要となります。
ボリンジャーバンドの上位ライン、下位ラインとも、期間や偏差の倍率などのパラメータは共通なので、ボリンジャーバンドの指標ハンドルは一つで構いません。
int hBB; //ボリンジャーバンドの指標ハンドル
double BufUpper[], BufLower[]; //ボリンジャーバンド用配列
double Close[]; //終値用配列
ボリンジャーバンドの初期化関数iBands()はMQL4と同じ名前ですが、引数の順番が一部異なるところに注意してください。「BBDeviation」を代入する引数は、4番目ではなく、5番目です。
また、BufUpper[], BufLower[], Close[]の3つの配列を時系列配列に設定します。
//初期化関数
int OnInit()
{
//テクニカル指標の初期化
hBB = iBands(_Symbol, 0, BBPeriod, 0, BBDeviation, PRICE_CLOSE);
//時系列配列に設定
ArraySetAsSeries(BufUpper, true);
ArraySetAsSeries(BufLower, true);
ArraySetAsSeries(Close, true);
return(INIT_SUCCEEDED);
}
OnTick()関数で、各配列にデータをコピーします。
ボリンジャーバンドのどちらのラインかは、CopyBuffer()の2番目の引数で区別します。上位ラインであれば「UPPER_BAND」、下位ラインであれば「LOWER_BAND」を代入します。
また終値用の配列Close[]に終値をコピーするには、CopyClose()という関数を使います。
この関数の引数は、「シンボル名」「タイムフレーム」「コピーする位置」「コピーするデータ数」「配列名」の順で、後半の3つの引数はCopyBuffer()と同じです。
これにより、MQL4の定義済み配列であるClose[]と同じ使い方ができるようになります。
//ティック時実行関数
void OnTick()
{
CopyClose(_Symbol, 0, 0, 3, Close); //終値のコピー
CopyBuffer(hBB, UPPER_BAND, 0, 3, BufUpper);
CopyBuffer(hBB, LOWER_BAND, 0, 3, BufLower);
//1本前のボリンジャーバンド
double BBUpper1 = BufUpper[1];
double BBLower1 = BufLower[1];
//2本前のボリンジャーバンド
double BBUpper2 = BufUpper[2];
double BBLower2 = BufLower[2];
:
:
その他の修正点は、基本プログラムと同じです。
損切り幅・利食い幅を設定したEA
サンプルプログラムex5_ea.mq4は、ex4_ea.mq4のOrderSend()関数に損切り注文と利食い注文を追加したものです。
MQL5でもOrderSend()関数に損切り注文、利食い注文を追加することができます。損切り注文の価格は「request.sl」に、利食い注文の価格は「request.tp」にそれぞれセットします。
それぞれの注文価格は、買値Ask、売値Bidを基準に算出します。ただし、MQL5では定義済み変数Ask、Bidが使えません。
そこで、買い注文の場合Ask、売り注文の場合Bidが「request.price」に代入されているので、それを利用して損切り価格、利食い価格を設定します。
設定するのは新規売買注文のところなので、「ポジションがなければ買い注文」のところに
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = Lots;
request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.type = ORDER_TYPE_BUY;
request.sl = request.price-SLPoint*_Point; //損切り注文
request.tp = request.price+TPPoint*_Point; //利食い注文
bool b = OrderSend(request, result);
if(result.retcode == TRADE_RETCODE_DONE) Ticket = result.order;
と記述、「ポジションがなければ売り注文」のところに
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = Lots;
request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
request.type = ORDER_TYPE_SELL;
request.sl = request.price+SLPoint*_Point; //損切り注文
request.tp = request.price-TPPoint*_Point; //利食い注文
bool b = OrderSend(request, result);
if(result.retcode == TRADE_RETCODE_DONE) Ticket = result.order;
と記述します。
決済シグナルを追加したEA
サンプルプログラムex6_ea.mq4は、ex4_ea.mq4に決済シグナルによる決済注文を追加したものです。
決済シグナルには、ボリンジャーバンドの中央ライン(移動平均線)と終値との交差を利用しているので、プログラムとして追加するのは、中央ライン用の配列と、その配列を使って変数にコピーするコードです。
以下のコードで赤で示したところがが追加した箇所です。
int hBB; //ボリンジャーバンドの指標ハンドル
double BufMain[], BufUpper[], BufLower[]; //ボリンジャーバンド用配列
double Close[]; //終値用配列
//初期化関数
int OnInit()
{
//テクニカル指標の初期化
hBB = iBands(_Symbol, 0, BBPeriod, 0, BBDeviation, PRICE_CLOSE);
//時系列配列に設定
ArraySetAsSeries(BufMain, true);
ArraySetAsSeries(BufUpper, true);
ArraySetAsSeries(BufLower, true);
ArraySetAsSeries(Close, true);
return(INIT_SUCCEEDED);
}
//ティック時実行関数
void OnTick()
{
CopyClose(_Symbol, 0, 0, 3, Close); //終値のコピー
CopyBuffer(hBB, BASE_LINE, 0, 3, BufMain);
CopyBuffer(hBB, UPPER_BAND, 0, 3, BufUpper);
CopyBuffer(hBB, LOWER_BAND, 0, 3, BufLower);
//1本前のボリンジャーバンド
double BBMain1 = BufMain[1];
double BBUpper1 = BufUpper[1];
double BBLower1 = BufLower[1];
//2本前のボリンジャーバンド
double BBMain2 = BufMain[2];
double BBUpper2 = BufUpper[2];
double BBLower2 = BufLower[2];
:
:
あとは、新規売買注文と決済注文の場所を確認して、基本プログラムと同様の修正を行ってください。
以下のkindle本の「共通ライブラリ」を利用したEAのサンプルプログラムを「MQL4/MQL5共通ライブラリCodeBase」というサイトで公開しています。MT4、MT5のどちらでも動作するコードですので、ご参考にしてください。