【超入門】MQL5 EA講座 第68回「簡単な仕組みのMT5用EAを作るーその1ー」【EAの作り方】

MQL5でEA作ろう講座

—————

前回は 待機注文の削除 について解説しました。

改めて前回の内容をおさらいをしておくと、

ということをお伝えしました。

今回から、いよいよ簡単な仕組みのEA(自動売買プログラム)を実際に作っていきたいと思います

今回の記事を読むことによって、今までの知識がどのような形でEA(自動売買プログラム)作成で利用されるのかを実感できるだけでなく、念願のEA作成がついにできるようになる訳です。

言うまでもなく、利益が出るような類のEAではなく、あくまでこれまでの知識を活かせばEAが作れることを示すためのものではありますが、是非楽しみにお読み頂ければと思います。

さて、今回作るEA(自動売買プログラム)の仕様は以下の通りです。

  • 保有するポジションは1つまで。
  • 売買判断には単純移動平均(SMA)を用いる
  • 現在値が単純移動平均(SMA)を上回っていて、ポジションが0の時に買いエントリーする。
  • 現在値が単純移動平均(SMA)を下回っていて、ポジションが0の時に売りエントリーする。
  • ストップロスとテイクプロフィットをパラメータで設定できるようにする。
  • 単純移動平均(SMA)の期間とボリューム(ロット数)もパラメーターで設定できるようにする。

EA(自動売買プログラム)を運用するのは現在大半のブローカーが採用しているヘッジングシステム口座を想定して記述していきます。

ネッティングシステムヘッジングシステムについては↓

MQL5 EA講座 第57回「ネッティングとヘッジング」 をご覧ください。

スポンサーリンク
スポンサーリンク

ステップ1:MQL5ウィザードを起動し、EAのひな型ファイルを作成する

「え?そこから?」という所から、説明をしていきますが、

MT5EA(自動売買プログラム)を作るにあたっては、メタエディターの「新規作成」ボタンを押して、MQL5ウィザードを立ち上げ、「エキスパートアドバイザー(テンプレート)」を選択→EAの名前を決めます。

イベントハンドラーは、なにもチェックを入れずに完了させます。

詳しい手順については↓の記事をご覧ください。

これをたたき台にしてEA(自動売買プログラム)を作っていきます。

ステップ2:デモ口座でしか機能しない回路を盛り込む

これから作るEA(自動売買プログラム)は、利益を保証するものでは当然ありません。あくまで学習用です。従ってデモ口座でのみ稼働するような回路をOnInit関数に組み込みます。

int OnInit()
  {

   ENUM_ACCOUNT_TRADE_MODE tradeMode=(ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE);
   if(tradeMode != ACCOUNT_TRADE_MODE_DEMO)                 // デモ口座以外の場合
     {
     
      MessageBox("このEAはデモ口座でのみ稼働します","口座エラー");
      return INIT_FAILED;                            // 処理終了
     }


//---
   return(INIT_SUCCEEDED);
  }

AccountInfoInteger関数引数ACCOUNT_TRADE_MODEを記述すると、口座がリアル口座かデモ口座かを調べることができます。取得した値がデモ口座ではなかった場合、↓の動画のように処理を終了させます。

※ちなみにMQL4だとIsDemo関数という関数が、デモ/リアル口座の切り分けに使えましたが、MQL5ではIsDemo関数はなくなっています。

OnInit関数については↓の記事をご覧ください。

MessageBox関数については↓の記事をご覧ください。

ステップ3:必要なパラメーターをinput変数で用意する

仕様で、

  • ストップロスとテイクプロフィットをパラメータで設定できるようにする。
  • SMAの期間とボリューム(ロット数)もパラメーターで設定できるようにする

という事を決めたので、必要なパラメーターを記述します。

パラメータはグローバル領域(関数の外の領域にて設定します)に、input変数で用意します。

//+------------------------------------------------------------------+
//|                                                      testEA1.mq5 |
//|                                                         MQL5ssei |
//|                                    https://mqlinvestmentlab.com/ |
//+------------------------------------------------------------------+
#property copyright "MQL5ssei"
#property link      "https://mqlinvestmentlab.com/"
#property version   "1.00"


//必要なパラメータ
input double Volume=1.0;//ロット数
input int SL=500;//ストップロス
input int TP=500;//テイクプロフィット
input int MAPeriod = 20;//移動平均期間

input変数については→コチラをご覧ください。

まだ売買記述は一切していませんが、この時点でコンパイルしてプログラムをチャートに挿入すると、

パラメータをいじることができるようになっています。↓

ステップ4:必要なグローバル変数を用意する

input変数の設定が終わったら、次はグローバル変数の記述に移ります。パラメータ化しない変数ですね。

今回作るEA(自動売買プログラム)最大で1つしかポジションを保有しない仕様なので、その制御を行います。

ポジションを最大1つに制限する制御方法は色々な記述方法があるかと思いますが、今回はbool型グローバル変数を使って制御したいと思います。

//直近の注文状況をチェックするグローバル変数
bool BuyPosition, SellPosition;

変数 「BuyPosition」、「SellPosition」の働きについては後程実際に使う段階で詳しく書きますが、BuyかSellどちらかの方向に直近ポジションを持っていたかを判断するbool型変数になります。

直近にポジションを持った方がtrue、 持っていない方はfalseとなるように記述していきます。

例えば直近にBuyポジションを持ったら、変数BuyPositionがtrueになり、変数SellPositionがfalseとなる・・・といった感じです。

グローバル変数については→コチラをご覧ください。

bool型については→コチラをご覧ください。

input変数グローバル変数の設定が終わったので次は、OnTick関数内の記述に移ります。

ステップ5:OnTick関数内の記述

MqlTradeRequest構造体とMqlTradeResult構造体のインスタンス生成

まず最初に、MqlTradeRequest構造体MqlTradeResult構造体インスタンスを生成する記述を行います。

MqlTradeRequest構造体MqlTradeResult構造体インスタンス生成は、トレードサーバーに注文を出す役割を担うOrderSend関数引数となるものなので、EA(自動売買プログラム)作成には必須の作業です。

MqlTradeRequest構造体MqlTradeResult構造体OrderSend関数の関係は以下の↓図のようになっています。

  MqlTradeRequest request;
	MqlTradeResult result;
	ZeroMemory(request);
     

↑requestというMqlTradeRequest構造体データ型にしたインスタンスと、resultというMqlTradeResult構造体データ型にしたインスタンスができました。

ZeroMemory関数について

ZeroMemory関数引数変数インスタンスを記述することで、記述した変数インスタンスの値をゼロにリセットする機能を担っています。

構造体一般については→コチラをご覧ください。

MqlTradeRequest構造体については→コチラをご覧ください。

MqlTradeResult構造体については→コチラをご覧ください。

インスタンスについては→コチラをご覧ください。

フィルポリシーを設定する関数を作り、メンバ変数.type_fillingに代入する

グローバル領域(関数の外の領域)に、適切なフィルポリシーを返す関数を作成します。

※「関数を作るってそもそもどういうこと?」という方は

第25回「関数について」をご覧ください。

//グローバル領域
//フィルポリシーを返す関数
ENUM_ORDER_TYPE_FILLING FillPolicy()
{
   long fillType = SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE);
   if(fillType==SYMBOL_FILLING_IOC)return ORDER_FILLING_IOC;
   else if(fillType==SYMBOL_FILLING_FOK)return ORDER_FILLING_FOK;
   else return ORDER_FILLING_RETURN;

}

↑作った関数の中身を簡単に説明すると、まず

フィルポリシーを返す関数なので、戻り値データ型ENUM_ORDER_TYPE_FILLING となっています。

SymbolInfoInteger関数の第2引数SYMBOL_FILLING_MODEを記述して取得した値を変数fillTypeに格納します。そこで獲得したフィルポリシー戻り値として返すようになっています。

フィルポリシーについては↓の記事をご参照ください。

作ったフィルポリシー関数を、メインプログラムであるOnTick関数内で、呼び出しメンバ変数 .type_filling に値を代入します。

//フィルポリシーを設定する。
   request.type_filling=FillPolicy();

今解説しているEA(自動売買プログラム)ではOnTick関数内で埋めていますが、クラスを使うようになったらOnInit関数で埋める記述を紹介していきます。

単純移動平均線(SMA)の値を取得する記述を行う。

今回のEA(自動売買プログラム)単純移動平均(SMA)をもとに、エントリー判断を行うので、単純単純移動平均(SMA)の値を取得する記述を行います。

 // 単純移動平均の値取得
   //単純移動平均の値を格納する配列宣言
	double sma[];
	
	//配列を時系列にセット
	ArraySetAsSeries(sma,true);
	
	//単純移動平均のハンドルを取得
	int smaHandle=iMA(_Symbol,0,MAPeriod,MODE_SMA,0,PRICE_CLOSE);
	///単純移動平均の値を配列にコピー
	CopyBuffer(smaHandle,0,0,1,sma);

MQL4とは違い、MQL5では各種インジケータの値取得が組み込み関数だけでは完結しません。

以上のようなプロセスをたどる必要があります。

図にすると↓のような感じになります。

double型配列 sma[]は、単純移動平均(SMA)の値を格納する為に用意されたものです。

ArraySetAsSeries関数は、第1引数に指定した動的配列に 時系列設定を付与することができる関数です。第2引数には時系列の設定フラグをtrueかfalseで設定します。

trueにすると、第1引数に指定した配列には直近の時間のデータから、配列に格納されていきます。配列[0]には最新の時間のデータが格納される、ということになります。

array[0](一番新しい時間)→・・・array[n](古い方の時間)という形です。

例えば5本分の足があったとして、[0]が一番新しく、[4]が一番古い・・・ということになります。↓

逆にfalseにした場合、配列は古い時間のデータから、配列に格納されていきます。配列[0]には取得されたデータ中で一番古い時間のデータが格納される、ということになります。

array[0](一番古い時間)→・・・array[n](新しい方の時間)

例えば5本分の足があったとして、[4]が一番新しく、[0]が一番古い・・・ということになります。↓

ArraySetAsSeries(sma,true);というのは、配列smaに、データを新しい順に格納していく、という事を意味しています。

ローカル変数については→コチラをご覧ください。

配列については→コチラをご覧ください。

ArraySetAsSeries関数については→コチラをご覧ください。

iMA関数について

iMA関数引数構成と戻り値は以下のようになっています。

int  iMA( 
   string              symbol,            // 銘柄名 
  ENUM_TIMEFRAMES      period,            // 期間 
  int                  ma_period,        // 平均期間 
  int                  ma_shift,          // 水平シフト 
  ENUM_MA_METHOD      ma_method,        // 平滑化の種類 
  ENUM_APPLIED_PRICE   applied_price      // 適用価格の種類
  );

戻り値は指標ハンドル
第1引数には銘柄を指定する

第1引数には銘柄を指定します。定義済み変数_Symbol」を記述すると、プログラムを挿入したチャートの銘柄を指定したことになります。

第2引数には時間軸を指定する

第2引数には時間軸を指定します。5分足なのか、1時間足なのか、日足なのか・・・そういう移動平均線を計算するベースとなるタイムフレームの指定です。定数ENUM_TIMEFRAMESで定められた値を設定します。0、もしくはPERIOD_CURRENTと記述すると現在のチャートの時間軸が適用されます。

定義済み変数については→コチラをご覧ください。

定数については→コチラをご覧ください。

enum列挙型については→コチラをご覧ください。

第3引数には移動平均を計算する期間を指定する

第3引数には移動平均線を計算する期間を指定します。例えば、ここに「20」と記述すれば、20期間の移動平均値が算出されることになります。今回作るEA(自動売買プログラム)の場合、最初に述べた通りここはinput変数「MAPeriod」で調整できるようにしてあります。

第4引数には、計算した移動平均の値をどれくらいずらして表示するか、を指定する

第4引数には、計算した移動平均線の値をどれくらいずらして表示するか、を指定します。

移動平均線インジケータを挿入する時の、プロパティ「シフト」箇所にあたります。

指定した期間だけ、未来方向にずれて描画されます。

マイナス記号をつけると、指定した期間だけ過去方向にずれて描画されます。↓の動画は移動平均線インジケータをチャートに挿入し、プロパティ「シフト」箇所(=iMA関数の第4引数にあたる部分)を変更している模様です。

最初にチャートに挿入した時は、シフトは「0」でした。その後、「10」に変更したところ、10期間分未来方向にずれて描画されています。一方、「-10」に変更したところ、10期間分過去方向にずれて描画されているのがわかると思います。

第5引数には移動平均平滑化の種類を指定する

第5引数には移動平均線の平滑化の種類を指定します。

移動平均線にもいくつかの種類があるため、それを選択する必要があります。

移動平均線の種類は、定数ENUM_MA_METHODで定められたものを設定します。

今回は単純移動平均(SMA)を採用するので、MODE_SMAを記述しています。

移動平均線の種類は単純移動平均(SMA)指数平滑移動平均(Exponential Moving Average, EMA)線形加重移動平均(Weighted Moving Average, WMA)があります。

詳しくは↓の記事で解説をしておりますので、宜しければご覧ください。

第6引数には適用価格の種類を指定する

第6引数には 適用価格の種類 を指定します。移動平均線を計算する際に、どの価格をベースするかを決めます。適用価格の種類は定数ENUM_APPLIED_PRICEの中から設定します。今回はPRICE_CLOSE(終値)を記述します。

以上を踏まえてiMA関数引数を埋めていくと以下のようになります。↓

//単純移動平均のハンドルを取得
int smaHandle=iMA(_Symbol,0,MAPeriod,0,MODE_SMA,PRICE_CLOSE);

int型変数「smaHandle」はiMA関数戻り値として返すハンドル値を格納する為に用意したものです。iMA関数に限らず、MQL5の組み込みインジケータ 関数はこのハンドル値を獲得する役割を担っています。このハンドル値を使って、さらにこれから説明するCopyBuffer関数を使って、移動平均線の値を取得します。

MQL4のように直接インジケータの値を返さないので注意が必要です。

ちなみに、MQL4のiMA関数引数構成と戻り値は↓のようになっています。

double  iMA( 
   string       symbol,           // 銘柄名
   int          timeframe,        // 期間
   int          ma_period,        // 平均期間  
   int          ma_shift,         // 水平シフト 
   int          ma_method,        // 平滑化の種類  
   int          applied_price,    //  適用価格の種類
   int          shift             // 価格を取得する位置
   );

戻り値は、引数「shift」で指定した位置の移動平均価格

CopyBuffer関数を使って、移動平均の値情報を配列にコピーする。

iMA関数を使い、晴れて単純移動平均(SMA)ハンドル値を取得出来たら、次はCopyBuffer関数を使って、単純移動平均(SMA)の値情報を配列sma[]にコピーします。

///単純移動平均の値を配列にコピー
	CopyBuffer(smaHandle,0,0,10,sma);

CopyBuffer関数について

CopyBuffer関数は指定されたインディケータのバッファデータ(保存領域に格納されているデータ)を任意の配列にコピーしてくれる関数です。

CopyBuffer関数引数戻り値の構成は以下のようになっています。

CopyBuffer関数は3つの書式をもつオーバーロード関数ですが、公式リファレンスにある第1書式のみ引用します)※オーバーロード関数については→コチラをご覧ください。

int  CopyBuffer( 
   int      indicator_handle,    // 指標ハンドル 
  int      buffer_num,          // 指標バッファ番号 
  int      start_pos,            // 開始位置 
  int      count,                // 複製する量 
  double    buffer[]              // 受け取り側の配列 
  );

戻り値は複製されたデータ数(エラーの場合は -1 )
第1引数には指標ハンドルを指定する

第1引数には指標ハンドルを指定します。iMA関数にて取得した値を変数「smaHandle」に格納しているので、変数「smaHandle」を記述します。

第2引数にはバッファ番号を指定する

第2引数にはバッファ番号を指定します。

バッファ番号とは?

プログラミングの世界では、バッファという言葉は保存領域という文脈で使われるので、インジケータバッファデータは、「インジケータの値のデータ」と読み替えれば問題ないかと思います。

インジケータによってはバッファデータが1つしかないものと、複数で構成されているものもあります。

バッファデータが1つしかないインジケータのことをシングルバッファインジケータと呼びます。

移動平均線モメンタムなどはシングルバッファインジケータにあたります。

バッファデータが複数で構成されているインジケータの事をマルチバッファインディケータと呼びます。

ボリンジャーバンドストキャスティクスMACDなどがマルチバッファインディケータに該当します。それぞれのインジケータバッファデータ数に応じて、バッファ番号というものが割り振られています。

今回第2引数に割り当てるバッファ番号ですが、移動平均線バッファデータを1つしか持たないシングルバッファインジケータなので、0を記述します。

第3引数には、コピー開始位置を指定する

第3引数には、コピー開始位置を指定します。インジケータバッファデータは、最新のデータが0番に格納され、時間軸が古い方に向かって、1.2.3・・・n番目と並んでいます。

出典:MQL5公式リファレンス、CopyBuffer関数の説明ページより

今回は最新足のデータからコピーをしたいので0を記述します。

第4引数には複製データ数を指定する

第4引数には複製データ数を指定します。第3引数で指定したコピー開始位置から指定した数だけバッファデータをコピーします。例えば第4引数に「10」と記述し、第3引数に「0」と記述した場合、最新足から10期間分のバッファデータが配列にコピーされます。

今回作るEA(自動売買プログラム)は、最新足の移動平均値だけ使う予定なので、第4引数には「1」を記述しています。

第5引数には複製データ数をコピーする配列を指定する

第5引数には複製データ数をコピーする配列を指定します。注意したいのが、第1引数から第4引数までは入力データを記述していましたが、第5引数は出力データを記述しているということです。

第1引数から第4引数までが注文伝票であり、注文した商品を第5引数で受け取るイメージです。

MQL5公式リファレンスで関数の働きを調べるときは、各引数が入力(input)なのか、出力(output)なのか、という部分も注意深く見る必要があります。公式リファレンスのCopyBuffer関数ページにおけるパラメータ部分を見ると↓

パラメータ

indicator_handle

[in]  対応する指標関数によって戻された指標ハンドル

buffer_num

[in]  指標バッファの番号

start_pos

[in]  1 番目の複製される要素の位置

count

buffer[]

[out] double 型の配列

[in]と書かれている引数は入力、[out]と書かれている引数は出力の働きをすることを示しています。

公式リファレンスの関数ページの見方については↓の記事もご参照ください。

第47回「MQL5公式リファレンスの見方」

CopyBuffer関数は以下の記事でも記述例・使用例が確認できますので、よろしければ参考にしていただければと思います。↓

——————————————————-

MQL5 EA講座 第98回「動的トレーリングストップについて」

【MQL5入門】MAの傾きでトレンド判定するEAの作り方

【MQL5入門】ウィリアムズ%レンジ(WPR)の売買シグナルを取得する方法【EAの作り方】

【MQL5入門】モメンタムの売買シグナルを取得する方法【EAの作り方】

【MQL5でパラボリックSARの売買シグナルを取得する方法】

【MQL5でストキャスティクスの売買シグナルを取得する方法】

【MQL5】5分で書ける、パーフェクトオーダーの記述【EAの作り方】

——————————————————-

ここまでで、EA(自動売買プログラム)の売買判断基準にする予定の、移動平均線に関する値取得の記述が完了しました。

今回は一旦ここまでとしたいと思います。<m(__)m>

ここまでの記述内容全体

ここまでの記述内容は以下の通りです↓

//+------------------------------------------------------------------+
//|                                                      testEA1.mq5 |
//|                                                         MQL5ssei |
//|                                    https://mqlinvestmentlab.com/ |
//+------------------------------------------------------------------+
#property copyright "MQL5ssei"
#property link      "https://mqlinvestmentlab.com/"
#property version   "1.00"


//必要なパラメータ
input double Volume=1.0;//ロット数
input int SL=500;//ストップロス
input int TP=500;//テイクプロフィット
input int MAPeriod = 20;//移動平均期間

//直近の注文状況をチェックするグローバル変数
bool BuyPosition, SellPosition;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

   ENUM_ACCOUNT_TRADE_MODE tradeMode=(ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE);
   if(tradeMode != ACCOUNT_TRADE_MODE_DEMO)                 // デモ口座以外の場合
     {

      MessageBox("このEAはデモ口座でのみ稼働します","口座エラー");
      return INIT_FAILED;                            // 処理終了
     }


//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlTradeRequest request;
   MqlTradeResult result;
   ZeroMemory(request);
  
   
//フィルポリシーを設定する。
   request.type_filling=FillPolicy();

   // 単純移動平均の値取得
   //単純移動平均の値を格納する配列宣言
	double sma[];
	
	//配列を時系列にセット
	ArraySetAsSeries(sma,true);
	
	//単純移動平均のハンドルを取得
	int smaHandle=iMA(_Symbol,0,MAPeriod,0,MODE_SMA,PRICE_CLOSE);
	///単純移動平均の値を配列にコピー
	CopyBuffer(smaHandle,0,0,10,sma);

  }
//+---

//グローバル領域
//フィルポリシーを返す関数
ENUM_ORDER_TYPE_FILLING FillPolicy()
{
   long fillType = SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE);
   if(fillType==SYMBOL_FILLING_IOC)return ORDER_FILLING_IOC;
   else if(fillType==SYMBOL_FILLING_FOK)return ORDER_FILLING_FOK;
   else return ORDER_FILLING_RETURN;

}

まとめ

今回は 簡単な仕組みのEA(自動売買プログラム)作り第1弾をお届けしました。

今回の記事では以下の作業を行いました。

今回は以上になります。次回は引き続きEA(自動売買プログラム)を作っていきます。エントリー条件などの記述を行っていく予定です。

最後までお読みいただきありがとうございました<m(__)m>

【超入門】MQL5 EA講座 第67回「待機注文の削除」【EAの作り方】

【超入門】MQL5 EA講座 第69回「簡単な仕組みのMT5用EAを作るーその2ー」【EAの作り方】

コメント

タイトルとURLをコピーしました