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番)

が連動します。

Diagram showing how SetIndexBuffer in MQL5 binds an indicator buffer array to the MetaTrader chart, illustrating the execution flow from OnCalculate updating buffer values to rendering plotted lines on the chart.


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の原因は何ですか?

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

主な原因:

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

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