【超入門】MQL5 EA講座 第110回「インジケータ取得クラスに派生クラスを追加する」

MQL5でEA作ろう講座

前回は、インジケータの値取得を簡略化できるクラスを作る解説の第1回目でした。

MT5に組み込まれているインジケータ共通の処理を担う基礎クラスと、

インジケータごとに異なった処理が必要な工程を担う、派生クラス

を作っていくというロードマップを示し、前回はまず基礎クラス(=CBaseIndicatorクラス)を作成しました。

※詳細は前回の記事の「インジケ-タクラス作成のロードマップ」セクションをご覧ください。

前回作成した基礎クラスであるCBaseIndicatorクラスには以下のメンバを追加しました。

メンバ変数「handle」インジケータハンドル値を格納する、アクセスレベル=protected変数

メンバ変数配列「main」インジケータ値を格納する、アクセスレベル=protected配列

CBaseIndicator関数インスタンス生成時に、配列の時系列をセットする、アクセスレベル=publicコンストラクタ

メンバ関数「Main」インジケータの値を取得して戻り値として返す、アクセスレベル=publicメンバ関数

メンバ関数「Release」インジケータの値をメモリから解放する時に使う、アクセスレベル=publicメンバ関数

メンバ関数「Init」戻り値だけを定めた、アクセスレベル=public仮想関数。細かい処理内容は、各派生クラスで定義する。

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

今回は、前回作った基礎クラス(=CBaseIndicatorクラス)を元にして、今後、どんなインジケータを使おうとしても滞りなく値を取得出来るようにするための派生クラスを作っていきます。

スポンサーリンク
スポンサーリンク
  1. CBaseIndicatorクラスの派生クラスを作る
    1. 移動平均線の派生クラスを作る
      1. 仮想関数「Init」の仮引数と処理実装記述をCDerivediMAクラスで再定義する
        1. CDerivediMAクラスにおける仮想関数「Init」の仮引数について
        2. CDerivediMAクラスにおける仮想関数Initの処理実装記述について
    2. 実際にメインプログラムでCDerivediMAクラスを使い、移動平均の値を取得してみる。
      1. OriginalIndicators.mqhファイルのインクルードする
      2. CDerivediMAクラスのインスタンスを宣言する
      3. 各種input変数を宣言する
      4. OnInit関数内にCDerivediMAクラスのInit関数を呼び出す
      5. OnTick関数内でCDerivediMAクラスのメンバ関数「Main」を呼び出す
    3. ストキャスティクスの派生クラスを作る
        1. メンバ配列「signal」はストキャスティクスのシグナルライン値を格納する
        2. 仮想関数「Init」の仮引数と処理実装記述をCDerivediStochasticクラスで再定義する
          1. CDerivediStochasticクラスにおける仮想関数「Init」の仮引数について
          2. CDerivediStochasticクラスにおける仮想関数「Init」の処理実装記述について
        3. CDerivediStochastic関数はインスタンス生成時に、配列signalの時系列をセットするコンストラクタ
          1. コンストラクタ、CDerivediStochastic関数の処理実装記述について
        4. メンバ関数「Signal」はシグナルラインの値を取得して戻り値として返す
          1. メンバ関数「Signal」の処理実装記述について
  2. 実際にメインプログラムでCDerivediStochasticクラスを使い、ストキャスティクスのの値を取得してみる。
    1. OriginalIndicators.mqhファイルのインクルードする
    2. CDerivediStochasticクラスのインスタンスを宣言する
    3. 各種input変数を宣言する
    4. OnInit関数内にCDerivediStochasticクラスのInit関数を呼び出す
    5. OnTick関数内でCDerivediStochasticクラスのMain関数とSignal関数を呼び出す
  3. まとめ

CBaseIndicatorクラスの派生クラスを作る

しつこいかもしれませんが、大事な点なので前提をおさらいしておきましょう。

前回作ったCBaseIndicatorクラスは、これから作る各インジケータ用の派生クラスの親クラスとなるものです。この親クラスではどのインジケータにも共通する処理を担ってもらいます。

しかしその一方で、インジケータにはたくさんの種類があり、その値取得にはインジケータごとに違うプロセスも踏まなくてはいけません。

そこで、自分が使いたいと思うインジケータ用の派生クラスを別途作っていこう、というのが今回の記事の趣旨となります。

その手始めとして、まずは移動平均線派生クラスから作っていきましょう。

移動平均線自体の詳しい解説は↓の記事で行っていますので、宜しければご覧ください。

移動平均線の派生クラスを作る

移動平均線は、シングルバッファインジケータです。

シングルバッファインジケータというのは、バッファの数=インジケータとしてMT5のチャートに表示する数値の数」が1つだけのインジケータの事です。

従って、派生クラスを作る手間も、後で解説するマルチバッファインジケータよりは少ないです。

class CDerivediMA : public CBaseIndicator
{
	
};

派生クラス名は「CDerivediMA」クラスとしました。

classキーワード

クラス名「「CDerivediMA」の後にコロン(:)、

アクセス指定子である「public」、

クラス名である「CBaseIndicator

の順番で記述する事によって、「CDerivediMA」クラスCBaseIndicatorクラス派生クラスであるという意味合いになります。

派生クラスについては↓の記事をご参照ください。

MQL5 EA講座 第51回「クラスについて4 -派生クラス-」

private,protected,publicなどのアクセス指定子については以下の記事をご参照ください。

MQL5 EA講座 第50回「クラスについて3 -アクセス指定子-」

この「CDerivediMA」クラスの中にメンバを追加していくのですが、今回追加するメンバは1つだけです。

class CDerivediMA : public CBaseIndicator
{
	public:
		int Init(string parSymbol,ENUM_TIMEFRAMES parTimeframe,int parMAPeriod,int parMAShift,ENUM_MA_METHOD parMAMethod,ENUM_APPLIED_PRICE parMAPrice);
};

アクセスレベル=publicの領域にメンバ関数「Init」を追加しました。

注意して頂きたいのが、追加するメンバ「Init」1つだけですが、「CDerivediMA」クラスCBaseIndicatorクラス派生クラスなので、実際には以下のCBaseIndicatorクラス所属メンバも使えるという事です。

【使えるCBaseIndicatorクラス所属のメンバ一覧】

「handle」 (インジケータハンドル値を格納する変数)

「main」 (インジケータ値を格納する配列)

CBaseIndicator関数 (インスタンス生成時に、配列の時系列をセットするコンストラクタ

Main関数 (インジケータの値を取得して戻り値として返すメンバ関数)

Release関数インジケータの値をメモリから解放する時に使メンバ関数

イメージとしては↓のような感じです。

class CDerivediMA : public CBaseIndicator
{

//protected:
	//	int handle;//書かれてないけど実際は使える
	//	double main[];//書かれてないけど実際は使える
		
	//public:
		//CBaseIndicator(void);書かれてないけど実際は使える
    //double Main(int parIndex=0);//書かれてないけど実際は使える
		//void Release();//書かれてないけど実際は使える
	
public:
		int Init(string parSymbol,ENUM_TIMEFRAMES parTimeframe,int parMAPeriod,int parMAShift,ENUM_MA_METHOD parMAMethod,ENUM_APPLIED_PRICE parMAPrice);
};

以上の前提を押さえた上で改めて、「CDerivediMA」クラスの中身を順を追って見てきましょう。

仮想関数「Init」の仮引数と処理実装記述をCDerivediMAクラスで再定義する

追加メンバ「Init」は親クラスCBaseIndicator」で定義した仮想関数です。

※詳細は前回講座記事の『メンバ関数「Init」は戻り値だけを定めた仮想関数』セクションをご覧ください。

クラスCBaseIndicator」の時には、戻り値データ型int型であるという事と、、return演算子で戻す値がアクセスレベル=protectedメンバ変数「handle」、ということだけでした。

仮想関数については↓の記事をご参照ください。

MQL5 EA講座 第53回「クラスについて6 -仮想関数-」

従って、派生クラスである「CDerivediMA」で、改めて引数と処理実装記述を設定します。

メンバ変数「handle」については、前回記事の『メンバ変数「handle」はインジケ-タのハンドル値を格納する』セクションをご覧ください。

CDerivediMAクラスにおける仮想関数「Init」の仮引数について

「CDerivediMA」クラスにおける、仮想関数「Init」引数は以下のようになっています。

(string parSymbol,//銘柄名を指定
ENUM_TIMEFRAMES parTimeframe,//チャート時間軸を指定
int parMAPeriod,//移動平均を計算する期間を指定
int parMAShift,//計算した移動平均の値をどれくらいずらして表示するかを指定
ENUM_MA_METHOD parMAMethod,//移動平均平滑化の種類を指定
ENUM_APPLIED_PRICE parMAPrice//適用価格の種類を指定)

引数は、移動平均線の値を取得する為に使う、iMA関数の各引数に記述される想定ですので、iMA関数の各引数に完全対応した形になっています。

iMA関数の各引数については、コチラのリンクをご参照ください。

<参照>

ENUM_TIMEFRAMES/ENUM_MA_METHOD/ENUM_APPLIED_PRICE

CDerivediMAクラスにおける仮想関数Initの処理実装記述について

仮想関数 「Init」の処理実装記述については以下のようになっています。

int CDerivediMA::Init(string parSymbol,ENUM_TIMEFRAMES parTimeframe,int parMAPeriod,int parMAShift,ENUM_MA_METHOD parMAMethod,ENUM_APPLIED_PRICE parMAPrice)
{
	handle = iMA(parSymbol,parTimeframe,parMAPeriod,parMAShift,parMAMethod,parMAPrice);
	return(handle);
}

{}内の処理実装記述では、iMA関数を呼び出して、親クラスであるCBaseIndicatorクラスのメメンバ変数「handle」に、取得したハンドル値を格納しています。

メンバ変数「handle」アクセスレベルCBaseIndicatorクラス内でprotectedに設定されていますので、派生クラスである「CDerivediMA」クラスメンバ関数からはアクセスができます。

あとは実際にEAを自作するメインプログラムにおいて、今回処理実装記述を施した

「Init」関数(「CDerivediMA」クラスメンバ

メンバ関数「Main」CBaseIndicatorクラスメンバ)を呼び出すことによって、移動平均線の値を簡単に取得する事ができます。

実際にメインプログラムでCDerivediMAクラスを使い、移動平均の値を取得してみる。

では実際に、EAを自作する事を想定してメインプログラム内で「CDerivediMA」クラスを使い、移動平均線の値を取得する記述をしてみましょう。

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

//OriginalIndicators.mqhファイルのインクルード
#include <OriginalIndicators.mqh>

//CDerivediMAクラスのインスタンスを宣言
CDerivediMA MA;
//必要なパラメータ
input int MAPeriod=20;//移動平均の期間
input int MAShift=0;//移動平均をどのくらいずらすか
input ENUM_MA_METHOD MAMethod=MODE_SMA;//移動平均の種類
input ENUM_APPLIED_PRICE AppliedPrice=PRICE_CLOSE;//移動平均に適用する価格種類

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {     //Init関数を呼び出して移動平均のハンドル値を取得
      MA.Init(_Symbol,_Period,MAPeriod,MAShift,MAMethod,AppliedPrice);
   return(INIT_SUCCEEDED);
  }

void OnTick()
  {   //現在足の移動平均値を取得する
      double currentMA=MA.Main();
   
  }
//+------------------------------------------------------------------+

OriginalIndicators.mqhファイルのインクルードする

まずは「OriginalIndicators.mqh」ファイルをメインプログラムのグローバル領域(関数の外の領域)にインクルードします。

//OriginalIndicators.mqhファイルのインクルード
#include <OriginalIndicators.mqh>

インクルードファイルについては下記の記事をご参照ください。

MQL5 EA講座 第56回「#include命令(#include directive)」

CDerivediMAクラスのインスタンスを宣言する

include命令により、晴れて「CDerivediMA」クラスが使えるようになったので、次はインスタンスを宣言します。

//CDerivediMAクラスのインスタンスを宣言
CDerivediMA MA;

インスタンス名は「MA」としました。

インスタンスについては下記の記事をご参照ください。

MQL5 EA講座 第54回「インスタンスについて」

各種input変数を宣言する

インスタンスを宣言した後は、各種input変数を宣言します。

//必要なパラメータ
input int MAPeriod=20;//移動平均の期間
input int MAShift=0;//移動平均をどのくらいずらすか
input ENUM_MA_METHOD MAMethod=MODE_SMA;//移動平均の種類
input ENUM_APPLIED_PRICE AppliedPrice=PRICE_CLOSE;//移動平均に適用する価格種類

この部分は講座記事第108回の「インジケータ関数の引数に記述するための値をinput変数で設定する」セクション(移動平均線編)と全く同じです。

input変数については下記の記事をご参照ください↓

MQL5 EA講座 第24回「Input変数」

OnInit関数内にCDerivediMAクラスのInit関数を呼び出す

次にやる事はOnInit関数内に「CDerivediMA」クラス「Init」関数を呼び出す事です。

int OnInit()
  {     //Init関数を呼び出して移動平均のハンドル値を取得
      MA.Init(_Symbol,_Period,MAPeriod,MAShift,MAMethod,AppliedPrice);
   return(INIT_SUCCEEDED);
  }

「CDerivediMA」クラス「Init」関数は、iMA関数を使って移動平均線ハンドル値を呼び出す機能を担っています。

ハンドル値の取得という作業は、1度だけ行えば事足りるので,EAMT5チャートに挿入する時にだけ処理を行うOnInit関数 内で呼び出すのが妥当でしょうOnTick関数内で呼び出しても特に差しさわりはありませんが、何度も呼び出す必要のない処理です)

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

MQL5 EA講座 第5回「OnInit関数」

OnTick関数内でCDerivediMAクラスのメンバ関数「Main」を呼び出す

最後にOnTick関数内で「CDerivediMA」クラスメンバ関数「Main」を呼び出します。

void OnTick()
  {   //現在足の移動平均値を取得する
      double currentMA=MA.Main();

       Print("移動平均価格= ",currentMA);
  }

double型変数「currentMA」を宣言し、そこに「CDerivediMA」クラスメンバ関数「Main」を呼び出して戻り値代入します。メンバ関数「Main」引数インデックス(通し番号)を指定するようになっています。

初期値は「0」に設定されていますので、()内に何も記述しなければ自動的にインデックス「0」、すなわち現在足の移動平均情報が取得できる、という訳です。

初期値については下記の記事をご参照ください。

MQL5 EA講座 第46回「関数の初期値について」

Print関数で取得した値をログ出力している挙動は以下のようになっています。

「CDerivediMA」クラスを利用した移動平均値の取得手順は以上になります。

ストキャスティクスの派生クラスを作る

もう1つのインジケータ派生クラスの例として、今度はストキャスティクス派生クラスを作っていきたいと思います。

ストキャスティクスマルチバッファインジケータとなります。

マルチバッファインジケータは、バッファの数が複数=「MT5のチャートに表示する数値の数」が複数のインジケータの事を指します

派生クラスの作成過程では、シングルバッファインジケータとはいくつか異なる点もあります。

違いに注意を払いながら見てきましょう。

class CDerivediStochastic : public CBaseIndicator
{
	
};

まずはクラス名の宣言です。クラス名を「CDerivediStochastic」としました。

classキーワード

クラス「CDerivediStochastic」の後にコロン(:)、

アクセス指定子である「public」、

クラス名である「CBaseIndicator

の順番で記述する事によって、「CDerivediStochastic」クラスCBaseIndicatorクラス派生クラスであるという意味合いになります。

この中に追加するメンバは以下のようになります。

class CDerivediStochastic : public CBaseIndicator
{
	private:
		double signal[];
	
	public:
		int Init(string parSymbol, ENUM_TIMEFRAMES parTimeframe, int parKPeriod, int parDPeriod, int parSlowing, ENUM_MA_METHOD parMAMethod, ENUM_STO_PRICE parPrice);
		double Signal(int parShift=0);
		CDerivediStochastic(void);
};

{}内に追加したメンバは上記の通りですが、「CDerivediStochastic」クラス派生クラスなので、親クラスであるCBaseIndicatorクラスメンバも使えます。実際のイメージとしては以下のようになるでしょうか?

class CDerivediStochastic : public CBaseIndicator
{
	private:
		double signal[];
 protected:
		int handle;//書かれてないけど実際は使える
		double main[];//書かれてないけど実際は使える
	
	public:
		int Init(string parSymbol, ENUM_TIMEFRAMES parTimeframe, int parKPeriod, int parDPeriod, int parSlowing, ENUM_MA_METHOD parMAMethod, ENUM_STO_PRICE parPrice);
		double Signal(int parShift=0);
		CDerivediStochastic(void);

    CBaseIndicator(void);//書かれてないけど実際は使える
		double Main(int parIndex=0);//書かれてないけど実際は使える
		void Release();//書かれてないけど実際は使える
};

移動平均線の値を取得する「CDerivediMA」クラスの時は、{}内に追加したメンバ仮想関数である「Init」関数のみだったのですが、ストキャスティクスの値取得を目的としている「CDerivediStochastic」クラスでは

アクセスレベルprivate配列「signal」

アクセスレベルpublicSignal関数CDerivediStochastic関数という

3つのメンバを追加しました。

「CDerivediMA」クラスと比べ、なぜこのような違いが生じるか?ですが、ストキャスティクスマルチバッファインジケータであることが理由です。

一つ一つの追加メンバについて解説していくので、ゆっくりと理解を深めていきましょう。

メンバ配列「signal」はストキャスティクスのシグナルライン値を格納する

アクセスレベルprivateメンバ配列signal[]は、ストキャスティクスのシグナルライン値を格納するのに使います。

シングルバッファインジケータである移動平均線の時は、インジケータ値を格納する配列は親クラスCBaseIndicatorクラスメンバ変数配列「main」だけで事足りたのですが、ストキャスティクスはメインラインとシグナルラインの2つのラインで構成されるマルチバッファインジケータなので、インジケータ値を格納する配列も2つ必要になります↓

ストキャスティクスのメインラインについては親クラスCBaseIndicatorクラスメンバ変数配列「main」に格納されます。

※なお、メンバ配列signal[]アクセスレベルprotectedではなく、privateとしているのは、これ以上クラスを派生させる必要がない、という判断をしている為です。クラスを作成する過程において、もし「CDerivediStochastic」クラスからさらに派生クラスを作る場合はprotectedにしても構わない、という事になります。

仮想関数「Init」の仮引数と処理実装記述をCDerivediStochasticクラスで再定義する

追加メンバ「Init」は親クラスCBaseIndicator」で定義した仮想関数です。

「CDerivediMA」クラスでも行った処理ではありますが、移動平均線ストキャスティクスではハンドル値を取得する関数も違うので、別途仮想関数 「Init」」を再定義しなおす必要があります。

※詳細は前回講座記事の『メンバ関数「Init」は戻り値だけを定めた仮想関数』セクションをご覧ください。

クラスCBaseIndicator」の時には、戻り値データ型int型であるという事と、、return演算子で戻す値がアクセスレベル=protectedメンバ変数「handle」、ということだけでした。

従って、派生クラスである「CDerivediStochastic」クラスで、改めて引数と処理実装記述を設定します。

CDerivediStochasticクラスにおける仮想関数「Init」の仮引数について

「CDerivediStochastic」クラスにおける、仮想関数 「Init」引数は以下のようになっています。

int Init(string parSymbol, 
ENUM_TIMEFRAMES parTimeframe, 
int parKPeriod, 
int parDPeriod, 
int parSlowing,
 ENUM_MA_METHOD parMAMethod,
 ENUM_STO_PRICE parPrice);

引数移動平均線の値を取得する=iStochastic関数の各引数に記述される想定ですので、iStochastic関数の各引数に完全対応した形になっています。

iStochastic関数の各引数についてはコチラのリンクをご参照ください。

CDerivediStochasticクラスにおける仮想関数「Init」の処理実装記述について

「CDerivediStochastic」クラスにおける仮想関数 「Init」の処理実装記述については以下のようになっています。

int CDerivediStochastic::Init(string parSymbol, ENUM_TIMEFRAMES parTimeframe, int parKPeriod, int parDPeriod, int parSlowing, ENUM_MA_METHOD parMAMethod, ENUM_STO_PRICE parPrice)
{
	handle = iStochastic(parSymbol,parTimeframe,parKPeriod,parDPeriod,parSlowing,parMAMethod,parPrice);
	return(handle);
}

{}内の処理実装記述では、iStochastic関数を呼び出して、親クラスであるCBaseIndicatorクラスメンバ変数「handle」に、取得したハンドル値を格納します。

メンバ変数「handle」アクセスレベルCBaseIndicatorクラス内でprotectedに設定されていますので、派生クラスである「CDerivediStochastic」クラスメンバ関数からでもアクセスができます。

あとは実際にEAを自作するメインプログラムにおいて、今回処理実装記述を施した「Init」関数(「CDerivediStochastic」クラスメンバ)とメンバ関数「Main」CBaseIndicatorクラスメンバ)、及びこの後解説するSignal関数を呼び出すことによって、ストキャスティクスのメインラインやシグナルラインの値を自由に取得する事ができます。

CDerivediStochastic関数はインスタンス生成時に、配列signalの時系列をセットするコンストラクタ

アクセスレベルpublicに宣言したCDerivediStochastic関数インスタンス生成時に、配列「signal」の時系列をセットするコンストラクタです。

クラスコンストラクタであるCBaseIndicator関数配列を時系列にセットする関数なのですが、CBaseIndicator関数は基本的にバッファ番号「0」のインジケータ値を格納する配列に対し、時系列セットを施すようになっています。

バッファ番号「0」のインジケータ値は、ストキャスティクスにおいてはメインラインの値になります。

従って、ストキャスティクスの値を正確に取ることを目的とした「CDerivediStochastic」クラスにおいては、『シグナルラインの値を格納する配列「signal」にも時系列セットを施すコンストラクタが必要になる訳です。

コンストラクタについては以下の記事をご参照ください。

MQL5 EA講座 第52回「クラスについて5 -コンストラクタ-」

コンストラクタ、CDerivediStochastic関数の処理実装記述について

コンストラクタCDerivediStochastic関数の処理実装記述は以下の通りです。

CDerivediStochastic::CDerivediStochastic(void)
{
	ArraySetAsSeries(signal,true);
}

コンストラクタ戻り値を取らないので、データ型void型(=型なし)になります

ArraySetAsSeries関数を使い、配列「signal」に時系列セットを施します。

メンバ関数「Signal」はシグナルラインの値を取得して戻り値として返す

メンバ関数Signall」はインジケータの値を取得して戻り値として返す関数です。

メインプログラムで呼び出す想定なので、アクセスレベルpublicとなります。戻り値データ型double型となります。

メンバ関数「Signal」の処理実装記述について

メンバ関数Signal」の処理実装記述については以下の通りです。

double CDerivediStochastic::Signal(int parShift=0)
{
	CopyBuffer(handle,1,0,MAX_COPY,signal);
	double value = NormalizeDouble(signal[parShift],_Digits);
	return(value);
}

引数「parIndex」には、シグナルラインの値を取得したい時系列のインデックス番号を指定します。

引数「parIndex」の初期値は「0」にしてあります。従って、メインプログラムで引数の記述を省略した場合、現在足のシグナルライン値を取得する事になります。

{}内の処理実装記述についてですが、CopyBuffer関数を使い、アクセスレベル=private配列「signal」にシグナルライン値をコピーします。CopyBuffer関数の第1引数には、これもアクセスレベル=protected変数handle」を記述します。

第2引数にはバッファ番号を記述する訳ですが、ストキャスティクスバッファ番号

メインライン→「0」

シグナルライン→「1」

となっていますので、第2引数には「1」を記述します。

CopyBuffer関数の詳細についてはコチラのリンクをご確認ください。

配列「signal」に格納されたシグナルライン値は、NormalizeDouble関数を使って正規化します。

正規化とは、プログラムが取り扱うルールに則って値を整える作業

のことを指します。

NormalizeDouble関数の第1引数には正規化する対象、すなわちsignal[parIndex]を記述します。

第2引数には定義済み変数_Digits」を記述します。

定義済み変数については↓の記事をご参照ください。

MQL5 EA講座 第29回「定義済み変数について」

正規化して、値を整えたsignal[parIndex]を、double型ローカル変数「value」 に代入します。

最後に変数「value」をreturn演算子戻り値として返して処理実装記述は終了です。

実際にメインプログラムでCDerivediStochasticクラスを使い、ストキャスティクスのの値を取得してみる。

「CDerivediStochastic」クラスの各メンバの処理実装記述が終わった所で、今度は実際に、EAを自作する事を想定してメインプログラム内で「CDerivediStochastic」クラスを使い、ストキャスティクスの値を取得する記述をしてみましょう。

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



//OriginalIndicators.mqhファイルのインクルード
#include <OriginalIndicators.mqh>

//CDerivediStochasticクラスのインスタンスを宣言
CDerivediStochastic Stocha;

//必要なパラメータ
input int KPeriod=5;//K%の期間
input int DPeriod=3;//D%の期間
input int Slowing=3;//スローイングの期間
input ENUM_MA_METHOD StochaMethod=MODE_SMA;//ストキャス計算に使う移動平均の種類
input ENUM_STO_PRICE StochaPrice=STO_LOWHIGH;//ストキャス計算に使う価格種類

int OnInit()
  {      //Init関数を呼び出してストキャスティクスのハンドル値を取得
      Stocha.Init(_Symbol,_Period,KPeriod,DPeriod,Slowing,StochaMethod,StochaPrice);
   return(INIT_SUCCEEDED);
  }

void OnTick()
  {
      double mainLine=Stocha.Main();
      double signalLine=Stocha.Signal();
      
      Print("メインライン=",mainLine,",シグナルライン=",signalLine);
   
  }
//+------------------------------------------------------------------+

OriginalIndicators.mqhファイルのインクルードする

まずは「OriginalIndicators.mqh」ファイルをメインプログラムのグローバル領域にインクルードします。

//OriginalIndicators.mqhファイルのインクルード
#include <OriginalIndicators.mqh>

CDerivediStochasticクラスのインスタンスを宣言する

「OriginalIndicators.mqh」ファイルをインクルードし、「CDerivediStochastic」クラスを使えるようになったので、今度は「CDerivediStochastic」クラスインスタンスを宣言します。

//CDerivediStochasticクラスのインスタンスを宣言
CDerivediStochastic Stocha;

インスタンス名は「Stocha」としました。

各種input変数を宣言する

インスタンスを宣言した後は、各種input変数を宣言します。

input int KPeriod=5;//K%の期間
input int DPeriod=3;//D%の期間
input int Slowing=3;//スローイングの期間
input ENUM_MA_METHOD StochaMethod=MODE_SMA;//ストキャス計算に使う移動平均の種類
input ENUM_STO_PRICE StochaPrice=STO_LOWHIGH;//ストキャス計算に使う価格種類

この部分は講座記事第108回の「インジケータ関数の引数に記述するための値をinput変数で設定する」セクション(ストキャスティクス編)と全く同じです。

<参照>

ENUM_STO_PRICE

OnInit関数内にCDerivediStochasticクラスのInit関数を呼び出す

続いてOnInit関数内に「CDerivediStochastic」クラス「Init」関数を呼び出します。

int OnInit()
  {      //Init関数を呼び出してストキャスティクスのハンドル値を取得
      Stocha.Init(_Symbol,_Period,KPeriod,DPeriod,Slowing,StochaMethod,StochaPrice);
   return(INIT_SUCCEEDED);
  }

「CDerivediStochastic」クラス「Init」関数は、iStochastic関数を使ってストキャスティクスハンドル値を呼び出す機能を担っています。

ハンドル値の取得作業は、1度だけ行えば事足りるので,EAMT5チャートに挿入する時にだけ処理を行うOnInit関数 内で行います。

OnTick関数内でCDerivediStochasticクラスのMain関数とSignal関数を呼び出す

最後にOnTick関数内で「CDerivediStochastic」クラスメンバ関数「Main」Signal関数を呼び出します。

void OnTick()
  {
      double mainLine=Stocha.Main();
      double signalLine=Stocha.Signal();
      
      Print("メインライン=",mainLine,",シグナルライン=",signalLine);
   
  }

double型ローカル変数「mainLine」を宣言し、そこにはメンバ関数「Main」戻り値を、

同じくdouble型ローカル変数「signalLine」を宣言し、そこにはSignal関数戻り値を、それぞれ代入します。

Print関数で値を出力させてみた挙動は以下のようになっています。

「CDerivediStochastic」クラスを利用したストキャスティクスの取得手順は以上になります。

まとめ

今回は、前回第109回で作った、基礎クラス(=CBaseIndicatorクラス)を元にして、今後、どんなインジケータを使おうとしても滞りなく値を取得出来るようにするための派生クラスを作りました。

作った派生クラスは、

シングルバッファインジケータの例として移動平均線の値を取得する「CDerivediMA」クラス

マルチバッファインジケータの例としてストキャスティクスの値を取得する「CDerivediStochastic」クラス

の2つですが、MQL5の組み込み関数があるインジケータであれば、今回紹介した手順に従って、使いたい組み込みインジケータ派生クラスを自由に作ることができます。

「OriginalIndicators.mqh」ファイルに作った派生クラスを集約させておけば、EA開発の際に、簡単に取得したいインジケータの値をメインプログラムから取得できるようになります。

EA開発の可能性がだいぶ広がったと感じられるのではないでしょうか?

※現時点での「OriginalIndicators.mqh」ファイルの記述内容全体は以下のようになっています。

//+------------------------------------------------------------------+
//|                                           OriginalIndicators.mqh |
//|                                                         MQL5ssei |
//|                                    https://mqlinvestmentlab.com/ |
//+------------------------------------------------------------------+
#property copyright "MQL5ssei"
#property link      "https://mqlinvestmentlab.com/"

//インジケータ値を配列にコピーす数を規定
#define MAX_COPY 100

//インジケータに共通する処理を担う基礎クラス
class CBaseIndicator
{
	protected:
		int handle;//インジケータのハンドル値を格納する変数
		double main[];//インジケータの値を格納する配列
		
	public:
		CBaseIndicator(void);//コンストラクタ
		double Main(int parIndex=0);
		void Release();
		virtual int Init() { return(handle); }
};


CBaseIndicator::CBaseIndicator(void)
{
	ArraySetAsSeries(main,true);
}

double CBaseIndicator::Main(int parIndex=0)
{
	CopyBuffer(handle,0,0,MAX_COPY,main);
	double value = NormalizeDouble(main[parIndex],_Digits);
	return(value);
}

void CBaseIndicator::Release(void)
{
	IndicatorRelease(handle);
}

class CDerivediMA : public CBaseIndicator
{
	public:
		int Init(string parSymbol,ENUM_TIMEFRAMES parTimeframe,int parMAPeriod,int parMAShift,ENUM_MA_METHOD parMAMethod,ENUM_APPLIED_PRICE parMAPrice);
};

int CDerivediMA::Init(string parSymbol,ENUM_TIMEFRAMES parTimeframe,int parMAPeriod,int parMAShift,ENUM_MA_METHOD parMAMethod,ENUM_APPLIED_PRICE parMAPrice)
{
	handle = iMA(parSymbol,parTimeframe,parMAPeriod,parMAShift,parMAMethod,parMAPrice);
	return(handle);
}

class CDerivediStochastic : public CBaseIndicator
{
	private:
		double signal[];
	
	public:
		int Init(string parSymbol, ENUM_TIMEFRAMES parTimeframe, int parKPeriod, int parDPeriod, int parSlowing, ENUM_MA_METHOD parMAMethod, ENUM_STO_PRICE parPrice);
		double Signal(int parShift=0);
		CDerivediStochastic(void);
};

int CDerivediStochastic::Init(string parSymbol, ENUM_TIMEFRAMES parTimeframe, int parKPeriod, int parDPeriod, int parSlowing, ENUM_MA_METHOD parMAMethod, ENUM_STO_PRICE parPrice)
{
	handle = iStochastic(parSymbol,parTimeframe,parKPeriod,parDPeriod,parSlowing,parMAMethod,parPrice);
	return(handle);
	
}

CDerivediStochastic::CDerivediStochastic(void)
{
	ArraySetAsSeries(signal,true);
}


double CDerivediStochastic::Signal(int parShift=0)
{
	CopyBuffer(handle,1,0,MAX_COPY,signal);
	double value = NormalizeDouble(signal[parShift],_Digits);
	return(value);
}

今回は以上とさせていただきます。

最後までお読みいただきありがとうございました。

【超入門】MQL5 EA講座 第109回「インジケータの値を簡単に取得できるクラスを作る」

【超入門】MQL5 EA講座 第111回「カスタムインジケ-タについての基本を知る」

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