MQLでよく出現するarray out of rangeとは?

インジケーター作成時に、コンパイルができたのにいざMT4に適用してみると何も表示されないなどのトラブルがあります。

そんな時にターミナルウィンドウのエラーを確認すると、たまに「array out of range」とでていますが、今回はこのエラーが発生する主な原因と対策を解説します!
array out of rangeは配列処理のエラー

「array out of range」は、配列の定義された領域(サイズ)を超えたインデックスへアクセスしようとした際に発生するエラーです。例えば、ローソク足(Bars)が300本しかない状態にもかかわらず、Open[300](301本目の値)を参照しようとした場合などに発生します。
このエラーは、ローソク足データを参照する際や、インジケーターの計算用Buffer(配列)へ値を格納・参照する際に頻出します。
array out of rangeの原因①「存在しない過去足の値を取りに行っている」
MQL4では配列のインデックスが「0」から始まります。そのため、チャート上の全ローソク足本数が Bars 本である場合、指定できる最大のインデックスは Bars - 1 となります。
初心者がよくやってしまうミスとして、最古のローソク足の始値を取得しようとして Open[Bars] と記述してしまうケースがあります。正しくは Open[Bars - 1] です。
また、移動平均線(MA)のように過去数本分のデータを参照するテクニカル指標を計算する際は、特に注意が必要です。期間60のSMAを計算する場合、最低でも60本分のローソク足が必要になるため、古い足の末端(Bars - 60 を超える領域)では参照エラーが発生します。
forループでの適切なガード処理
期間60の移動平均線をforループで計算する場合は、参照インデックスが Bars - 1 を超えないよう、以下のように安全に制御します。
int counted = IndicatorCounted();
if(counted < 0) return(-1);
if(counted > 0) counted–; // 直近足の再計算用
int limit = Bars – counted;
// ローソク足が計算期間(60本)未満の場合は処理をスキップ
if(Bars < 60) return(0);
// 初回計算時、配列上限を超えないように上限をガードする
if(limit > Bars – 60) limit = Bars – 60;
for(int i = limit – 1; i >= 0; i–) {
Buf0[i] = iMA(Symbol(), PERIOD_CURRENT, 60, 0, MODE_SMA, PRICE_CLOSE, i);
}
このようにあらかじめ計算上限(limit)を配列の参照可能範囲内に制限しておくことで、array out of range を防止できます。
array out of rangeの原因②「Buffer(配列)が宣言・割り当てされていない」
インジケーターでラインや矢印を表示する場合、配列を宣言するだけでなく、プログラム側へ「使用するBufferの数」を正しく通知する必要があります。
1. 配列の宣言
double Buf0[];
double Buf1[];
double Buf2[];
double Buf3[];
2. Buffer数のプロパティ宣言
#property indicator_buffers 4
よくあるトラブルとして、開発の途中で新しいライン(`Buf4[]`)を追加した際、配列だけを増やして `#property indicator_buffers` の数値を更新し忘れるケースがあります。
#property indicator_buffers 4 // ← ここが4のままになっている!
double Buf0[];
double Buf1[];
double Buf2[];
double Buf3[];
double Buf4[]; // 新しく追加
この状態のまま `Buf4[i] = …` のように値を代入しようとすると、メタトレーダー側でバッファ領域がメモリ上に割り当てられていないため、array out of range が発生します。
解決手順:Buffer数とSetIndexBufferの設定
配列を増やした際は、必ずプロパティの数を更新し、`OnInit()` 内で `SetIndexBuffer()` を呼び出してマッピングを行ってください。
#property indicator_buffers 5 // 5に変更
double Buf0[];
double Buf1[];
double Buf2[];
double Buf3[];
double Buf4[];
int OnInit() {
SetIndexBuffer(0, Buf0);
SetIndexBuffer(1, Buf1);
SetIndexBuffer(2, Buf2);
SetIndexBuffer(3, Buf3);
SetIndexBuffer(4, Buf4);
return(INIT_SUCCEEDED);
}
まとめ

「array out of range」は初心者から上級者まで、MQL開発で必ず一度は直面するエラーですね。

コンパイルが通ったのに画面に何も出ないと焦りますが、ターミナルでこのエラーが出ている場合は「配列の参照範囲(`Bars – 1`)」か「Bufferの宣言漏れ」を疑えばほぼ解決できますよ!

