MT4インジケータの開発で中心的な存在となる時系列配列ですが、他のプログラミング言語には見られない配列でMQL独特の仕様となっています。インジケータを作るなら必ず知らなければならないこの配列の挙動について今回解説してみようと思います。
まず下記インジケータ雛形の行頭付近で宣言しているBuffer1、Buffer2は宣言時点では通常の配列ですが、赤字にしたSetIndexBufferで時系列配列に転化させています。
なお全ての指標バッファを表示させる必要はなく、内部プログラムでしか使わないようにさせることもできます。
以下の雛形では2つの指標バッファを宣言していますが、1つは内部プログラム用にしています。
これは2行目の”#property indicator_buffers”で指定することができます。
#property indicator_chart_window //チャートウィンドウに表示 #property indicator_buffers 1 //表示する指標バッファの数を設定 double Buffer1[]; //表示用指標バッファ double Buffer2[]; //内部利用用指標バッファ int OnInit() { IndicatorBuffers(2); //全体の指標バッファ数を設定 //指標バッファへの割り当て(時系列配列化) SetIndexBuffer(0, Buffer1); SetIndexBuffer(1, Buffer2); return(INIT_SUCCEEDED); } int OnCalculate( const int rates_total, //指標バッファ(時系列配列)の要素数=バーの本数 const int prev_calculated, //1つ前のティックのOnCalculate戻り値 const datetime &time[], //時間配列 const double &open[], //始値配列 const double &high[], //高値配列 const double &low[], //安値配列 const double &close[], //終値配列 const long& tick_volume[], //ティック発生数 const long& volume[], //通常使用しない const int& spread[]) //通常使用しない { //ティック発生毎に実行 return rates_total; }
時系列配列の場合、新しいバーが1本増えるとそれまでの配列要素のインデックスは1つ繰り上がります。
以下の例では元々Buffer[0]に入っていた”100.001″という値は、新しいバーが作成されるとBuffer[1]に自動的に再配置されます。これにより最新バーのインデックスは常に0となるわけです。
これを知らないでインジケータの値を取得しようとして固定のインデックスを指定していると想定とは違う値を取得してしまう羽目になります。
<バー本数がN本の時の時系列配列の中身>
Buffer[0] = 100.001
Buffer[1] = 100.002
…
Buffer[N-1] = 101.000
↓
<バー本数がN+1本の時の時系列配列の中身>
Buffer[0] = 100.000
Buffer[1] = 100.001
Buffer[2] = 100.002
…
Buffer[N] = 101.000
余談ですがインジケータ作成においてOnCalculateの引数についての理解も大切です。特にrates_totalとprev_calculatedはちゃんと知っておく必要があるかと思います。
rates_totalはチャート全体のバー本数と覚えておけば事足りるかと思いますが、prev_calculatedは上記コメントにも書きました通り1つ前のティックのOnCalculate戻り値と理解しておくことが肝要です。
prev_calculatedはチャートにインジケータを適用した瞬間は0になります。OnCalculateの戻り値をrates_totalにしておくと1つ前のティックでのバー本数を次のティックのprev_calculatedで受け取ることができます。
これによりrates_totalとprev_calculatedを比較して新しいバーが発生したタイミングをはかるといったことができます。