『新メタトレ入門本』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.mq4OrderSend()関数に損切り注文利食い注文を追加したものです。

MQL5でもOrderSend()関数に損切り注文利食い注文を追加することができます。損切り注文の価格は「request.sl」に、利食い注文の価格は「request.tp」にそれぞれセットします。

それぞれの注文価格は、買値Ask、売値Bidを基準に算出します。ただし、MQL5では定義済み変数AskBidが使えません。
そこで、買い注文の場合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のどちらでも動作するコードですので、ご参考にしてください。

メタトレーダー4&5共通ライブラリによるEA開発入門

前へ

『新メタトレ入門本』ストラテジーテスターによるEAの動作確認

次へ

『新メタトレ入門本』EAのデバッグ