MQL5でのインディケーター の呼び方
はじめに
MQL5ではインディケーターを呼び出す方法がいくつかあり、ほとんどがIndicatorCreate() と iCustom() 関数を使って実行されます。 さらに、 これらの関数はインディケーター ハンドルを戻すだけで、さらなるインディケーターの仕事はそれを通して行われます。 ではハンドルとは何か?どのようにIndicatorCreate() と iCustom() 関数を扱うのか?そしてあなたのエキスパートがどのようにインディケーター データを入手するのか?これらの質問に本記事ですべて答えます。
ソースファイル作成
我々のエキスパートを開始するにあたって、そのソースファイルを作りましょう。MetaEditor4同様、 File -> New メニューからMQL5 ウィザードを呼び出すことによってこれを頻繁に行います。最初のステップでは、Expert Advisor を選択しNextを押します。
第二のステップでは、名前、著者の連絡詳細、 Expert Adviserの入力パラメーターの入力ができます。アドバイザーの名前 (必須項目) と Author(著者)だけ入力します。必要な場合、入力パラメーターは後で直接プログラムコードの中で追加できます。
Finishをクリックした後、 ウィザードが以下のソースコードを作成します。:
//+------------------------------------------------------------------+ //| SampleMQL5.mq5 | //| Copyright KlimMalgin | //| | //+------------------------------------------------------------------+ #property copyright "KlimMalgin" #property link "" #property version "1.00" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+
ソースファイル構造
エキスパートのソースファイル構造を簡単に考察して次に行きましょう。
プログラムコードはヘッダーで始まります。それはファイル名と著者を含むコメントです。タイトルの後、エキスパートのプログラムプロパティ (#property) が来ます。ここで、プログラムバージョン、著者名、あなたのページへのリンクが、前に入力していると自動で表示されます。 ロパティ説明の後、入力パラメーターが指定され(我々はまだそれらを指定していません)、グローバル変数が宣言されます。
プロパティはメインMQL5-fileで設定されるべきです。付属ファイルからのすべてのプロパティは無視されます!
次に以下を処理する3つの関数が来ます。:
- OnInit() - エキスパート開始時、文字変更時、または期間変更時でエキスパートが設定されている時に一回起動。
- OnDeinit(const int reason) - エキスパートが仕事を終えた時または再初期化の実行時これもまた一回起動。reason パラメータは非初期化の理由コードを含みます。
- OnTick() - チャートで新しい tickを受信した時、エキスパートが添付されているところで毎回開始。
インディケーター接続
MQL5ではインディケーターとの取組方法が変化しました!MQL4では、特定のバーのインディケーター値を入手するために、そのバーのインデックスが iCustom() 関数にパラメータとして渡されました。今では、インディケーターバッファー値を入手せず、ハンドルを入手します。そしてこのハンドラーを使い、 CopyBuffer()と呼ばれる特別な関数を使って、インディケーター値を 特定のインターバルで 入手できます。ではハンドルとは何か?
ハンドルはユニーク識別子で、あるインディケーターと共に使うために作成されます。整数で表され、 変数の int タイプに保管されます。MQL5ではインディケーターハンドルを入手する2つの方法があります。
- インディケーターCreate() 関数の呼び出し。成功の場合インディケーターハンドルを戻し、失敗の場合は -1 。
- テクニカルインディケーター 関数の1つの呼び出し。それらの実行の結果は似ています。
両方の方法は同等に有効で、どちらを使うかはあなた次第です。 両方の方法を詳細に考えましょう。
インディケーターCreate() 関数を使ってインディケーターハンドルを入手
そのため、 IndicatorCreate() 関数の正常な実行の結果として、インディケーターハンドルを入手します。そして失敗の場合、その関数は -1に等しい INVALID_ハンドル 値を戻します。もし、 呼ばれまたインディケーター がパラメータを持つなら、その関数の呼び出しの前に 、MqlParam タイプパラメータの配列を記入しなければなりません。この配列の各エレメントは4つのフィールドを含むMqlParam タイプの構造として表されています。 この構造の最初のフィールドは、残りの3つのフィールドの内どれが インディケーターのパラメータとして使われたか示します。
移動平均とParabolicSAR インディケーターのハンドルを作成するコードを書きましょう。グローバル変数の宣言から始めます。それはハンドルを保管し、インディケーターのパラメータを設定するためMqlParam タイプ の配列を宣言します。:
int MA1 = 0, // Declaring variable to store fast MA handle MA2 = 0, // Declaring variable to store slow MA handle SAR = 0; // Declaring variable to store SAR handle MqlParam params[]; // Array for storing indicators parameters
エキスパートプロパティ定義後すぐにこのコードが置かれなければなりません。.
これで、変数が宣言される時、パラメータ配列を記入し、IndicatorCreate() 関数を呼び出すことができます。インディケーターは各tick毎ではなくプログラムの始めで一回作成されるため、 OnInit() 関数でこれを行う方がいいです!
パラメータ 配列を記入し、最初の インディケーターを呼びましょう。:
int OnInit() { //--- // Setting the params size equal to number of called indicator parameters ArrayResize(params,4); // Setting the period of fast MA params[0].type =TYPE_INT; params[0].integer_value=5; // Offset params[1].type =TYPE_INT; params[1].integer_value=0; // Calculation method: simple averaging params[2].type =TYPE_INT; params[2].integer_value=MODE_SMA; // Price type for calculation: the Close prices params[3].type =TYPE_INT; params[3].integer_value=PRICE_CLOSE; MA1 = IndicatorCreate(Symbol(), // Symbol used to calculate the indicator 0, // Timeframe. 0 means current IND_MA, // Indicator type from the ENUM_INDICATOR enumeration 4, // Number of parameters passed in the params array params // Parameters array ); //--- return(0); }
params 配列が動的配列として宣言されました。つまり、配列のサイズは括弧内に設定されていなかったので、使用前にサイズを設定しなければなりません。 ArrayResize() 関数を使って、サイズを、配列に転送するパラメータの数に等しく定義します。 移動平均では4つのパラメータが必要です。
最初のパラメータは MA 期間です。それは整数として設定されます。そのため, 最初のパラメータのタイプ フィールドにTYPE_INT 値を設定し、それによって我々の IndicatorCreate() 関数が、integer_value フィールドから値が取られたはずであることを「理解」します。移動平均の全てのパラメータは int タイプを持つので、それらは適宜設定されます。
配列が記入されれば、IndicatorCreate() 関数を呼び出すことができます。その出力はMA1 変数に保管されます。その関数を呼び出すことは難しくないはずで、5つのパラメータがそれに転送されなければならないだけです。:
- 最初は作業ツールの名前です。Symbol() 関数はエキスパートが実行している現在ツールの名前を戻します。
- 第2のパラメータはインディケーター 値がカウントされる タイムフレームを指定します。
- 第3のパラメータは呼び出されるインディケーターのタイプ を指定します。
- 第4のパラメータはparams 配列に渡されるパラメータの数を指定します。
- そして最後に第5パラメータはインディケーターの入力パラメーター配列 です。
これだけです!速いMA ハンドルを手に入れたのでスローMA と SAR インディケーターハンドルを入手しなければなりません。結果、 OnInit() 関数はこのように見えます。:
int OnInit() { //--- // Setting the params size equal to number of called indicator's parameters ArrayResize(params,4); //* Calling indicators * //*************************** // Setting the period of fast MA params[0].type =TYPE_INT; params[0].integer_value=5; // Offset params[1].type =TYPE_INT; params[1].integer_value=0; // Calculation method: simple averaging params[2].type =TYPE_INT; params[2].integer_value=MODE_SMA; // Price type for calculation: the Close prices params[3].type =TYPE_INT; params[3].integer_value=PRICE_CLOSE; MA1 = IndicatorCreate(Symbol(), 0, IND_MA, 4, params); // Setting the period of slow MA params[0].type =TYPE_INT; params[0].integer_value=21; // Offset params[1].type =TYPE_INT; params[1].integer_value=0; // Calculation method: simple averaging params[2].type =TYPE_INT; params[2].integer_value=MODE_SMA; // Price type for calculation: the Close prices params[3].type =TYPE_INT; params[3].integer_value=PRICE_CLOSE; MA2 = IndicatorCreate(Symbol(), 0, IND_MA, 4, params); // Changing array size to store the SAR indicator parameters ArrayResize(params,2); // Step params[0].type =TYPE_DOUBLE; params[0].double_value = 0.02; // Maximum params[1].type =TYPE_DOUBLE; params[1].double_value = 0.2; SAR = IndicatorCreate(Symbol(), 0, IND_SAR, 2, params); //--- return(0); }
スロー MA ハンドルを入手 するには、期間を5から21に変えるだけです。そして、ParabolicSAR が呼ばれるとき、浮動小数点数 (倍精度) がそのパラメータとして転送されます。配列を記入する時これを考慮し、タイプ フィールド内の TYPE_DOUBLE とパラメータ自身を double_value フィールドにそれぞれ置かなければなりません。 また、 SARは2つのパラメータだけを要求するので、配列サイズが配列Resize()を使って2 に変更します。
今のところIndicatorCreate() 関数はおしまいです。クラスのライブラリがインディケーターと一緒に作成される時、私の意見では、このインディケーター呼び出し方法がオブジェクト指向アプローチの中で最も便利です。このライブラリは大きなスケールのプロジェクトを処理しやすくします。また、クイックエキスパートの作成とテストについては、以下の方法を使用するのがベストです。
テクニカルインディケーター 関数を使ってハンドルを入手
インディケーター ハンドルの入手を可能にする第二の方法は、 テクニカルインディケーター 関数の1つを呼び出すことです。これらの関数のそれぞれはMetaTrader 5の標準インディケーターの1つのハンドルを入手することを目的にしています。それらはすべてインディケーターの目的に応じたパラメータの一式を持っています。例えば、CCI インディケーターは iCCI() 関数が呼ばれ、以下のように見えます。:
CCI = iCCI( Symbol(), // symbol name PERIOD_CURRENT, // period 20, // averaging period PRICE_CLOSE // price type or handle );
他のインディケーターハンドルは最後のパラメータとして、価格タイプではなくテクニカルインディケーター 関数に提出できます。そして、このように呼ばれたインディケーターは価格データではなく、インディケーターデータを使って計算されます。
カスタムのものを含めどんなインディケーターも呼び出すことができるので iCustom() 関数はテクニカルインディケーター 関数の中で特定の興味を引きます。 iCustom() 関数を使って上記に似たコードを書きましょう。:
int OnInit() { //--- MA1 = iCustom(NULL,0,"Custom Moving Average", 5, // Period 0, // Offset MODE_SMA, // Calculation method PRICE_CLOSE // Calculating on Close prices ); MA2 = iCustom(NULL,0,"Custom Moving Average", 21, // Period 0, // Offset MODE_SMA, // Calculation method PRICE_CLOSE // Calculating on Close prices ); SAR = iCustom(NULL,0,"ParabolicSAR", 0.02, // Step 0.2 // Maximum ); //--- return(0); }
エキスパート開始中に一旦ハンドルを入手するのがベストということを念頭に置き、OnInit() 関数内で呼び出しましょう。
iCustom() 関数は以下のパラメータを含みます。:
- データがインディケーター計算に使われる作業ツールの名前。NULL - 現在ツールを意味。NULLではなくSymbol () を使うことができます。あまり違いはありません。Symbol()の場合、金融商品の名前が iCustom()に転送されますが、NULLの場合、iCustom() が金融商品自身を見つけます。
- チャート期間。 期間を指定するために、事前定義チャートタイムフレームと現在タイムフレームを参照する0 を使用できます。
- インディケーター名。 呼ばれたインディケーター はコンパイルされ、「MQL5\インディケーター\」フォルダーまたはそのサブフォルダにあるべきです。
- 残りのパラメータ。 これらの値は入力パラメーターとして呼ばれたインディケーターのために使用されるので、それらのタイプとその連なりがお互いマッチなければなりません。 もし、指定されていないとデフォルト値が使用されます。
前述の通り、経験のあるライブラリがない場合、この方法でインディケーターを使うのがより便利です。これでハンドル受信時、インディケーター 値の取組を開始することができます!
インディケーターデータの入手
MQL5でインディケーターデータを使用する際のいい点は欲しいインターバルでだけデータが入手できる機会ができたことです。. インターバルは様々な方法で設定できます。 :
- 選択されたバーに関連のある指定バー数の入手。
- 選択されたデータに関連のある指定バー数の入手。
- あるインターバル時間(つまり、開始と終了日付を指定 )においてデータをインディケーターから 入手。
インディケーターの日付を読むために CopyBuffer() 関数が使用されます。どのデータ入手方法が使用されるかは、どの入力パラメータがこの関数に転送されるかによります。
インディケーター データ (それらのハンドルは前に入手) を配列にコピーするコードを書きましょう。 :
void OnTick() { //--- // Dynamic arrays to store indicators values double _ma1[], _ma2[], _sar[]; // Setting the indexing in arrays the same as in timeseries, i.e. array element with zero // index will store the values of the last bar, with 1th index - the last but one, etc. ArraySetAsSeries(_ma1, true); ArraySetAsSeries(_ma2, true); ArraySetAsSeries(_sar, true); // Using indicators handles, let's copy the values of indicator // buffers to arrays, specially prepared for this purpose if (CopyBuffer(MA1,0,0,20,_ma1) < 0){Print("CopyBufferMA1 error =",GetLastError());} if (CopyBuffer(MA2,0,0,20,_ma2) < 0){Print("CopyBufferMA2 error =",GetLastError());} if (CopyBuffer(SAR,0,0,20,_sar) < 0){Print("CopyBufferSAR error =",GetLastError());} //--- }
今、各 tickでインディケーター データが変化し更新されなければならないので、我々の作業はすべてOnTick() 関数に集中します。
最初に、 各インディケーターバッファーの動的配列を宣言しましょう 。私の意見では、もし配列インデックスが時系列と同じようであるならインディケーター データと働く方がより便利です。つまり、配列エレメント0で最後のバーデータがあり、ナンバー1 エレメントでは - 最後から1つ前など。インデックス方法は ArraySetAsSeries() 関数を使って設定されます。
インデックス方法が設定されると、配列記入を開始できます。各インディケーターの計算には、 CopyBuffer() 関数を以下のパラメータ一式と共に呼び出します。:
- 欲しいデータであるインディケーター ハンドル。
- インディケーターバッファー ナンバー。MA とSAR インディケーターは1つのバッファーを持つので、それらを0として設定します。もし、バッファーが一つ以上ある場合、第二がナンバー1で、第三がナンバー2など。
- カウントがスタートする初期バー
- コピーしたいバー数 。
- データがコピーされる配列{/0} 。
正常の呼び出しで、CopyBuffer() 関数はコピーされたエレメントの数を戻し、失敗の場合 -1を戻します。失敗の場合、エラーを追跡しなければなりません。 もし、戻された値が0未満なら、エラーをエキスパートログに Print() 関数を使って書きます。
結論
今では、我々のンディケーターとの取組は終わりにはまだまだです。本記事はデータアクセスの基本方法を取り上げました。そして利便性からMQL5でかなりいいレベルで実装されたオブジェクト指向アプローチを使うのがベストです!
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/43
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索