MQL5 Indicator Bufferとは?仕組み・SetIndexBuffer・表示されない原因まで完全解説

目次

1. MQL5のIndicator Bufferとは何か

Indicator Buffer(インジケーターバッファ)とは、インジケーターの計算結果を格納するための配列です。
MQL5では、インジケーターは単に計算するだけではなく、「チャート上に描画する」という役割を持っています。そのため、計算結果を一時的に保持する構造としてBufferが必須になります。

例えば移動平均(MA)を考えると、各バーごとに計算された値を保存し、それを線として表示する必要があります。このとき、各バーに対応する値を格納する配列=Indicator Bufferが使われます。

重要なのは、Indicator Bufferは単なる配列ではなく、MetaTraderが描画・管理するための専用データ領域である点です。通常の配列とは異なり、後述する SetIndexBuffer によってMT5と紐づけることで、はじめて画面に表示されます。


1.1 Indicator Bufferの基本概念

Indicator Bufferは、以下の特徴を持つ配列です。

  • 各要素が「1本のバー」に対応する
  • インデックスで時間軸を管理する
  • MT5の描画エンジンと連携する

典型的な定義例は以下です。

double buffer[];

しかし、このままでは通常の配列であり、インジケーターとしては機能しません。
実際に使うには、以下のように紐づけます。

SetIndexBuffer(0, buffer);

この処理によって、

  • buffer配列
  • インジケーターの描画スロット(0番)

が接続され、初めてチャート上に表示される準備が整います。


1.2 なぜ配列(Buffer)で管理されるのか

Indicator Bufferが配列である理由は、「時系列データ」を扱うためです。

FXのチャートは以下の構造を持っています。

  • 過去 → 現在へと並ぶデータ列
  • 各バーごとに1つの値を持つ

つまり、インジケーターは本質的に以下のような構造になります。

[過去データ] ... [現在データ]

この構造に最も適しているのが配列です。

さらにMQL5では、

  • buffer[0] → 最新バー
  • buffer[1] → 1つ前のバー

という形で扱うのが一般的です(ArraySetAsSeriesを使用した場合)。


1.3 EAとの違い(Indicator特有の仕組み)

初心者が混乱しやすいポイントとして、EA(自動売買)との違いがあります。

項目 EA Indicator
主な役割 売買処理 表示・分析
データ管理 任意の変数 Buffer必須
描画 不要 必須

EAでは単純に変数に値を入れるだけで完結しますが、インジケーターでは以下が必要です。

  • 計算結果をBufferに格納
  • BufferをMT5に登録
  • 描画設定を行う

つまり、Indicator Bufferは単なるデータ保存ではなく、「表示するためのインフラ」として機能します。


よくあるつまずき・注意点

  • Bufferを宣言しただけで表示されると思う
    → SetIndexBufferを設定しないと表示されない
  • 配列に値を入れているのに線が出ない
    → 描画設定(Plot)が未設定の可能性
  • インデックスの意味を誤解する
    → 0が最新か最古かは設定に依存(ArraySetAsSeries)

2. Indicator Bufferの仕組み(内部構造)

Indicator Bufferを正しく扱うには、「どう動いているか(内部構造)」の理解が不可欠です。
ここを曖昧にしたまま実装すると、array out of range や表示不具合が頻発します。

Indicator Bufferは一見シンプルな配列ですが、実際には以下の3要素で成り立っています。

  • 時系列データ(バー単位)
  • インデックス管理(どのバーか)
  • MT5との同期(描画・更新)

2.1 Bufferは時系列データ配列

Indicator Bufferは、時間順に並んだデータの集合です。

例えば、5本分のデータがある場合:

buffer[0] → 最新バー
buffer[1] → 1つ前
buffer[2] → 2つ前
...

このように、1つのインデックス = 1本のローソク足(バー)に対応します。

重要なのは、インジケーターは常に「過去から現在までの全データ」を持つ点です。
つまり、毎回の計算は単一値ではなく、配列全体の更新処理になります。


2.2 インデックスの意味(0 = 最新バー)

MQL5では、通常 ArraySetAsSeries() を使うことで、配列を時系列として扱います。

ArraySetAsSeries(buffer, true);

これにより、

  • buffer[0] → 最新バー
  • buffer[1] → 1つ前
  • buffer[n] → n本前

という直感的な構造になります。

ただし、この設定をしない場合は逆になります。

buffer[0] → 最古
buffer[last] → 最新

つまずきポイント

  • ArraySetAsSeriesを忘れる → インデックスが逆になる
  • CopyBufferなどと組み合わせたときに混乱する
  • ループ方向を誤る(0→N or N→0)

2.3 ArraySetAsSeriesとの関係

ArraySetAsSeriesは、Indicator Buffer運用においてほぼ必須です。

理由は以下の通りです。

  • 時系列処理が直感的になる
  • 最新データへのアクセスが簡単
  • EAとの連携(CopyBuffer)と整合性が取れる

実際のセット例:

double buffer[];

int OnInit()
{
   SetIndexBuffer(0, buffer);
   ArraySetAsSeries(buffer, true);
   return(INIT_SUCCEEDED);
}

よくある失敗

  • SetIndexBufferの前後で順序を誤る
    → 基本はどちらでも動くが、混乱の原因になるため統一推奨
  • 他の配列(price配列など)と方向が混在する
    → ロジック破綻の原因

補足:なぜ内部構造の理解が重要か

Indicator Bufferのバグの多くは、以下に集約されます。

  • インデックスのズレ
  • 配列範囲外アクセス(array out of range)
  • 表示位置のズレ

これらはすべて、内部構造の理解不足が原因です。


よくあるつまずき・注意点

  • buffer[0]が過去だと思ってしまう
    → ArraySetAsSeries(true)なら「最新」
  • ループ方向を間違える
    → 通常は「過去→現在」または「必要範囲のみ」
  • prev_calculatedを無視する
    → 不要な全再計算で重くなる

3. SetIndexBufferの使い方(最重要)

SetIndexBuffer は、配列(Indicator Buffer)をMT5の描画システムに登録する関数です。
この処理を行わない限り、どれだけ正しく計算してもチャートには一切表示されません。
インジケーター開発における最重要ポイントです。


3.1 SetIndexBufferとは何か

SetIndexBuffer は、インジケーターの「描画スロット」と配列を結びつける関数です。

基本構文:

SetIndexBuffer(index, buffer);
  • index:描画番号(0〜)
  • buffer:データを格納する配列

例:

double buffer[];

int OnInit()
{
   SetIndexBuffer(0, buffer);
   return(INIT_SUCCEEDED);
}

この設定により、

  • buffer配列の内容
  • チャート上のライン(0番)

が連動します。


3.2 index番号と描画の関係

index は「どのラインに対応するか」を決める番号です。

例:

SetIndexBuffer(0, buffer1);
SetIndexBuffer(1, buffer2);

この場合:

  • buffer1 → 1本目のライン
  • buffer2 → 2本目のライン

になります。


重要な前提

インデックス数は、必ず以下で事前に宣言する必要があります。

#property indicator_buffers 2

これを忘れると、

  • コンパイルエラー
  • 表示されない

といった問題が発生します。


3.3 ENUM_INDEXBUFFER_TYPE(高度だが重要)

SetIndexBuffer には第3引数を指定することもできます。

SetIndexBuffer(index, buffer, type);

代表的な種類:

  • INDICATOR_DATA
    → 描画されるデータ(通常はこれ)
  • INDICATOR_CALCULATIONS
    → 計算専用(表示されない)

例:

SetIndexBuffer(0, buffer, INDICATOR_DATA);

なぜ重要か

  • 計算用と表示用を分離できる
  • パフォーマンス最適化
  • 複雑なインジケーターで必須

3.4 実装手順(最短ルート)

初心者向けの最小構成を示します。

#property indicator_buffers 1
#property indicator_plots   1

double buffer[];

int OnInit()
{
   SetIndexBuffer(0, buffer);
   ArraySetAsSeries(buffer, true);
   return(INIT_SUCCEEDED);
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
{
   for(int i = 0; i < rates_total; i++)
   {
      buffer[i] = price[i]; // 例:そのままコピー
   }
   return(rates_total);
}

よくあるつまずき・注意点

  • SetIndexBufferを書いていない
    → 100%表示されない
  • #property indicator_buffersを忘れる
    → バッファ不足エラー or 無表示
  • index番号がズレている
    → 想定と違う線が出る
  • 計算用BufferをINDICATOR_DATAにしてしまう
    → ゴミデータが表示される
  • 配列サイズを意識していない
    → array out of range

実務的な重要ポイント(再現性)

  • 最初は「1バッファ構成」で確実に動かす
  • その後、複数バッファへ拡張する
  • 計算用Bufferは後から分離

この順序で進めると、バグ率が大きく下がります。

4. OnCalculateとBufferの関係(値の書き込み)

Indicator Bufferは「入れ物」に過ぎず、実際の値を書き込む処理は OnCalculate が担います
ここが正しく実装されていない場合、以下の問題が発生します。

  • 何も表示されない
  • 値がズレる
  • 重くなる(全再計算)

つまり、OnCalculateインジケーターの心臓部です。


4.1 OnCalculateとは何か

OnCalculate は、新しい価格データが来るたびに呼ばれる関数です。

基本構文:

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])

主要パラメータ:

  • rates_total:現在のバー総数
  • prev_calculated:前回までに計算済みのバー数
  • price[]:入力データ(通常は価格)

4.2 Bufferへの値の書き込み方法

基本はシンプルで、Bufferに値を代入するだけです。

for(int i = 0; i < rates_total; i++)
{
   buffer[i] = price[i];
}

これにより、

  • bufferの内容
  • チャート表示

が一致します。


4.3 prev_calculatedを使った最適化(重要)

初心者が最も見落としがちなポイントです。

毎回すべてのバーを再計算すると、

  • CPU負荷増大
  • パフォーマンス低下

につながります。

そこで prev_calculated を使います。

int start = prev_calculated;

if(start == 0)
{
   start = 0; // 初回のみ全計算
}

for(int i = start; i < rates_total; i++)
{
   buffer[i] = price[i];
}

仕組み

  • 初回 → 全計算
  • 2回目以降 → 新しいバーのみ計算

よくある誤解

  • prev_calculatedは「最後のインデックス」ではない
  • 0のときだけ特別扱いが必要

4.4 実務での安全なテンプレート

実務では以下の形が安定です。

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
{
   int start = prev_calculated;

   if(start > 0)
      start--;

   for(int i = start; i < rates_total; i++)
   {
      buffer[i] = price[i];
   }

   return(rates_total);
}

なぜ start– が必要か

  • 最新バーは未確定(価格が変動する)
  • 再計算しないと値ズレが発生

よくあるつまずき・注意点

  • 毎回0から計算してしまう
    → 無駄に重くなる
  • prev_calculatedをそのまま使う
    → 最新バーが更新されない
  • return値を間違える
    → 次回計算が崩れる(必ず rates_total)
  • bufferに値を入れていない
    → 当然表示されない

実務的な判断基準(重要)

  • 小規模インジケーター → 全計算でもOK
  • 実運用EA・重いロジック → prev_calculated必須

補足:beginの扱い

begin は「計算開始位置」ですが、通常は無視して問題ありません。
ただし、カスタムインジケーター連携では影響する場合があります。

5. 表示されない原因と対処法(最重要トラブル)

Indicator Bufferは正しく設定しているつもりでも、チャートに何も表示されないケースが非常に多いです。
原因はほぼパターン化されており、以下を順に確認すれば高確率で解決できます。


5.1 SetIndexBuffer未設定

最も多い原因です。

double buffer[];

と宣言しただけでは、ただの配列であり表示対象ではありません

必ず以下を記述します。

SetIndexBuffer(0, buffer);

チェックポイント

  • OnInit内に書いているか
  • index番号が正しいか(0から始まる)

5.2 indicator_buffers / indicator_plotsの不足

バッファ数や描画数の宣言が不足していると表示されません。

#property indicator_buffers 1
#property indicator_plots   1

よくあるミス

  • buffersとplotsの数が一致していない
  • 複数バッファなのに1しか宣言していない

5.3 Plot設定(描画設定)がない

Bufferは登録しても、「どう描画するか」を設定しないと見えません。

最低限必要な設定:

#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue

補足

  • DRAW_LINE → ライン表示
  • DRAW_HISTOGRAM → ヒストグラム
  • DRAW_NONE → 非表示(デバッグ用)

5.4 Bufferに値が入っていない

単純ですが非常に多いです。

buffer[i] = price[i];

のように、必ず値を代入する必要があります


確認方法

  • Printで値を出力
  • debuggerで確認

5.5 EMPTY_VALUEを誤用している

MQL5では、表示しない値に EMPTY_VALUE を使います。

buffer[i] = EMPTY_VALUE;

これを誤って全体に入れると、当然何も表示されません。


よくあるミス

  • 条件分岐が常にEMPTY_VALUEになる
  • 初期化ミス

5.6 ArraySetAsSeriesの不整合

インデックス方向がズレると、描画が崩れる or 表示されないことがあります。

ArraySetAsSeries(buffer, true);

典型例

  • price配列はseriesだがbufferは違う
  • ループ方向が逆

5.7 OnCalculateが正しく動いていない

OnCalculate内で処理が実行されていない場合:

  • return値が不正
  • ループ条件が間違い

などが原因になります。


例(NG)

return(0);

→ 次回以降計算されない


5.8 表示範囲外(スケール問題)

値が極端だと、チャート外に描画されることがあります。

例:

buffer[i] = 1000000;

対処

  • 値をPrintで確認
  • 別ウィンドウ表示に変更
#property indicator_separate_window

体系的チェック手順(実務用)

以下の順で確認すれば効率的です。

  1. SetIndexBufferがあるか
  2. indicator_buffers / plots が正しいか
  3. Plot設定があるか
  4. bufferに値が入っているか
  5. OnCalculateが動いているか
  6. インデックス方向が一致しているか

よくあるつまずき・注意点

  • 「コードは正しいのに出ない」と思い込む
    → ほぼ設定ミス
  • 複数原因が同時に発生する
    → 一つずつ潰すのが重要
  • デバッグをしない
    → Printは必須

実務的な戦略(再現性)

最短で原因特定する方法:

  1. bufferに固定値を入れる
buffer[i] = 1;
  1. 表示されるか確認

→ 出れば「計算ロジック問題」
→ 出なければ「設定問題」

6. 複数Bufferの使い方(応用)

実務レベルのインジケーターでは、複数のIndicator Bufferを組み合わせて使うのが一般的です。
例えば以下のようなケースです。

  • 移動平均2本(短期・長期)
  • シグナル(矢印)とラインの同時表示
  • 計算用データと表示用データの分離

ここでは、再現性の高い設計パターンを解説します。


6.1 複数Bufferの基本構成

まずはバッファを複数定義します。

#property indicator_buffers 2
#property indicator_plots   2

double buffer1[];
double buffer2[];

次に、それぞれを登録します。

int OnInit()
{
   SetIndexBuffer(0, buffer1);
   SetIndexBuffer(1, buffer2);

   ArraySetAsSeries(buffer1, true);
   ArraySetAsSeries(buffer2, true);

   return(INIT_SUCCEEDED);
}

対応関係

  • index 0 → buffer1(1本目のライン)
  • index 1 → buffer2(2本目のライン)

6.2 描画設定(Plot)との連動

複数Bufferを使う場合、描画設定も複数必要です。

#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue

#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed

重要ポイント

  • 「buffer数」と「plot数」は一致させる
  • index番号とproperty番号は対応させる

6.3 計算用Bufferと表示用Bufferの分離

実務では、表示しないBuffer(計算専用)を使うケースが多いです。

#property indicator_buffers 2
#property indicator_plots   1

double displayBuffer[];
double calcBuffer[];
SetIndexBuffer(0, displayBuffer, INDICATOR_DATA);
SetIndexBuffer(1, calcBuffer, INDICATOR_CALCULATIONS);

メリット

  • ロジックを整理できる
  • 表示が汚れない
  • 再利用性が高い

6.4 実装例(2本ライン)

簡単な例:

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
{
   int start = prev_calculated;
   if(start > 0) start--;

   for(int i = start; i < rates_total; i++)
   {
      buffer1[i] = price[i];         // 元データ
      buffer2[i] = price[i] * 1.01;  // 少し上に表示
   }

   return(rates_total);
}

6.5 シグナル系(矢印)のBuffer

売買サインなどは、通常別Bufferで管理します。

#property indicator_type1 DRAW_ARROW
buffer[i] = price[i];  // シグナル位置

非表示時

buffer[i] = EMPTY_VALUE;

よくあるつまずき・注意点

  • index番号がズレる
    → 線が入れ替わる
  • buffers数とplots数が一致しない
    → 表示されない
  • すべてINDICATOR_DATAにする
    → 不要な線が出る
  • EMPTY_VALUEを忘れる
    → 常にシグナル表示される

実務的な設計パターン(推奨)

最も安定する構成:

  • buffer0:メインライン(表示)
  • buffer1:サブライン(表示)
  • buffer2:計算用(非表示)
#property indicator_buffers 3
#property indicator_plots   2

再現性のある設計戦略

  • 最初は1Bufferで動作確認
  • 次に2Bufferへ拡張
  • 最後に計算Bufferを追加

この順番で進めると、デバッグコストが大幅に下がります。

7. よくあるエラーと原因

Indicator Bufferの理解が浅い段階で実装を進めると、発生するエラーはかなり似通います。
特に多いのは以下の3系統です。

  • array out of range
  • 値が表示されない
  • 値が0や EMPTY_VALUE のままになる

ここでは、症状 → 原因 → 対処の順で整理します。


7.1 array out of range

array out of range は、存在しない配列要素にアクセスしたときに出る代表的なエラーです。
Indicator Buffer関連では最頻出です。

典型例:

for(int i = 0; i <= rates_total; i++)
{
   buffer[i] = price[i];
}

このコードは i <= rates_total になっているため、最後に buffer[rates_total] へアクセスします。
ただし、有効な最後の要素は通常 rates_total - 1 です。これで範囲外アクセスが発生します。

修正版:

for(int i = 0; i < rates_total; i++)
{
   buffer[i] = price[i];
}

よくある原因

  • ループ条件が <= になっている
  • prev_calculated の開始位置計算を誤る
  • 最新バーと過去バーのインデックス認識が逆
  • 複数Bufferで片方だけサイズ前提がズレる

実務的な注意点

特に ArraySetAsSeries(true) を使っていると、「0が最新バー」であるため、頭の中の時系列とループ方向が食い違いやすくなります。
配列の向きとループ方向を必ずセットで確認することが重要です。


7.2 Bufferに値を入れているのに表示されない

これはエラーが出ないため、初心者が最も長く詰まりやすい問題です。
原因は大きく4つです。


7.2.1 SetIndexBufferまたはPlot設定の不足

SetIndexBuffer(0, buffer);

が無い、または

#property indicator_type1 DRAW_LINE
#property indicator_color1 clrBlue

などの描画設定が無いと、値が入っていても見えません。


7.2.2 すべて EMPTY_VALUE になっている

buffer[i] = EMPTY_VALUE;

は「その位置を描画しない」という意味です。
条件分岐を誤ると全バーが非表示になります。


7.2.3 値がチャートの表示範囲外

例えば価格チャート上で異常に大きい値や小さい値を出すと、画面外へ飛びます。

buffer[i] = 1000000;

この場合、コード自体は動いていても「見えない」状態になります。


7.2.4 別ウィンドウ向けの値をメインチャートへ出している

オシレーター系のように価格とスケールが異なる値は、別ウィンドウ表示のほうが適切です。

#property indicator_separate_window

環境や値の種類によっては、こちらの方が視認性とトラブル回避の両方で有利です。


7.3 値が0のままになる

Bufferに何らかの値は入っているが、意図した値ではなく0ばかりになるケースです。


主な原因

  • 計算式そのものが0を返している
  • 初期化だけされて更新されていない
  • OnCalculate の開始位置がズレて計算対象に入っていない
  • 入力配列 price[] 側の参照位置が違う

例:

for(int i = start; i < rates_total; i++)
{
   buffer[i] = 0;
}

これは意図的な例ですが、実際には途中式や未設定変数の結果として0が並ぶことがあります。


対処の基本

  • Print(i, " ", buffer[i]); で途中値を確認する
  • 固定値 1.0 を代入して表示確認する
  • 問題が「計算」か「表示」かを分離する

例:

buffer[i] = 1.0;

これで線が出るなら、設定は正しく、原因は計算ロジック側にあります。


7.4 値が EMPTY_VALUE のままになる

シグナル系インジケーターではよくある症状です。
これは「描画しない値」が想定外に維持されている状態です。

例:

if(condition)
   buffer[i] = price[i];
else
   buffer[i] = EMPTY_VALUE;

この構造自体は正しいですが、condition が常に偽なら一切表示されません。


典型的な原因

  • 条件式が厳しすぎる
  • 参照バーがズレていて条件成立しない
  • 比較対象の配列値が未更新

7.5 デバッグ時の確認手順

再現性の高い確認順は以下です。

  1. SetIndexBuffer があるか確認
  2. indicator_buffers / indicator_plots を確認
  3. DRAW_LINE など描画設定を確認
  4. buffer[i] = 1.0; にして表示されるか確認
  5. Print() で実際の値を確認
  6. ループ条件とインデックス方向を確認

この順で潰すと、原因特定がかなり速くなります。


よくあるつまずき・注意点

  • 表示されない = 計算ミスと決めつける
    → 実際は設定ミスの方が多いです。
  • array out of range を一か所直して終える
    → 複数箇所で同じズレが潜んでいることがあります。
  • 複数Buffer化した直後に一気に複雑化する
    → まず1本表示、次に2本表示の順で検証した方が安全です。

8. ベストプラクティス(安定運用のコツ)

Indicator Bufferは仕組み自体は単純ですが、実運用では再現性・可読性・デバッグ容易性を意識しないと破綻しやすい領域です。
ここでは、実務で安定稼働させるための設計指針を整理します。


8.1 最小構成から段階的に拡張する

最も重要な原則は「いきなり複雑にしない」ことです。

推奨手順

  1. 1Bufferで固定値を表示
  2. 実データを入れる
  3. 2Bufferへ拡張
  4. 計算用Bufferを追加

理由

  • 問題の切り分けが容易
  • 表示問題とロジック問題を分離できる
  • バグ発生時の原因特定が高速

8.2 BufferとPlotの対応を明確にする

複数Bufferになると、index番号の管理ミスが頻発します。


推奨パターン

#define MAIN_LINE   0
#define SUB_LINE    1
#define CALC_BUF    2
SetIndexBuffer(MAIN_LINE, mainBuffer);
SetIndexBuffer(SUB_LINE, subBuffer);
SetIndexBuffer(CALC_BUF, calcBuffer, INDICATOR_CALCULATIONS);

メリット

  • 可読性向上
  • indexズレ防止
  • チーム開発でも安全

8.3 ArraySetAsSeriesは統一する

配列の方向が混在すると、ロジックが破綻します。


原則

  • すべてのBufferで統一
  • price配列と同じ方向にする
ArraySetAsSeries(buffer, true);

よくある失敗

  • bufferだけseriesにする
  • price配列と逆方向になる

8.4 prev_calculatedを正しく使う

パフォーマンスと正確性の両方に影響します。


推奨テンプレ

int start = prev_calculated;

if(start > 0)
   start--;

for(int i = start; i < rates_total; i++)
{
   buffer[i] = price[i];
}

理由

  • 最新バーを再計算するため
  • 不整合防止

8.5 EMPTY_VALUEの使い方を徹底する

描画制御に直結します。


基本ルール

  • 表示したい → 値を代入
  • 表示しない → EMPTY_VALUE

if(signal)
   buffer[i] = price[i];
else
   buffer[i] = EMPTY_VALUE;

注意点

  • 初期化忘れでゴミ値が出る
  • 条件が成立しないと一切表示されない

8.6 デバッグを前提に設計する

Indicatorは「見た目」で判断しがちですが、内部確認が重要です。


推奨デバッグ手法

Print("i=", i, " value=", buffer[i]);

さらに強力な方法

  • 固定値テスト(1.0など)
  • 特定バーのみ出力
  • 条件成立時のみログ出力

8.7 エラーを前提にした設計(リスク管理)

Indicator開発は「正常動作より異常系が多い」と考えるのが現実的です。


典型リスク

  • 配列範囲外アクセス
  • インデックスズレ
  • 初期化漏れ

回避策

  • ループ条件を厳密に管理
  • 初回計算と更新処理を分離
  • 必ず return(rates_total)

8.8 実務での最適構成(再現性)

最も安定する構成例:

#property indicator_buffers 3
#property indicator_plots   2

// 表示
double mainBuffer[];
double subBuffer[];

// 計算
double calcBuffer[];

設計意図

  • 表示とロジックを分離
  • 将来的な拡張性確保
  • バグ影響範囲を限定

よくあるつまずき・注意点

  • 最初から複雑なロジックを組む
    → デバッグ不能になる
  • Bufferの役割を曖昧にする
    → 意図しない描画
  • prev_calculatedを軽視する
    → パフォーマンス劣化
  • デバッグを後回しにする
    → 問題が複雑化

実務的まとめ(重要)

Indicator Bufferは「配列」ではなく、描画システムの一部として扱うのが正しい理解です。

9. FAQ(よくある質問)

Indicator Bufferに関して、実務で頻出する疑問を整理します。
「検索意図に直結するもの」のみ厳選しています。


9.1 Indicator Bufferとは何ですか?

インジケーターの計算結果を保存し、チャートに表示するための配列です。
単なる配列ではなく、SetIndexBuffer によってMT5の描画システムと接続される特殊なデータ領域です。


9.2 SetIndexBufferを使わないとどうなりますか?

何も表示されません。
配列に値を入れても、MT5に登録しない限り描画対象にならないためです。


9.3 buffer[0]は最新バーですか?

通常は最新バーです(ArraySetAsSeries(true)の場合)。
設定していない場合は逆(最古)になるため、環境・コードに依存します。


9.4 Indicator Bufferは何個まで使えますか?

理論上は複数可能ですが、#property indicator_buffers で宣言した数に制限されます。
実務では、表示用+計算用を含めて2〜5個程度が一般的です。


9.5 なぜ何も表示されないのですか?

主な原因は以下です。

  • SetIndexBuffer未設定
  • Plot設定がない
  • bufferに値が入っていない
  • EMPTY_VALUEになっている
  • スケール外に表示されている

→ 設定ミスの可能性が高いです。


9.6 prev_calculatedは必ず使うべきですか?

必須ではないが、実務ではほぼ必須です。
使わない場合、毎回全データを再計算するためパフォーマンスが低下します。


9.7 INDICATOR_DATAとINDICATOR_CALCULATIONSの違いは?

  • INDICATOR_DATA:表示されるデータ
  • INDICATOR_CALCULATIONS:内部計算専用(非表示)

複雑なインジケーターでは分離が推奨されます。


9.8 array out of rangeの原因は何ですか?

配列の範囲外にアクセスしているためです。

主な原因:

  • ループ条件の誤り(<=)
  • インデックスのズレ
  • 配列サイズを超えたアクセス

→ ループ条件とインデックスを確認する必要があります。

This website stores cookies on your computer. These cookies are used to provide a more personalized experience and to track your whereabouts around our website in compliance with the European General Data Protection Regulation. If you decide to to opt-out of any future tracking, a cookie will be setup in your browser to remember this choice for one year.

Accept or Deny