前回は
第109回で作った、基礎クラス(=CBaseIndicatorクラス)を元にして、今後、どんなインジケータを使おうとしても滞りなくインジケータの値を取得出来るようにするための派生クラスを作りました。
作った派生クラスは、
シングルバッファインジケータの例として、移動平均線の値を取得する「CDerivediMA」クラス
マルチバッファインジケータの例としてストキャスティクスの値を取得する「CDerivediStochastic」クラス
の2つですが、MQL5の組み込み関数があるインジケータであれば、今回紹介した手順に従って、使いたい組み込みインジケータの派生クラスを自由に作ることができます。
「OriginalIndicators.mqh」ファイルに作った派生クラスを集約させておけば、EA開発の際に、簡単に取得したいインジケータの値をメインプログラムから取得できるようになります。
第108回からインジケータに関する講座記事を続けていましたが、これまでの内容というのは基本的にMT5にあらかじめ実装されている組み込みインジケータに関しての解説でした。
今回はそれを一歩推し進めて、カスタムインジケ-タというものについて説明していきたいと思います。
- カスタムインジケ-タとは?→MT5に標準実装されていない特別仕様のインジケータのこと。
- MT5では組み込みインジケータだけでなく、カスタムインジケ-タも使うことができる。
- カスタムインジケ-タの作成や利用において、把握しておくべきこと。
- MT5に用意されているカスタムインジケ-タのサンプルコードを確認する
- ボリンジャーバンドとは?
- MT5のデータウィンドウから、カスタムインジケ-タのバッファ数を確認する
- 「BB」カスタムインジケ-タのMQL5 Source Fileの中、OnInit関数内の記述に注目する
- カスタムインジケ-タの描画バッファのインデックス番号を推測する
- カスタムインジケ-タの描画バッファとインデックス番号との紐づけを確認する
- バッファの数や描画バッファとインデックス番号との紐づけ状況を確認する事により、EA開発の際にカスタムインジケータを利用できるようになる
- カスタムインジケータ「BB」の全体コード記述
- まとめ
カスタムインジケ-タとは?→MT5に標準実装されていない特別仕様のインジケータのこと。
カスタムインジケ-タとは、直訳すると、
「特別仕様の指標」となります。指標=インジケータは、FXを始めとする金融商品トレードの世界においては、
過去相場の検証および未来相場の予測の為に用いられる、一連の計算式
と定義づけられます。
この講座内で取り上げてきた、移動平均線やストキャスティクスはMT5に標準実装されているインジケータ(=組み込みインジケータ)です。
カスタムインジケ-タはそれら組み込みインジケータとは反対に、MT5に標準実装されていないインジケータを総称する言葉です。
・MQL5リファレンス内のコードベースやマーケット、その他外部のウェブサイトから入手した組み込みインジケータではない、オリジナルのインジケータ
上記のようなインジケータをカスタムインジケ-タと呼びます。
MT5では組み込みインジケータだけでなく、カスタムインジケ-タも使うことができる。
MT5では組み込みインジケータだけではなく、カスタムインジケ-タも相場予測やEA開発に利用することができます。
MQL5を使って、自身でオリジナルのインジケータを自作する事もできるし、MQL5リファレンス内のコードベースやマーケット内で共有されたり、販売されているインジケータをMT5に取り込んで利用する事も可能です。
カスタムインジケ-タの作成や利用において、把握しておくべきこと。
カスタムインジケ-タを作ったり、EAのロジックに利用するにあたっては、以下の点を把握する必要があります↓
・インジケータ名
・カスタムインジケ-タに用いられているパラメータ(= input変数)のデータ型や数
MT5には、組み込みインジケータとは別にカスタムインジケ-タのサンプルも用意されています。
カスタムインジケ-タのサンプルはコードを確認・編集できるように、
実行ファイルであるMQL5 Program Fileの他に、編集可能なMQL5 Source Fileも用意されています。
カスタムインジケ-タというものを理解するにあたり、まずはこれらMT5に用意されているカスタムインジケ-タのサンプルコードをまずは見ていきましょう。
※MQL5 Program FileとMQL5 Source Fileについては↓の記事をご参照ください。
MT5に用意されているカスタムインジケ-タのサンプルコードを確認する
MT5にあらかじめ用意されているカスタムインジケ-タのサンプルは、
「indicators」フォルダ内の「examples」サブフォルダに一括して格納されています。
まずはこの中から「BB」という名前のMQL5 Source Fileをメタエディタで開いてみます↓
カスタムインジケ-タ「BB」はボリンジャーバンドのソースコードを明示的に示したものであり、実質ボリンジャーバンドと同じです。
ボリンジャーバンドは有名なインジケータではありますが、念のためどんなインジケータであるかをまずは押さえておきましょう
ボリンジャーバンドとは?
ボリンジャーバンドは、中央の移動平均線と、その移動平均線から上下2本に描画された標準偏差で形成されているマルチバッファインジケータです。
移動平均線は、指定期間の価格の平均を計算してその推移をグラフ化したものです。
計算する基軸の地点が、例えば10日移動平均線であれば9/1からさかのぼって10日間、日が変わって9/2になれば9/2からさかのぼって10日間・・・と移動していく事から移動平均線と呼びます。
※移動平均線については、以下の記事で詳しく解説していますのでご覧ください↓
標準偏差とは、平均の値からどれくらい「ばらついているか」を示した指標となります。
標準偏差の詳しい仕組みや計算式については↓のリンクを参考にして頂ければと思います。
移動平均線からの標準偏差の計算結果を「σ(シグマ)」という単位で呼称し、このσに2を掛け算した2σや3を掛け算した3σなどをよくチャート上に表示する事が多いです。
※ボリンジャーバンドの一般的な使い方などにつきましては↓のリンクを参考にして頂ければと思います。↓
MT5のデータウィンドウから、カスタムインジケ-タのバッファ数を確認する
カスタムインジケ-タのバッファ数を確認するにはMT5のデータウィンドウを開きます。
データウィンドウとは?
データウィンドウとは、MT5で表示できる情報窓の1つで、MT5でアクティブになっているチャートにおける
日付、時間、始値、高値、安値、終値、取引量、スプレッド、チャートに挿入しているインジケータの値
などを情報として表示してくれる情報窓となっています。
データウィンドウはMT5の「表示」メニューから「データウィンドウ」を選択するか、Ctrl+[D]のショートカットキー押下する事によって表示できます↓
カスタムインジケ-タ「BB」をチャート上に挿入した状態で、データウィンドウ内を確認すると、元々はチャートの基本データしか表示されていないかったところから、データウィンドウ最下部に「Bands(Middle)」「Bands(Upper)」「Bands(Lower)」というデータが追加表示された事が確認できます。↓
これが、カスタムインジケ-タ「BB」がチャート上に描画されている値の数、すなわち描画バッファ数となります。
カスタムインジケ-タ「BB」の描画バッファ数は3ということになります。
「BB」カスタムインジケ-タのMQL5 Source Fileの中、OnInit関数内の記述に注目する
メタエディタで開いた、「BB」カスタムインジケ-タのMQL5 Source Fileでもこの事を確認する事ができます。
ソースコードのOnInit関数内を見ると、以下のような記述があります↓
//--- define buffers
SetIndexBuffer(0,ExtMLBuffer);
SetIndexBuffer(1,ExtTLBuffer);
SetIndexBuffer(2,ExtBLBuffer);
SetIndexBuffer(3,ExtStdDevBuffer,INDICATOR_CALCULATIONS);
※OnInit関数については↓の記事をご参照ください。
記述内に見られる、SetIndexBuffer関数という関数が、インジケータのバッファ数を規定しています。
SetIndexBuffer関数について
SetIndexBuffer関数はカスタムインジケ-タを作る時に、必須となる関数です。
第1引数に指定したバッファ番号と、第2引数に指定した配列を連動させる働きを担います。
インジケータにはシングルバッファインジケータとマルチバッファインジケータがあるということは、講座記事109回~110回でお伝えしましたが、SetIndexBuffer関数は
カスタムインジケ-タに用いるバッファの数を決める関数と言い換えることもできます。
SetIndexBuffer関数の引数と戻り値について
SetIndexBuffer関数の引数と戻り値は以下の通りです
bool SetIndexBuffer(
int index, // インデックス番号
double buffer[], // インジケ-タの値を格納する配列
ENUM_INDEXBUFFER_TYPE data_type // 配列に格納されるデータタイプ
);戻り値は、処理が成功した場合true、失敗した場合falseを返す
第1引数「index」はインジケータのインデックス番号を指定する。
SetIndexBuffer関数の第1引数「index」はインジケータのインデックス番号を指定します。
ここで記述されるインデックス番号と第2引数で指定する配列を紐づける事になります
『「BB」カスタムインジケ-タのMQL5 Source Fileの中、OnInit関数内の記述に注目する』セクションで記載したサンプルコード例を見ると
SetIndexBuffer関数が4回呼び出されており、
インデックス番号「0」には、配列「ExtMLBuffer」が、
インデックス番号「1」には、配列「ExtTLBuffer」が、
インデックス番号「2」には、配列「ExtMLBuffer」が、
インデックス番号「3」には、配列「ExtStdDevBuffer」が、
それぞれ紐づけられている事がわかります。
※ここで「BBのバッファ数は3つじゃなかったっけ?」と疑問に思った方がいらっしゃるかもしれませんが、その事については後程説明します。
※配列については以下の記事をご参照ください↓
・MQL5 EA講座 第18回「配列(Array)について」
第2引数「buffer」はインデックス番号に紐づける配列を指定する。
SetIndexBuffer関数の第2引数「buffer」はインデックス番号に紐づける配列を指定します
『「BB」カスタムインジケ-タのMQL5 Source Fileの中、OnInit関数内の記述に注目する』セクションで記載したサンプルコード例では
配列「ExtMLBuffer」、配列「ExtTLBuffer」、配列「ExtMLBuffer」、配列「ExtStdDevBuffer」が、
4回呼び出されているSetIndexBuffer関数の第2引数に記述されています。
それぞれの配列が第1引数に指定したインデックス番号に紐づけられ、MT5のチャートに表示されるバッファを形成します。
※配列「ExtMLBuffer」、配列「ExtTLBuffer」、配列「ExtMLBuffer」、配列「ExtStdDevBuffer」
はカスタムインジケ-タ「BB」のMQL5 Source File内グローバル領域(関数の外の領域)で事前に定義されています↓
//--- indicator buffer
double ExtMLBuffer[];
double ExtTLBuffer[];
double ExtBLBuffer[];
double ExtStdDevBuffer[];
第3引数「data_type 」はバッファのタイプを指定する。
SetIndexBuffer関数の第3引数「data_type 」はバッファのタイプを指定します。
バッファのタイプというのは、「配列に格納される計算結果をどのような形で利用するか?」という意味合いになります。
第3引数「data_type 」のデータ型はENUM_INDEXBUFFER_TYPEというMQL5で定めた定数リストとなっています。
初期値はチャートに計算値を描画する目的で利用する「INDICATOR_DATA」に設定されており、省略が可能です。
※初期値については↓の記事をご参照ください。
4回呼び出されているSetIndexBuffer関数のうち、3つまでは第3引数が省略された状態です。
これは3つのバッファは「INDICATOR_DATA」が設定されている状態、すなわち計算値を描画する目的で利用する、という意味に他なりません。
その一方で、4回目に呼び出されているSetIndexBuffer関数の第3引数には「INDICATOR_CALCULATIONS」という定数値が設定されています。
これはこの4回目に呼び出されているSetIndexBuffer関数で紐づけたバッファはインジケータの内部的な計算に用いるためのもので、チャートに描画する為のものではない、という事を示しています。
従って、カスタムインジケ-タ「BB」において、バッファは4つ使われているのですが、チャートに描画されるバッファは3つ、インジケータの内部的な計算に用いるバッファは1つという事になります。
(↓以下のような整理になります)
//--- define buffers
SetIndexBuffer(0,ExtMLBuffer);//チャートに描画する為のバッファ
SetIndexBuffer(1,ExtTLBuffer);//チャートに描画する為のバッファ
SetIndexBuffer(2,ExtBLBuffer);//チャートに描画する為のバッファ
SetIndexBuffer(3,ExtStdDevBuffer,INDICATOR_CALCULATIONS);//インジケータの計算に用いるバッファ
※enum列挙型については、↓の記事をご参照ください。
カスタムインジケ-タ「BB」に使われているバッファの数についての確認ができた所で、次はチャートに描画する為に用意されている3つのバッファがそれぞれその線を描画しているのかを確認する作業に移ります。
この記事の「ボリンジャーバンドとは?」セクションで書いたように、ボリンジャーバンドは中央ラインの移動平均線と上下2本のσラインで構成されています。
3つのバッファのうちどれが、移動平均線でどれがσラインかを確認するにはどうればよいでしょうか?
SetIndexBuffer関数が呼び出されている記述箇所のすぐ下を見ると、PlotIndexSetString関数という関数が呼び出されています。ここに注目してみましょう。
PlotIndexSetString(0,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Middle");
PlotIndexSetString(1,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Upper");
PlotIndexSetString(2,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Lower");
PlotIndexSetString関数について
PlotIndexSetString関数は、SetIndexBuffer関数によって紐づけられたチャート描画バッファに関して、「MT5のデータウィンドウに表示される情報名」を設定する関数です。
「MT5のデータウィンドウに表示される情報名」とは↓の画像で矢印をつけている部分にあたります。
PlotIndexSetString関数の引数と戻り値について
PlotIndexSetString関数の引数と戻り値は以下のようになっています。
bool PlotIndexSetString(
int plot_index, // チャットに描画するバッファのインデックス番号
int prop_id, // プロパティ識別子 「PLOT_LABEL」
string prop_value // データウィンドウに表示される情報名
);//戻り値は、処理が成功した場合true、失敗した場合falseを返す
第1引数「plot_index」にはチャットに描画するバッファのインデックス番号を指定する
PlotIndexSetString関数の第1引数「plot_index」には、チャートに描画するバッファのインデックス番号を指定します。
SetIndexBuffer関数の第1引数で指定した、描画用のインデックス番号がPlotIndexSetString関数の第1引数に記述される想定です。
第2引数「prop_id」にはENUM_PLOT_PROPERTY_STRINGで設定された定数値「PLOT_LABEL」を指定する
PlotIndexSetString関数の第2引数「prop_id」には、MQL5側で事前に定義したENUM_PLOT_PROPERTY_STRINGで設定された定数値「PLOT_LABEL」を指定します。
ENUM_PLOT_PROPERTY_STRINGはenum型なので、定数リストの形をとっているますが、定数リストには現状「PLOT_LABEL」しかありません。
従って、実質、PlotIndexSetString関数の第2引数には「PLOT_LABEL」しか記述されない、と考えて差し支えありません。
第3引数「prop_value」にはデータウィンドウに表示されるバッファの表示情報を指定する
PlotIndexSetString関数の第3引数「prop_value」には、データウィンドウに表示されるバッファの表示情報を指定します
この第3引数に記述されるのは文字列なので、データ型はstring型です。
※文字列データに関しては↓の記事をご参照ください。
カスタムインジケ-タ「BB」のソースコードにおけるPlotIndexSetString関数の第3引数部分に注目してみると・・・↓
PlotIndexSetString(0,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Middle");
PlotIndexSetString(1,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Upper");
PlotIndexSetString(2,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Lower");
インデックス番号「0」には、文字列情報”Bands(“+string(ExtBandsPeriod)+”) Middle”が、
インデックス番号「1」には、文字列情報”Bands(“+string(ExtBandsPeriod)+”) Upper”が、
インデックス番号「2」には、文字列情報”Bands(“+string(ExtBandsPeriod)+”) Lower”が、
それぞれ対応付けられているのが分かります。
※なお、文字列内の
string(ExtBandsPeriod)
という表記は、型変換(タイプキャスト)と呼ばれるものです。型変換(タイプキャスト)については↓の記事をご参照ください
変数「ExtBandsPeriod」はグローバル領域(関数の外の領域)で宣言されたint型の変数です。
変数「ExtBandsPeriod」はカスタムインジケ-タ「BB」の計算期間を指定する為に使われています。これを文字列情報であるstring型に変換する為に、変数「ExtBandsPeriod」に予約語であるstringが記述されています。
カスタムインジケ-タの描画バッファのインデックス番号を推測する
ここまで解説してきた中での、
「ボリンジャーバンドとは?」セクション、
「SetIndexBuffer関数について」セクション、
「PlotIndexSetString関数について」セクションの内容をおさらいすると、
ボリンジャーバンドは中央の移動平均線と、その移動平均線から上下2本に描画された標準偏差の合計3本のラインで形成されたインジケータである、という事、そして
SetIndexBuffer関数とPlotIndexSetString関数によって、
インデックス番号「0」のバッファは→”Bands(“+(指定期間)+”) Middle”というデータウィンドウ表示名が、
インデックス番号「1」のバッファは→”Bands(“+(指定期間)+”) Upper”というデータウィンドウ表示名が、
インデックス番号「2」のバッファは→”Bands(“+(指定期間)+”) Lower”というデータウィンドウ表示名が、それぞれ紐づけられている事がわかりました。
カスタムインジケ-タ「BB」は実質ボリンジャーバンドと同じであり、またデータウィンドウ表示名に「Middle」「Upper」「Lower」という名前が付与されている事から、チャートに描画されているバッファ番号は以下のようになっていることが推測できます↓
推測通り、実際に画像のような紐づけになっているのか確認してみましょう。
カスタムインジケ-タの描画バッファとインデックス番号との紐づけを確認する
カスタムインジケ-タの描画バッファとインデックス番号との紐づけを確認するには、MT5で以下のような操作を行います。
1:カスタムインジケ-タが挿入されているチャートを右クリックし、メニューから「インジケータリスト」を選択→該当のインジケータ(ここでは「BB」)を選択する。
2:「プロパティ」メニューを選択し、インジケータのプロパティ画面から「カラー」タブを選択する。
3:「カラー」タブ内には、インジケータの描画バッファの一覧が表示されており、線の太さや線のカラーを変更する事が出来るようになっているので、線の太さや色を変更してみて、描画バッファのインデックス番号が推測通りのものかどうかを確認する。
↑上記1-3の手順を試したものが下記の動画になります。
インデックス番号「0」のバッファはデータウィンドウに表示される情報名にMiddleという単語がはいっていることから、中央ラインである移動平均線である、という想定をしました。そこでBands(20)Middle欄の線の太さを1から5に変更してみました。すると、想定通り中央ラインの線の太さが変わりました。
同じように、インデックス番号「1」=Bands(20)Upperの線の太さを1から5に変更したところ、上方ラインの太さが変わり、インデックス番号「2」=Bands(20)Lowerの線の太さを1から5に変更したところ、下方ラインの太さが変わる、というこれも想定通りの結果が得られました。
バッファの数や描画バッファとインデックス番号との紐づけ状況を確認する事により、EA開発の際にカスタムインジケータを利用できるようになる
ここまで読んできて、
「一体これを知る事によって、なにか良い事でもあるの?」
と疑問に思われた方も多いかと思います。
実は、この「カスタムインジケ-タにおける描画バッファの構成を把握する」作業を行う事によって、EAを自作する際にカスタムインジケ-タ情報をロジックに簡単に取り込めるようになるのです。
今回と次回の講座内容を理解することによって、MT5に実装済みの組み込みインジケータだけではなく、インターネット上で共有されていたり、購入してきたカスタムインジケ-タもEAに実装できるようになり、より一層EA開発の可能性が広がる事になるでしょう。
詳しい事は次回講座でiCustom関数というものを解説する際に、お伝えしていきたいと思いますので、楽しみにお待ちください。
カスタムインジケータ「BB」の全体コード記述
最後に、カスタムインジケ-タ「BB」の全体コード記述を掲載しておきます。
MT5に標準実装されているものなので、普通にメタエディタから確認できるものではありますが、
今回は、この中から必要な箇所に絞って解説を行ったので、今回の記事を読み終わった後に、改めて見直すとより理解が深まるのではないかと思います。
//+------------------------------------------------------------------+
//| BB.mq5 |
//| Copyright 2000-2023, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2023, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property description "Bollinger Bands"
#include <MovingAverages.mqh>
//---
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots 3
#property indicator_type1 DRAW_LINE
#property indicator_color1 LightSeaGreen
#property indicator_type2 DRAW_LINE
#property indicator_color2 LightSeaGreen
#property indicator_type3 DRAW_LINE
#property indicator_color3 LightSeaGreen
#property indicator_label1 "Bands middle"
#property indicator_label2 "Bands upper"
#property indicator_label3 "Bands lower"
//--- input parametrs
input int InpBandsPeriod=20; // Period
input int InpBandsShift=0; // Shift
input double InpBandsDeviations=2.0; // Deviation
//--- global variables
int ExtBandsPeriod,ExtBandsShift;
double ExtBandsDeviations;
int ExtPlotBegin=0;
//--- indicator buffer
double ExtMLBuffer[];
double ExtTLBuffer[];
double ExtBLBuffer[];
double ExtStdDevBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- check for input values
if(InpBandsPeriod<2)
{
ExtBandsPeriod=20;
PrintFormat("Incorrect value for input variable InpBandsPeriod=%d. Indicator will use value=%d for calculations.",InpBandsPeriod,ExtBandsPeriod);
}
else
ExtBandsPeriod=InpBandsPeriod;
if(InpBandsShift<0)
{
ExtBandsShift=0;
PrintFormat("Incorrect value for input variable InpBandsShift=%d. Indicator will use value=%d for calculations.",InpBandsShift,ExtBandsShift);
}
else
ExtBandsShift=InpBandsShift;
if(InpBandsDeviations==0.0)
{
ExtBandsDeviations=2.0;
PrintFormat("Incorrect value for input variable InpBandsDeviations=%f. Indicator will use value=%f for calculations.",InpBandsDeviations,ExtBandsDeviations);
}
else
ExtBandsDeviations=InpBandsDeviations;
//--- define buffers
SetIndexBuffer(0,ExtMLBuffer);//チャートに描画する為のバッファ
SetIndexBuffer(1,ExtTLBuffer);//チャートに描画する為のバッファ
SetIndexBuffer(2,ExtBLBuffer);//チャートに描画する為のバッファ
SetIndexBuffer(3,ExtStdDevBuffer,INDICATOR_CALCULATIONS);//インジケータの計算に用いるバッファ
//--- set index labels
PlotIndexSetString(0,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Middle");
PlotIndexSetString(1,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Upper");
PlotIndexSetString(2,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Lower");
//--- indicator name
IndicatorSetString(INDICATOR_SHORTNAME,"Bollinger Bands");
//--- indexes draw begin settings
ExtPlotBegin=ExtBandsPeriod-1;
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtBandsPeriod);
PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,ExtBandsPeriod);
PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,ExtBandsPeriod);
//--- indexes shift settings
PlotIndexSetInteger(0,PLOT_SHIFT,ExtBandsShift);
PlotIndexSetInteger(1,PLOT_SHIFT,ExtBandsShift);
PlotIndexSetInteger(2,PLOT_SHIFT,ExtBandsShift);
//--- number of digits of indicator value
IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
}
//+------------------------------------------------------------------+
//| Bollinger Bands |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double &price[])
{
if(rates_total<ExtPlotBegin)
return(0);
//--- indexes draw begin settings, when we've recieved previous begin
if(ExtPlotBegin!=ExtBandsPeriod+begin)
{
ExtPlotBegin=ExtBandsPeriod+begin;
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtPlotBegin);
PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,ExtPlotBegin);
PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,ExtPlotBegin);
}
//--- starting calculation
int pos;
if(prev_calculated>1)
pos=prev_calculated-1;
else
pos=0;
//--- main cycle
for(int i=pos; i<rates_total && !IsStopped(); i++)
{
//--- middle line
ExtMLBuffer[i]=SimpleMA(i,ExtBandsPeriod,price);
//--- calculate and write down StdDev
ExtStdDevBuffer[i]=StdDev_Func(i,price,ExtMLBuffer,ExtBandsPeriod);
//--- upper line
ExtTLBuffer[i]=ExtMLBuffer[i]+ExtBandsDeviations*ExtStdDevBuffer[i];
//--- lower line
ExtBLBuffer[i]=ExtMLBuffer[i]-ExtBandsDeviations*ExtStdDevBuffer[i];
}
//--- OnCalculate done. Return new prev_calculated.
return(rates_total);
}
//+------------------------------------------------------------------+
//| Calculate Standard Deviation |
//+------------------------------------------------------------------+
double StdDev_Func(const int position,const double &price[],const double &ma_price[],const int period)
{
double std_dev=0.0;
//--- calcualte StdDev
if(position>=period)
{
for(int i=0; i<period; i++)
std_dev+=MathPow(price[position-i]-ma_price[position],2.0);
std_dev=MathSqrt(std_dev/period);
}
//--- return calculated value
return(std_dev);
}
//+------------------------------------------------------------------+
まとめ
今回はカスタムインジケ-タについて解説しました。
まず、「そもそもカスタムインジケ-タとは何か?」という基本から説明を行いまた。
※詳細は「カスタムインジケ-タとは?→MT5に標準実装されていない特別仕様のインジケータのこと。」セクションをご覧ください。
その具体例として、MT5に実装されているカスタムインジケ-タ「BB」を取り上げ、そのサンプルコードを見ながら、要所要所のコード記述と、重要な役割を果たす関数(SetIndexBuffer関数とPlotIndexSetString関数)についての説明を行いました。
また、カスタムインジケ-タの情報をEAに実装するのにあたり、カスタムインジケ-タで使われているバッファ数や、描画バッファとインデックス番号の紐づけ状況を把握する事の必要性について解説し、その確認方法についてもお話しました。
※詳しくは今回の記事内、
「MT5のデータウィンドウから、カスタムインジケ-タのバッファ数を確認する」セクション
「カスタムインジケ-タの描画バッファのインデックス番号を推測する」セクション
をご参照ください。
今回は以上とさせていただきます。次回は、今回解説したカスタムインジケ-タに関する前提を元にiCustom関数についての解説を行います。
最後までお読みいただきありがとうございました。
※今回の記事内容を理解するにあたっては以下の記事も参考になるかと思います。
パラボリックSARを例にとり、インジケータのコード記述を一気通貫で、徹底解説していますので、インジケータだけではなく、今までの講座記事で学んできたことを網羅的に復習できる絶好の機会にもなります↓
・【徹底解説】MQL5ソースコード解体新書-パラボリック編-【MQL勉強用】