恥は/dev/nullへ by 初心者

プログラミング素人がのろのろと学んだことをつづっています♪

[MQL5]CopyBuffer関数に登場するバッファ番号とは?

インジケーターを作成する場合などに使うCopyBufferという関数には、引数の1つとして buffer_num(バッファ番号)というものがあります。


CopyBufferの書式の1つを引用すると

int CopyBuffer( 
    int       indicator_handle,     // indicator handle 
    int       buffer_num,           // indicator buffer number 
    int       start_pos,            // start position
    int       count,                // amount to copy 
    double    buffer[]              // target array to copy 
);

となっており、buffer_num の行には「indicator buffer number」というコメントが書かれています。

CopyBuffer関数のヘルプを初めて読んだ時は、この buffer_numが何なのかよく分かりませんでした。そこで、ネット情報を調べた結果、 各インジケーター関数が持っているバッファの番号である(SetIndexBufer関数内で指定したバッファ 番号ではない)ことが分かりました。


このことに気づかせてくれたのは、以下のページに載っていたやり取りでした。 https://www.mql5.com/en/forum/319420


上記ページにおいて、質問者は2つの移動平均線をチャートに表示しようとしています。そして、質問者が投稿したコードには

// 行数を減らすために編集してあります。

int copiedAmount_1 = CopyBuffer(handle_1, 0, 0, rates_total, buffer_1);
        (中略)
int copiedAmount_2 = CopyBuffer(handle_2, 1, 0, rates_total, buffer_2);

という部分があり、最初に登場するCopyBuffer関数の第2引数は「0」で、次に登場するCopyBuffer関数の第2引数は「1」になっています。


このコードに対して、他の人が「iMA関数には1つのバッファしかない」という趣旨の返信をしていました。 これは、バッファ番号は0から始まるので、1つのバッファしか持たないiMA関数のバッファ番号として 1 はおかしい(iMA関数のバッファ番号は 0 だけ)という意味です。

このことはインジケーター関数のヘルプを読むことで確認することができます。


iMA関数のヘルプを見てみましょう。すると、次のようにiMA関数には1つのバッファしかないことが記載されています。

The function returns the handle of the Moving Average indicator. It has only one buffer.  


ついでに、iStochastic関数のヘルプを見ると

Note
  The buffer numbers: 0 - MAIN_LINE, 1 - SIGNAL_LINE.  

という記述がありました。このことから、iStochastic関数には2つのバッファがあることが分かります。
ストキャスティクスのメインラインの値を取得する場合はCopyBufferの第2引数に 0 を指定し、 シグナルラインの値を取得する場合はCopyBufferの第2引数に 1 を指定することになります。


最後に、iBands関数のヘルプを見てみましょう。

Note
  The buffer numbers are the following: 0 - BASE_LINE, 1 - UPPER_BAND, 2 - LOWER_BAND  

という記述があることから、iBands関数には3つのバッファがあると分かります。

ボリンジャーバンドのミドルラインの値を取得する場合はCopyBuffer関数の第2引数に 0 を指定し、 アッパーラインの値を取得する場合はCopyBuffer関数の第2引数に 1 を指定し、 ロウアーラインの値を取得する場合はCopyBuffer関数の第2引数に 2 を指定することになります。


indicator buffer という表現が紛らわしいような?

CopyBuffer関数のヘルプにおいて、「indicator buffer」という表現が異なる意味合いで複数回登場することが紛らわしいと感じました。


冒頭に引用したCopyBuffer関数の書式に登場する「indicator buffer number」の「indicator」という語は iMA関数やiStochastic関数など、特定のテクニカル指標を計算する関数を指しています。よって、この「indicator buffer」は、「特定のテクニカル指標を計算する関数に付属しているバッファ」という意味です。


その一方で、CopyBuffer関数のヘルプには以下の文章も登場します。

When copying the yet unknown amount of data, it is recommended to use
a dynamic array as a buffer[] recipient buffer, because the CopyBuffer() 
function tries to allocate the size of the receiving array to the size of 
the copied data. If an indicator buffer(array that is pre-allocated for 
storing indicator values by the SetIndexBufer() function) is used as 
the buffer[] recipient array, partial copying is allowed.

4行目に「indicator buffer」という表現がありますね。
それに続く括弧の中を読むと、「indicator buffer」の説明として「インジケーターの値を格納するために SetIndexBufer関数によって事前に割り当てられた配列」と書かれています。


すなわち、この文章においては、先述した「indicator buffer」(特定のテクニカル指標を計算する関数が持つバッファ)とは違う意味で、「indicator buffer」という表現が使われています。このことが、場合によっては、ヘルプを読む人に誤解を与えているのではないかと感じました。


なお、上記の文章の大雑把な内容は以下のとおりです。

もし複製するデータの量(サイズ)がまだ分からないのなら、データを受け取る側のバッファ配列には動的配列を使うとよい。 というのも、CopyBuffer関数は、受け側の配列のサイズと同じ量のデータを複製しようとするからである。
(備考)受け取る側の配列のサイズがコピー量の基準となる。


一方、受け側の配列がインジケーターバッファ(事前にSetIndexBuffer関数を使って割り当てた配列で、インジケーターの値を保存するためのもの )ならば、部分的な複製をすることができる。

(備考)部分的な複製とは、受け取る側の配列のサイズより少ない量を複製すること。