MQL5でiCustom・CopyBufferの値が取れない原因|4箇所を順に見る

iCustomCopyBuffer で値が取れないときは、ハンドル・戻り値・パラメータ・バー位置の4箇所を順に見れば切り分けられます。

CopyBuffer は失敗時に0ではなく -1 を返し、iCustom は失敗時に INVALID_HANDLE を返します。この2つの戻り値を見ていないケースが最も多いです。

確認環境:MetaTrader 5(Windows 11)/確認日 2026年9月2日。公式ドキュメントの引用は同日に確認したものです。

見る場所は4つ

症状は「0が返る」「巨大な数値が返る」「配列が空のまま」などいくつかありますが、原因は下の4つに収まります。上から順に潰してください。

値が取れないときに確認する4箇所
# 確認すること 失敗しているときの見え方
1 ハンドルが取れているか INVALID_HANDLE/エラー4802
2 CopyBuffer の戻り値 -1、または要求した本数より少ない
3 iCustom のパラメータ エラーは出ないが値の中身が違う
4 そのバーに値があるか 巨大な数値(EMPTY_VALUE

3番が厄介です。エラーが一切出ないのに、返ってくる値だけが間違っています。

1. ハンドルが取れているか

iCustom は失敗するとハンドルではなく INVALID_HANDLE を返します。公式ドキュメントの記述は次のとおりです。

指定されたテクニカル指標ハンドル。失敗の場合 INVALID_HANDLE。

出典:MQL5リファレンス「iCustom」 https://www.mql5.com/ja/docs/indicators/icustom

このとき、ツールボックスの「エキスパート」タブに エラー4802(ERR_INDICATOR_CANNOT_CREATE) が出ます。まずここを見てください。

int handle = iCustom(_Symbol, PERIOD_CURRENT, "MyIndicator", 12, 5);
if(handle == INVALID_HANDLE)
  {
   Print("iCustom failed: ", GetLastError());
   return(INIT_FAILED);
  }

ハンドル取得に失敗する原因で多いのは、インジケーター名のパスの書き方です。MQL5\Indicators の直下でないなら、サブフォルダを含めて指定します(例:"realine\\MyIndicator")。拡張子は付けません。

そもそもインジケーター側がコンパイルできていない場合もハンドルは取れません。MQL5のコンパイルエラーが消えない時に見る順番を先に確認してください。

ハンドルは OnInit で1回だけ取得してください。OnTick の中で毎回 iCustom を呼ぶと、ハンドルが増え続けてメモリを圧迫します。使い終わったら IndicatorRelease() で解放します。

2. CopyBuffer の戻り値を見ているか

ここが最も多い見落としです。公式ドキュメントには次のように書かれています。

複製されたデータ数(エラーの場合は -1 )

出典:MQL5リファレンス「CopyBuffer」 https://www.mql5.com/ja/docs/series/copybuffer

失敗すると0ではなく -1 です。「0が返ってきた」と思っているなら、それは失敗ではなく別の問題です。

さらに注意すべきなのは、成功しても要求した本数より少ない数が返ることがある点です。戻り値を本数と比較してください。

double buf[];
int copied = CopyBuffer(handle, 0, 0, 3, buf);
if(copied < 3)
  {
   Print("CopyBuffer copied only ", copied, " err=", GetLastError());
   return;   // 足りない状態で buf[2] を読まない
  }

戻り値を見ずに buf[2] を読むと、中身が未定義のまま計算に流れ込みます。エラーにならずに間違った値で動き続けるので、原因に辿り着くのが遅れます。

EA起動直後にコピーできないのは正常なこともあります。インジケーター側の計算が終わっていないためで、数ティック待てば取れるようになります。起動直後の1回で判断しないでください。

3. iCustom のパラメータがインジ側と一致しているか

これはエラーが出ないので気づきにくい問題です。公式ドキュメントには次のように書かれています。

パラメータの型と順序がカスタム指標の定義と一致している必要があります。パラメータを指定しない場合は初期値が使用されます。

出典:MQL5リファレンス「iCustom」 https://www.mql5.com/ja/docs/indicators/icustom

つまり、パラメータを省略してもハンドルは取れます。ただし、その場合はインジケーター側の初期値で計算されます。チャートに載せたインジケーターを手で設定変更していると、画面に見えている線とEAが読んでいる値が別物になります。

「チャートでは正しく出ているのに、EAが読むと違う」の典型がこれです。

確認する順番は次のとおりです。

  1. インジケーター側の input 宣言を上から順に並べる
  2. iCustom の引数と、型と順序を1つずつ突き合わせる
  3. 数が合っていても、intdouble が入れ替わっていないか見る

なお、チャート上でインジケーターの設定を変えても反映されないという別の症状もあります。こちらは原因が違うので、MT5でインジケーターの初期値を変更しても反映されない理由を参照してください。

4. そのバーにインジ側の値が存在するか

ハンドルも戻り値も正常なのに、値だけが 1.7976931348623157e+308 のような巨大な数値になることがあります。これは EMPTY_VALUE で、「そのバーには値が無い」という意味です。エラーではありません。

よくあるのは次の2つです。

  • 計算に必要な本数が足りないバー。期間20の移動平均なら、最初の19本には値がありません
  • 条件を満たしたときだけ描画するインジケーター。サインやZigZagのように、点が立つバーにしか値を入れない設計のものは、大半のバーが EMPTY_VALUE です

後者を「値が取れない」と誤解すると、直しようのないものを直そうとして時間を失います。まず、そのインジケーターが全バーに値を入れる設計かどうかを確認してください。

5. 配列の並びを誤解していないか

ここは、日本語の解説記事に広く出回っている説明と、公式ドキュメントの記述が食い違っている箇所です。

公式が言っていること

受け取り側の配列が as_series=true であるか as_series=false であるかは関係ありません。データは、一番古い要素が配列に割り当てられた物理メモリの先頭に配置されるように複製されます

出典:MQL5リファレンス「CopyBuffer」 https://www.mql5.com/ja/docs/series/copybuffer

よくある説明との違い

日本語の記事では「ArraySetAsSeries を使って、0番目が最新になるように並べ替える」と説明されていることがあります。実際には並べ替えは起きません。データは常に古い順に物理メモリへ書かれ、as_series は「その並びをどちら側から数えるか」を変えるだけです。

結果として ArraySetAsSeries(buf, true)buf[0] が最新になるのは、記事の説明どおりです。違うのは仕組みのほうです。「並べ替えられる」と理解していると、CopyBuffer の開始位置や本数を変えたときに添字がどう動くかを予測できず、原因に辿り着けなくなります。

公式には、開始位置についても明記されています。

複製されたデータの要素は、開始位置から現在から過去に向かって数えられます。0 の開始位置は現在足(の指標値)を意味します

出典:MQL5リファレンス「CopyBuffer」

開始位置0は現在のバーです。現在のバーはまだ確定していないため、確定した値だけを使いたいなら開始位置を1にします。

4ステップで切り分ける

  1. ハンドルを INVALID_HANDLE と比較する。失敗ならエキスパートタブでエラー番号を見る
  2. CopyBuffer の戻り値を要求本数と比較する。-1 と「少ない」を区別する
  3. 値が返るのに中身が違うなら、iCustom の引数をインジ側の input と突き合わせる
  4. 巨大な値なら EMPTY_VALUEそのバーに値が無いだけなので、インジの設計を確認する

1と2でエラーの有無が分かり、3と4で「エラーは無いが値がおかしい」が分かります。この順番を飛ばすと、3番の症状を2番の問題として調べ続けることになります。

iCustomを使わないという選択肢

ここまでの4つは、いずれも実行時にインジケーターとEAを直結していることから生じる問題です。当サイトでMQL5のインジケーターとEAを開発した際は、EA側でインジの値を読む方式として iCustom を採らず、インジケーターがファイルへ書き出したものをEAが読む構成にしました。

この構成にすると、上の4つのうち3つが実行時に発生しなくなります。

  • ハンドル管理が不要になる(1が消える)
  • パラメータの一致を実行時に気にしなくてよい(3が消える)
  • 未計算バーの扱いを書き出す側で決められる(4を書き出し時点で吸収できる)

代わりに、ファイルの保存先と文字コードという別の問題を抱えます。こちらはMT5でCSVが出力されない・文字化けする原因で扱っています。

どちらが良いという話ではありません。リアルタイム性が要るなら iCustom のほうが素直です。上の4点を潰す手間と、ファイル入出力を管理する手間を比べて決めてください。

この記事で確認していないこと

  • 実機での網羅的な再現テスト。本文の技術的な記述はMQL5公式ドキュメント(2026年9月2日確認)と開発経験に基づくもので、4つの症状すべてを意図的に再現させて検証したものではありません
  • EMPTY_VALUE の具体的な値。巨大な数値が返ることは確認していますが、定数の実体が処理系でどう定義されているかは確認していません
  • MT5のビルドによる差。確認は1環境のみです

関連記事

参照した公式ドキュメント

いずれも2026年9月2日に確認しました。