MQL5 SetIndexBufferの使い方完全解説|表示されない原因と解決方法

目次

1. SetIndexBufferとは何か

MQL5でカスタムインジケーターを作成する際、最初に理解すべき最重要関数のひとつが「SetIndexBuffer」です。
この関数を正しく理解していないと、「値を計算しているのにチャートに表示されない」という典型的な問題に必ず直面します。

結論から言うと、SetIndexBufferは
「計算結果をチャートに表示するための配列を登録する関数」です。

MQL5では、単に配列に値を入れただけでは表示されません。
必ず「この配列を表示用データとして使う」と明示的に登録する必要があります。


1.1 SetIndexBufferの役割

SetIndexBufferの役割は非常にシンプルですが重要です。

  • インジケーターの描画データを配列に紐づける
  • チャートに表示するための「データの通り道」を作る

イメージとしては以下の通りです。

計算ロジック → 配列(buffer) → SetIndexBuffer → チャート表示

つまり、SetIndexBufferを使わない場合:

  • 配列に値を入れても
    チャートには一切表示されません

最低限の流れ(重要)

double buffer[];

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

この1行がないだけで、どれだけ正しい計算を書いても表示されません。


よくある失敗

  • SetIndexBufferを書いていない
  • OnInit以外で呼んでいる
  • bufferの宣言を忘れている

これらは初心者のほぼ全員が一度は通るエラーです。


1.2 インジケーターバッファとは何か

「バッファ」という言葉が難しく感じるかもしれませんが、実体は単純です。

👉 バッファ = 値を格納する配列(double配列)

例:

double buffer[];

この配列の各要素は、チャートの各バー(ローソク足)に対応します。

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

※ArraySetAsSeriesの設定により逆転する場合あり(後述)


重要なポイント

  • インジケーターは「配列単位」で描画される
  • 1つのバッファ = 1本のライン(または描画要素)

よくある誤解

  • ❌「変数に値を入れれば表示される」
  • ❌「Printすれば出る」

配列+SetIndexBufferが必須


1.3 なぜSetIndexBufferが必要なのか

MQL5の設計上、描画と計算は分離されています。

つまり:

  • 計算 → OnCalculateで行う
  • 表示 → SetIndexBufferで登録した配列のみ

この構造により:

  • 高速描画(内部最適化)
  • 複数ライン管理
  • インジケーターの統一構造

が実現されています。


もしSetIndexBufferを使わないとどうなるか

buffer[i] = Close[i];

このように値を入れても:

  • チャートに何も表示されない
  • エラーも出ない(これが厄介)

実務での注意点(重要)

  • 表示されない原因の80%以上がSetIndexBuffer周り
  • デバッグ時はまずここを疑う

チェックリスト(必須)

  • OnInitでSetIndexBufferを呼んでいるか
  • bufferがdouble配列か
  • INDICATOR_DATAが指定されているか
  • bufferに値を入れているか

2. SetIndexBufferの基本構文と使い方

SetIndexBufferは「理解」よりも「正しく書けること」が重要です。
ここでは、そのまま使えるレベルまで具体化します。


2.1 基本構文

SetIndexBufferの基本構文は以下の通りです。

bool SetIndexBuffer(
   int index,
   double buffer[],
   ENUM_INDEXBUFFER_TYPE type
);

各引数の意味(重要)

  • index
    → バッファ番号(0から開始)
  • buffer[]
    → 表示・計算に使う配列
  • type
    → バッファの用途(表示用 or 内部計算用)

最重要ポイント

  • indexは0から始まる
  • bufferはdouble配列のみ
  • typeで表示可否が決まる

2.2 最小構成の使い方(これだけで動く)

まずは「絶対に動く最小構成」を理解します。


手順(初心者向け)

  1. 配列を宣言
  2. OnInitでSetIndexBufferを設定
  3. OnCalculateで値を入れる

コード例(最小構成)

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1

double buffer[];

int OnInit()
{
   SetIndexBuffer(0, buffer, INDICATOR_DATA);
   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);
}

このコードでやっていること

  • price[](価格)をそのまま表示
  • bufferに代入 → SetIndexBuffer経由で描画

動作確認のポイント

  • サブウィンドウにラインが出る
  • 値が更新される

2.3 index(バッファ番号)の考え方

indexは「何番目のラインか」を意味します。


例:複数ライン

SetIndexBuffer(0, buffer1, INDICATOR_DATA);
SetIndexBuffer(1, buffer2, INDICATOR_DATA);
  • 0 → 1本目のライン
  • 1 → 2本目のライン

注意点

  • indexとPlotIndexがズレると表示されない
  • indicator_buffersと一致させる必要あり

よくある失敗

  • indexを1から始めてしまう
  • buffer数より多いindexを指定する

2.4 type(バッファタイプ)の基本

typeは初心者が最も混乱するポイントです。


よく使う2種類

INDICATOR_DATA
INDICATOR_CALCULATIONS

違い(重要)

  • INDICATOR_DATA
    → チャートに表示される
  • INDICATOR_CALCULATIONS
    → 内部計算用(表示されない)

初心者は基本これでOK

SetIndexBuffer(0, buffer, INDICATOR_DATA);

よくあるミス

  • CALCULATIONSを使って表示されない
  • typeを省略(MQL5では不可)

2.5 よくあるエラーと原因

ここは検索意図の核心です。


ケース1:何も表示されない

原因:

  • INDICATOR_DATA未指定
  • SetIndexBuffer未実行

ケース2:ラインが途中で消える

原因:

  • bufferに値を入れていない
  • 未初期化のまま使用

ケース3:値がズレる

原因:

  • ArraySetAsSeries未設定
  • インデックス方向の誤解

2.6 実務での重要チェックポイント

実際の開発では以下を必ず確認します。


チェックリスト

  • SetIndexBufferはOnInitで呼んでいるか
  • bufferはグローバルで宣言されているか
  • indicator_buffersの数と一致しているか
  • typeがINDICATOR_DATAになっているか

デバッグのコツ

  • Printでbuffer値を確認
  • 最初は単純なコピーで動作確認

3. バッファタイプ(INDICATOR_DATA / CALCULATIONS)の違い

SetIndexBufferの中でも、最も誤解されやすく、表示トラブルの原因になりやすいのが「type(バッファタイプ)」です。
ここを曖昧に理解したままだと、「計算はできているのに表示されない」という状態から抜け出せません。


3.1 INDICATOR_DATAとは(表示用バッファ)

INDICATOR_DATAは、チャートに表示されるバッファです。

SetIndexBuffer(0, buffer, INDICATOR_DATA);

この指定をした配列だけが、ラインやヒストグラムとして描画されます。


特徴

  • チャートに描画される
  • PlotIndexSet系と連動する
  • indicator_plotsの対象になる

使用例(典型)

double mainBuffer[];

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

実務ポイント

  • 「見せたいデータ」は必ずINDICATOR_DATA
  • 複数ラインの場合は複数指定

よくある失敗

  • INDICATOR_DATAを設定していない
  • indexとplot設定が一致していない

3.2 INDICATOR_CALCULATIONSとは(内部計算用)

INDICATOR_CALCULATIONSは、表示しない計算用バッファです。

SetIndexBuffer(1, calcBuffer, INDICATOR_CALCULATIONS);

特徴

  • チャートには表示されない
  • 中間計算に使う
  • パフォーマンス最適化に寄与

使用例(移動平均の途中計算)

double tempBuffer[];
double outputBuffer[];

int OnInit()
{
   SetIndexBuffer(0, outputBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, tempBuffer, INDICATOR_CALCULATIONS);
   return(INIT_SUCCEEDED);
}

典型用途

  • EMAの途中計算
  • ATRの内部値
  • フィルタリング用データ

よくある誤解

  • ❌「CALCULATIONSでも表示される」
    表示されません

3.3 両者の使い分け(重要)

ここが設計の分岐点です。


判断基準

用途 指定
チャートに表示する INDICATOR_DATA
計算だけに使う INDICATOR_CALCULATIONS

実務での基本設計

表示用:最終結果 → INDICATOR_DATA
計算用:途中データ → CALCULATIONS

実例(構造イメージ)

価格 → tempBuffer(計算) → outputBuffer(表示)

3.4 初心者がハマる典型パターン

ここは検索ニーズが非常に強い部分です。


パターン1:何も表示されない

SetIndexBuffer(0, buffer, INDICATOR_CALCULATIONS);

原因:CALCULATIONSにしている


パターン2:バッファはあるのに見えない

原因:

  • Plot設定が不足
  • indicator_plots未定義

パターン3:値は入っているのに線が出ない

原因:

  • EMPTY_VALUEが混在
  • 描画設定ミス

3.5 設計レベルの理解(中級者向け)

MQL5は以下の思想で設計されています。


分離設計

  • 計算(CALCULATIONS)
  • 表示(DATA)

これにより:

  • 高速処理
  • 再利用性
  • 安定描画

が実現されています。


実務上のメリット

  • 計算ロジックを分離できる
  • バグ切り分けが容易
  • パフォーマンス改善

3.6 チェックリスト(最重要)

表示されないときはここを確認します。


必須チェック

  • 表示したいバッファはINDICATOR_DATAか
  • indexとplotが一致しているか
  • bufferに値が入っているか

デバッグ手順

  1. 全てINDICATOR_DATAにする
  2. 単純な値(Close)を代入
  3. 徐々にロジックを戻す

3.7 実務アドバイス(期待値ベース)

  • 初期段階ではCALCULATIONSは使わない
  • まず「表示されること」を優先
  • その後に最適化

推奨ステップ

  1. INDICATOR_DATAのみで構築
  2. 動作確認
  3. CALCULATIONSに分離

4. 複数バッファを使ったインジケーター実装

SetIndexBufferは単体でも使えますが、実務では複数バッファを組み合わせて使うケースが基本です。
ここでは、複数ライン(例:メインライン+シグナル)を持つインジケーターを題材に、実装手順を具体化します。


4.1 複数バッファの基本設計

複数バッファを使う場合、以下の設計が基本になります。

buffer0 → メイン表示(INDICATOR_DATA)
buffer1 → サブ表示(INDICATOR_DATA)
buffer2 → 内部計算(INDICATOR_CALCULATIONS)

必須設定

#property indicator_buffers 3
#property indicator_plots   2
  • indicator_buffers → 使用する配列数
  • indicator_plots → 表示するライン数

重要ポイント

  • buffers ≥ plots(必須)
  • 表示する数だけplotsを設定

4.2 実装手順(テンプレート)

実務では以下の手順で組み立てます。


手順

  1. バッファを宣言
  2. indicator_buffers / plots を定義
  3. SetIndexBufferで紐付け
  4. 描画設定(PlotIndexSet系)
  5. OnCalculateで値を代入

4.3 実用コード例(2ライン+内部計算)

以下は「シンプルな移動平均+シグナルライン」の構成です。

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   2

double mainBuffer[];
double signalBuffer[];
double tempBuffer[];

int OnInit()
{
   // バッファ登録
   SetIndexBuffer(0, mainBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, signalBuffer, INDICATOR_DATA);
   SetIndexBuffer(2, tempBuffer, INDICATOR_CALCULATIONS);

   // 描画設定
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
   PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE);

   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++)
   {
      tempBuffer[i]   = price[i];             // 中間データ
      mainBuffer[i]   = tempBuffer[i];        // メイン
      signalBuffer[i] = mainBuffer[i] * 0.9;  // シグナル
   }

   return(rates_total);
}

このコードの構造

  • tempBuffer → 内部計算
  • mainBuffer → 表示1
  • signalBuffer → 表示2

表示結果

  • 2本のラインが描画される
  • signalはmainより少し下に表示

4.4 よくある失敗(重要)

複数バッファではエラーが増えます。


ケース1:ラインが1本しか出ない

原因:

  • indicator_plotsが不足
  • PlotIndexSet未設定

ケース2:何も表示されない

原因:

  • indexとbufferの紐付けミス
  • INDICATOR_DATA不足

ケース3:配列エラー(out of range)

原因:

  • bufferサイズ未初期化
  • rates_total未考慮

4.5 実務での設計パターン

複雑なインジケーターでは以下の構造になります。


典型構造

価格
 ↓
前処理(CALCULATIONS)
 ↓
メインロジック(CALCULATIONS)
 ↓
表示用(DATA)

メリット

  • ロジック分離
  • デバッグ容易
  • 再利用性向上

4.6 デバッグの進め方(重要)

複数バッファで問題が出た場合:


手順

  1. すべてINDICATOR_DATAに変更
  2. 単純な値(Close)を入れる
  3. 1本ずつ戻す

期待値の高い切り分け

  • 表示問題 → SetIndexBuffer or Plot
  • 計算問題 → OnCalculate

4.7 注意点まとめ

  • buffer数とpropertyが一致しているか
  • indexは0から順番か
  • 表示用と計算用を混同していないか

実務アドバイス

  • 最初は「1バッファ」で作る
  • 動いたら拡張

5. 表示されない原因と具体的な解決方法

SetIndexBufferを使ったインジケーターで最も多いトラブルは、「コンパイルは通るのに何も表示されない」という問題です。
この種の不具合は、文法エラーではなく設定・紐付け・代入のどこかが欠けている
ことが原因です。
ここでは、実務で発生頻度の高い原因を、確認順序付きで整理します。


5.1 まず確認するべき最小チェック項目

表示されないときは、いきなり複雑なロジックを疑うのではなく、以下を上から順に確認します。

  • SetIndexBuffer()OnInit() で呼んでいるか
  • 表示したい配列が INDICATOR_DATA になっているか
  • #property indicator_buffers の数が足りているか
  • #property indicator_plots の数が表示本数と合っているか
  • OnCalculate() 内で実際にバッファへ値を代入しているか

この5点のどれかが欠けるだけで、エラーなしで非表示になります。


5.2 原因1:SetIndexBuffer自体が未設定

最も基本的な原因です。
配列を宣言して値を入れていても、SetIndexBufferで登録していなければ、MQL5はそれを描画対象として扱いません。

失敗例

double buffer[];

int OnInit()
{
   return(INIT_SUCCEEDED);
}

この状態では、buffer[] に値を入れても表示されません。

修正例

double buffer[];

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

注意点

  • OnCalculate() の中で毎回 SetIndexBuffer() を呼ぶ必要はありません
  • 基本は OnInitで1回設定 です

5.3 原因2:INDICATOR_CALCULATIONSを使っている

内部計算用バッファを表示しようとしているケースです。

失敗例

SetIndexBuffer(0, buffer, INDICATOR_CALCULATIONS);

この指定では、buffer[] は計算用として扱われるため、チャートには描画されません

修正例

SetIndexBuffer(0, buffer, INDICATOR_DATA);

判断基準

  • 見せたい値 → INDICATOR_DATA
  • 内部だけで使う値 → INDICATOR_CALCULATIONS

よくある失敗

  • コードを整理しようとして、全部CALCULATIONSにしてしまう
  • 「値が入っているから出るはず」と思い込む

5.4 原因3:OnCalculateで値を代入していない

SetIndexBufferを設定していても、バッファの中身が空であれば表示されません。
特に、ループ条件や prev_calculated の扱いを誤ると、実質的に一度も代入されないことがあります。

失敗例

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

登録はされていても、何も代入していないため表示されません。

修正例

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);
}

つまずきやすい点

  • ループ開始位置を間違える
  • 条件分岐で代入が飛ばされる
  • 一部バーしか代入しておらず、表示範囲に値がない

5.5 原因4:property設定が不足している

バッファやプロットの本数に関する #property が不足していると、正しく紐付けても期待通りに出ません。

典型例

#property indicator_buffers 1
#property indicator_plots   1

この状態で2本の表示バッファを使うと、構造が合いません。

修正の考え方

  • 使用する全バッファ数 → indicator_buffers
  • 実際に見せるライン数 → indicator_plots

#property indicator_buffers 3
#property indicator_plots   2

この場合は、

  • 表示用2本
  • 計算用1本
    のような構成にできます。

注意点

  • buffersplots は同じ意味ではありません
  • 表示しない計算用バッファも indicator_buffers には含めます

5.6 原因5:描画設定が足りない

バッファ登録だけでは不十分で、どう描くか の設定が不足している場合があります。
特に複数プロットでは、描画タイプの指定が曖昧だと意図通りに見えません。

PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);

これにより、0番目のプロットをラインとして描画します。

確認ポイント

  • DRAW_LINE
  • DRAW_HISTOGRAM
  • DRAW_ARROW

など、表示形式が目的に合っているかを確認します。

よくある失敗

  • バッファはあるが、描画形式が不一致
  • 矢印表示のつもりでライン設定のまま
  • カラーや太さ設定以前に、描画タイプ自体が適切でない

5.7 原因6:EMPTY_VALUEや未初期化値の混在

MQL5では、描画しない要素に EMPTY_VALUE を入れることがあります。
これは正しい使い方ですが、全バーにEMPTY_VALUEを入れてしまうと当然何も見えません

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

このコードだけでは全て非表示です。

使い方の原則

  • 表示しないバーだけ EMPTY_VALUE
  • 表示するバーには実数値を入れる

注意点

  • 条件式が厳しすぎて、全バー非表示になることがある
  • デバッグ時は一度 Close[i] など単純な値を入れて確認すると切り分けしやすい

5.8 原因7:インデックス方向の誤解

時系列配列は、環境や使い方によって 新しいバーが0番か、古いバーが0番か の理解を間違えやすいです。
このズレにより、値は入っていても見え方が不自然になったり、想定位置に出なかったりします。

よくある症状

  • 線が逆方向に見える
  • 最新バーに値が入っていない
  • 一部だけおかしな場所に出る

対策

  • ArraySetAsSeries() の有無を確認する
  • price[] や独自バッファの方向を統一する
  • 最初は複雑な最適化をせず、単純ループで挙動確認する

実務上の考え方

表示されないというより、「正しい場所に表示されていない」 問題として出ることが多いです。


5.9 最短で切り分けるデバッグ手順

表示トラブルは、以下の順で絞り込むと早いです。

手順

    1. SetIndexBuffer() があるか確認
    1. INDICATOR_DATA か確認
    1. indicator_buffers / indicator_plots を確認
    1. OnCalculate()buffer[i] = price[i]; のような単純代入に変更
    1. それで表示されるなら、原因は元の計算ロジック側

実務で有効な簡易テスト

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

これで表示されれば、

  • SetIndexBuffer周りは正常
  • 問題は計算式または条件分岐
    と判断しやすくなります。

5.10 よくある失敗のまとめ

  • SetIndexBufferを書いていない
  • INDICATOR_CALCULATIONS を使っている
  • OnCalculate() で値を入れていない
  • indicator_buffers と実数が合っていない
  • EMPTY_VALUE ばかり入っている
  • 配列方向を誤解している

表示されない問題は、一見複雑に見えても、実際は「登録」「設定」「代入」の3系統にほぼ集約されます。
まずはこの3つを順番に潰すことが、最短での解決につながります。

6. ArraySetAsSeriesとの関係と注意点

SetIndexBufferを正しく使っても、「値は入っているのに表示がズレる」「最新バーに値が出ない」といった問題が発生する場合、ArraySetAsSeriesの扱いが原因であるケースが非常に多いです。
この章では、配列の向き(インデックス方向)を正しく理解し、バグを回避する方法を整理します。


6.1 ArraySetAsSeriesとは何か

ArraySetAsSeriesは、配列のインデックス方向(時系列の並び)を変更する関数です。

ArraySetAsSeries(array, true);

動作の違い

設定 index 0 index 1 index 2
false(デフォルト) 最古 最新
true(時系列) 最新 過去

結論(重要)

  • true → MT4風(最新が0)
  • false → 通常配列(古い順)

6.2 なぜ重要なのか

MQL5では、データ配列の方向が統一されていないと:

  • 最新バーに値が入らない
  • 線が逆方向に見える
  • 一部だけ表示されない

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


典型的なズレ

buffer[0] = 最新データのつもり

しかし実際は:

  • buffer[0] = 最古データ(ArraySetAsSeries=falseの場合)

意図と逆になる


6.3 実務での基本ルール

混乱を防ぐため、以下のどちらかに統一します。


パターンA(推奨:MT4互換思考)

ArraySetAsSeries(buffer, true);
  • buffer[0] = 最新バー
  • 直感的でわかりやすい

パターンB(標準配列)

ArraySetAsSeries(buffer, false);
  • buffer[0] = 最古
  • C言語的な配列構造

結論

👉 初心者は「true」に統一するのが安全


6.4 実装例(正しい設定)

double buffer[];

int OnInit()
{
   SetIndexBuffer(0, buffer, INDICATOR_DATA);
   ArraySetAsSeries(buffer, true);

   return(INIT_SUCCEEDED);
}

補足

  • price[] などの標準配列は通常 true(時系列)で渡される
  • 自作バッファと方向を揃える必要あり

6.5 よくある失敗(重要)

ここは実務で非常に多いです。


ケース1:表示が逆になる

原因:

  • bufferはfalse
  • priceはtrue

→ インデックスがズレる


ケース2:最新バーが更新されない

原因:

  • ループ方向と配列方向が不一致

ケース3:一部だけ表示されない

原因:

  • 配列方向に対して誤った範囲でループ

6.6 ループ設計の注意点

配列方向によってループの書き方が変わります。


true(推奨)

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

falseの場合

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

※同じコードでも意味が変わる点に注意


実務アドバイス

  • 初期段階ではループ最適化しない
  • まず正しく表示されることを優先

6.7 prev_calculatedとの関係

最適化でよく使う prev_calculated も、配列方向と密接に関係します。


よくあるミス

for(int i = prev_calculated; i < rates_total; i++)

これが正しく動かない原因:

  • 配列方向の誤認識

安全な方法(初期段階)

for(int i = 0; i < rates_total; i++)

→ まずはこれで確認


6.8 デバッグの最短ルート

配列方向の問題は、以下で一発確認できます。


テストコード

buffer[0] = 100;
buffer[1] = 50;
buffer[2] = 0;

見え方で判断

  • 右端に100 → 正しい
  • 左端に100 → 逆

6.9 実務での統一ルール(重要)

トラブルを減らすため、以下に統一します。


推奨ルール

  • 全バッファで ArraySetAsSeries(true)
  • price配列と同じ方向にする
  • ループは0→rates_total

NGパターン

  • バッファごとに方向が違う
  • 一部だけtrue/false混在
  • 意図せずデフォルトに依存

6.10 まとめ(実務視点)

  • SetIndexBufferだけでは不十分
  • 配列方向がズレると正常に表示されない
  • 初心者は trueに統一 が最も安全

7. PlotIndexSet系関数による描画カスタマイズ

SetIndexBufferで「表示するデータの登録」は完了しますが、どのように描画するか(線・色・太さ・スタイルなど)は別途設定が必要です。
この役割を担うのが PlotIndexSet系関数 です。ここを理解すると、実務レベルのインジケーター表現が可能になります。


7.1 PlotIndexSet系の役割

PlotIndexSet系は、インジケーターの見た目(レンダリング設定)を制御する関数群です。

PlotIndexSetInteger(index, property, value);
PlotIndexSetDouble(index, property, value);
PlotIndexSetString(index, property, value);

重要な関係

SetIndexBuffer → データを登録
PlotIndexSet   → 見た目を設定

結論

👉 両方セットで初めて「正しく表示される」


7.2 最低限必要な設定(必須)

まずは最低限これだけでOKです。

PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);

意味

  • 0 → バッファ番号
  • DRAW_LINE → 線として描画

設定しない場合

  • デフォルト描画になる
  • 環境によっては意図しない表示になる

7.3 主な描画タイプ(重要)

描画タイプは用途に応じて選びます。


代表的な種類

DRAW_LINE
DRAW_HISTOGRAM
DRAW_ARROW
DRAW_NONE

用途別

  • LINE → 移動平均・オシレーター
  • HISTOGRAM → MACD・ボリューム
  • ARROW → シグナル表示

PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_HISTOGRAM);

7.4 色・太さ・スタイルの設定

見た目を整えるにはここが重要です。


色設定

PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrBlue);

太さ

PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 2);

線の種類

PlotIndexSetInteger(0, PLOT_LINE_STYLE, STYLE_DASH);

実務例

PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrRed);
PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 2);

7.5 複数プロットの設定

複数ラインを扱う場合、それぞれに設定が必要です。


PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrBlue);
PlotIndexSetInteger(1, PLOT_LINE_COLOR, clrGreen);

注意点

  • indexごとに設定が独立
  • 設定漏れ=デフォルト表示

7.6 ラベル設定(重要)

凡例(インジケーター名表示)を設定します。

PlotIndexSetString(0, PLOT_LABEL, "Main Line");

効果

  • データウィンドウに表示
  • 複数ラインの識別が容易

7.7 よくある失敗(重要)

描画系は見落としやすいです。


ケース1:表示されない(実は描画なし)

原因:

PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_NONE);

ケース2:色が見えない

原因:

  • 背景と同色
  • 透明設定

ケース3:ラインが細すぎる

原因:

PLOT_LINE_WIDTH = 1

→ 視認性が低い


7.8 実務テンプレート(推奨)

以下は実務でよく使う安定構成です。

int OnInit()
{
   SetIndexBuffer(0, buffer, INDICATOR_DATA);

   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrBlue);
   PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 2);
   PlotIndexSetString(0, PLOT_LABEL, "Indicator");

   return(INIT_SUCCEEDED);
}

7.9 デバッグ視点での重要ポイント

表示されない場合:


切り分け

  • SetIndexBuffer → OKか
  • PlotIndexSet → DRAW_TYPEが正しいか

確認方法

一度以下に変更:

PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrWhite);
PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 3);

→ 見えれば描画設定問題


7.10 実務アドバイス

  • 最初はLINE固定でOK
  • 見た目は後から調整
  • 表示されることを最優先

8. 実務で使える完成テンプレート(コピペ可)

ここまでの内容を踏まえ、SetIndexBuffer・ArraySetAsSeries・PlotIndexSetを正しく組み合わせた最小かつ実用的なテンプレートを提示します。
まずはこの形で「確実に表示される状態」を作り、その後ロジックを追加してください。


8.1 最小安定テンプレート(1バッファ)

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1

double buffer[];

int OnInit()
{
   // バッファ登録(表示用)
   SetIndexBuffer(0, buffer, INDICATOR_DATA);

   // 配列方向を統一(最新バーが0)
   ArraySetAsSeries(buffer, true);

   // 描画設定
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrBlue);
   PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 2);
   PlotIndexSetString(0, PLOT_LABEL, "Sample");

   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);
}

このテンプレートの特徴

  • 確実に表示される構成
  • 配列方向の不一致を回避
  • 描画設定済み
  • デバッグしやすい

動作確認ポイント

  • サブウィンドウにラインが表示される
  • 価格に追従する

8.2 2バッファ(メイン+シグナル)

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2

double mainBuffer[];
double signalBuffer[];

int OnInit()
{
   SetIndexBuffer(0, mainBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, signalBuffer, INDICATOR_DATA);

   ArraySetAsSeries(mainBuffer, true);
   ArraySetAsSeries(signalBuffer, true);

   // メインライン
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrBlue);

   // シグナルライン
   PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE);
   PlotIndexSetInteger(1, PLOT_LINE_COLOR, clrRed);

   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++)
   {
      mainBuffer[i]   = price[i];
      signalBuffer[i] = price[i] * 0.9;
   }

   return(rates_total);
}

ポイント

  • バッファごとにSetIndexBuffer
  • 描画設定も個別に必要
  • indicator_plotsと一致させる

8.3 内部計算バッファ付き(実務構成)

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   1

double outputBuffer[];
double calcBuffer1[];
double calcBuffer2[];

int OnInit()
{
   SetIndexBuffer(0, outputBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, calcBuffer1, INDICATOR_CALCULATIONS);
   SetIndexBuffer(2, calcBuffer2, INDICATOR_CALCULATIONS);

   ArraySetAsSeries(outputBuffer, true);
   ArraySetAsSeries(calcBuffer1, true);
   ArraySetAsSeries(calcBuffer2, true);

   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);

   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++)
   {
      calcBuffer1[i] = price[i];
      calcBuffer2[i] = calcBuffer1[i] * 2;
      outputBuffer[i] = calcBuffer2[i];
   }

   return(rates_total);
}

実務的な意味

  • calcBuffer → 中間処理
  • outputBuffer → 表示

8.4 よくあるミス(テンプレ使用時)

テンプレを使っても以下で崩れます。


ミス1:property未変更

  • buffers数が足りない
  • plots数が一致していない

ミス2:ArraySetAsSeries忘れ

→ 表示位置ズレ


ミス3:OnCalculate未実装

→ 表示されない


ミス4:price配列の扱い誤り

→ 値が不正


8.5 実務での推奨手順(重要)

開発時は以下の順序で進めると安定します。


手順

  1. このテンプレをそのまま動かす
  2. 表示確認
  3. 単純ロジックに置き換え
  4. 本来のロジックを追加

理由

  • SetIndexBufferの問題を先に潰せる
  • 表示系と計算系を分離できる

8.6 デバッグ用ミニコード(最強)

問題切り分け用に使います。

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

効果

  • 直線が表示される
  • 配列・描画が正常か確認可能

8.7 実務アドバイス(期待値最大化)

  • 最初から最適化しない
  • prev_calculatedは後回し
  • まず「確実に出る」状態を作る

8.8 結論(重要)

SetIndexBufferは単体ではなく:

SetIndexBuffer
+
ArraySetAsSeries
+
PlotIndexSet

この3点が揃って初めて安定動作します。

9. FAQ(よくある質問と回答方針)

9.1 SetIndexBufferを書いているのに表示されません

回答方針:設定・代入・描画の3点を切り分ける

  • INDICATOR_DATA になっているか
  • OnCalculate() で値を代入しているか
  • PlotIndexSet の描画タイプが正しいか
    → この3点のどれかが欠けているケースが大半

9.2 INDICATOR_DATAとINDICATOR_CALCULATIONSの違いは何ですか?

回答方針:表示可否で明確に区別

  • INDICATOR_DATA → 表示される
  • INDICATOR_CALCULATIONS → 表示されない(内部用)
    → 表示したいなら必ずDATAを使う

9.3 SetIndexBufferはどこで呼ぶべきですか?

回答方針:OnInit一択と明示

  • 基本は OnInit() で1回だけ呼ぶ
  • OnCalculate() で毎回呼ぶ必要はない
    → 初期化処理として扱う

9.4 配列に値を入れているのに線が出ません

回答方針:EMPTY_VALUEと代入漏れを疑う

  • 全要素が EMPTY_VALUE になっていないか
  • 条件分岐で代入されていないバーがないか
  • rates_total 分ループしているか

9.5 indicator_buffersとindicator_plotsの違いは何ですか?

回答方針:役割分離で説明

  • indicator_buffers → 全バッファ数(計算含む)
  • indicator_plots → 表示ライン数
    → buffers ≥ plots が必須条件

9.6 ArraySetAsSeriesは必ず必要ですか?

回答方針:必須ではないが統一が重要

  • 必須ではないが、方向不一致の原因になる
  • 初心者は true に統一するのが安全
    → 表示ズレ防止のため実質必須

9.7 複数バッファを使うと表示がおかしくなります

回答方針:index・property・紐付けの整合性確認

  • indexが0から順番になっているか
  • indicator_buffers と一致しているか
  • 各バッファに対応する描画設定があるか

9.8 prev_calculatedを使うと動かなくなります

回答方針:最適化は後回しにする

  • 初期段階では全ループでOK
  • prev_calculatedは最適化用
    → まず表示確認 → 後で最適化

9.9 SetIndexBufferとPlotIndexSetはどちらが重要ですか?

回答方針:役割の違いを明確化

  • SetIndexBuffer → データ登録(必須)
  • PlotIndexSet → 見た目設定(補助)
    → まずSetIndexBufferが正しくないと何も始まらない

9.10 MQL4との違いはありますか?

回答方針:設計思想の違いを簡潔に説明

  • MQL5は描画と計算が分離されている
  • type(DATA / CALCULATIONS)の概念がある
    → MQL4より厳密で柔軟な設計

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