- 1 1. MQL5のIndicator Bufferとは何か
- 2 2. Indicator Bufferの仕組み(内部構造)
- 3 3. SetIndexBufferの使い方(最重要)
- 4 4. OnCalculateとBufferの関係(値の書き込み)
- 5 5. 表示されない原因と対処法(最重要トラブル)
- 6 6. 複数Bufferの使い方(応用)
- 7 7. よくあるエラーと原因
- 8 8. ベストプラクティス(安定運用のコツ)
- 9 9. FAQ(よくある質問)
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
体系的チェック手順(実務用)
以下の順で確認すれば効率的です。
- SetIndexBufferがあるか
- indicator_buffers / plots が正しいか
- Plot設定があるか
- bufferに値が入っているか
- OnCalculateが動いているか
- インデックス方向が一致しているか
よくあるつまずき・注意点
- 「コードは正しいのに出ない」と思い込む
→ ほぼ設定ミス - 複数原因が同時に発生する
→ 一つずつ潰すのが重要 - デバッグをしない
→ Printは必須
実務的な戦略(再現性)
最短で原因特定する方法:
- bufferに固定値を入れる
buffer[i] = 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 デバッグ時の確認手順
再現性の高い確認順は以下です。
SetIndexBufferがあるか確認indicator_buffers/indicator_plotsを確認DRAW_LINEなど描画設定を確認buffer[i] = 1.0;にして表示されるか確認Print()で実際の値を確認- ループ条件とインデックス方向を確認
この順で潰すと、原因特定がかなり速くなります。
よくあるつまずき・注意点
- 表示されない = 計算ミスと決めつける
→ 実際は設定ミスの方が多いです。 - array out of range を一か所直して終える
→ 複数箇所で同じズレが潜んでいることがあります。 - 複数Buffer化した直後に一気に複雑化する
→ まず1本表示、次に2本表示の順で検証した方が安全です。
8. ベストプラクティス(安定運用のコツ)
Indicator Bufferは仕組み自体は単純ですが、実運用では再現性・可読性・デバッグ容易性を意識しないと破綻しやすい領域です。
ここでは、実務で安定稼働させるための設計指針を整理します。
8.1 最小構成から段階的に拡張する
最も重要な原則は「いきなり複雑にしない」ことです。
推奨手順
- 1Bufferで固定値を表示
- 実データを入れる
- 2Bufferへ拡張
- 計算用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の原因は何ですか?
配列の範囲外にアクセスしているためです。
主な原因:
- ループ条件の誤り(<=)
- インデックスのズレ
- 配列サイズを超えたアクセス
→ ループ条件とインデックスを確認する必要があります。