技術辞典

MQL5 CopyBufferで値が取れない原因と確認ポイント

EAファンクラブ

MQL5でEAからインジケーター値を取得する時は、CopyBufferを使う場面が多くあります。

しかし、CopyBufferは「呼べば必ず値が返る」関数ではありません。インジケーターハンドルの生成失敗、BarsCalculated不足、buffer番号の間違い、shiftの指定ミス、取得本数不足、配列の向き、EMPTY_VALUE、iCustomの引数不一致、未確定足の扱いなどにより、値が取れないことがあります。

特に、EA化やカスタムインジケーター連携では、「チャート上ではインジケーターが表示されているのにEA側では値が取れない」「CopyBufferの戻り値が0または-1になる」「error 4806が出る」「取得した値が0やEMPTY_VALUEに見える」といった問題が起きやすくなります。

このページでは、MQL5のCopyBufferで値が取れない原因を、handle、INVALID_HANDLE、BarsCalculated、buffer番号、shift、取得本数、EMPTY_VALUE、error 4806、iCustom、ログ確認の観点から整理します。

なお、このページはMQL5開発における技術確認を目的とした内容です。売買判断、推奨エントリー、推奨ロット、利益保証、損失回避保証を行うものではありません。

CopyBufferとは何か

CopyBufferは、MQL5でインジケーターのバッファ値を取得するための関数です。

iMA、iRSI、iATR、iBandsなどの標準インジケーターや、iCustomで呼び出したカスタムインジケーターは、通常、インジケーターハンドルを作成してからCopyBufferで値を取得します。

項目役割確認ポイント
handleインジケーターを参照する識別子INVALID_HANDLEになっていないか
buffer番号取得するインジケーターバッファの番号表示ラインとbuffer番号が一致しているか
start position / shiftどのバーから取得するか0が現在足、1が1本前の確定足として扱われる場面が多い
count取得する本数必要本数以上を要求しているか
配列取得値の格納先ArraySetAsSeriesの向きと参照位置を確認する

CopyBufferで値が取れない場合は、CopyBufferだけを見るのではなく、handle生成、インジケーター計算状況、buffer番号、バー本数、取得後の配列参照まで順番に確認する必要があります。

CopyBufferで値が取れない時の確認順序

CopyBufferの不具合確認では、いきなりコード全体を書き換えるのではなく、確認順序を固定すると原因を切り分けやすくなります。

順番確認項目見る内容
1handleINVALID_HANDLEではないか
2GetLastErrorhandle生成やCopyBuffer失敗時のエラー番号
3BarsCalculatedインジケーター計算済みバー数が足りているか
4Bars / iBarsチャートや対象時間足にバーが十分あるか
5buffer番号取得したいラインのbuffer番号が正しいか
6shift現在足か確定足か、参照バーを取り違えていないか
7取得本数CopyBufferのcountと配列サイズが合っているか
8EMPTY_VALUE値は取得できているが未描画値ではないか
9iCustomファイル名、パス、input順序、引数型が一致しているか

この順序で確認すれば、「ハンドルが作れていない」のか、「計算がまだ終わっていない」のか、「buffer番号が違う」のか、「値は取れているが参照位置が違う」のかを分けやすくなります。

基本的なCopyBufferの流れ

標準インジケーターの値を取得する場合、基本的な流れは以下です。

int ma_handle = INVALID_HANDLE;

int OnInit()
{
   ma_handle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);

   if(ma_handle == INVALID_HANDLE)
   {
      Print("HANDLE_ERROR name=iMA last_error=", GetLastError());
      return INIT_FAILED;
   }

   return INIT_SUCCEEDED;
}

void OnTick()
{
   double ma_values[];
   ArraySetAsSeries(ma_values, true);

   int copied = CopyBuffer(ma_handle, 0, 0, 3, ma_values);

   if(copied <= 0)
   {
      Print("COPYBUFFER_ERROR copied=", copied,
            " last_error=", GetLastError());
      return;
   }

   Print("MA_VALUE current=", DoubleToString(ma_values[0], _Digits),
         " prev=", DoubleToString(ma_values[1], _Digits));
}

void OnDeinit(const int reason)
{
   if(ma_handle != INVALID_HANDLE)
   {
      IndicatorRelease(ma_handle);
      ma_handle = INVALID_HANDLE;
   }
}

この例では、OnInitでiMAのhandleを作成し、OnTickでCopyBufferを呼び、OnDeinitでIndicatorReleaseを行っています。

重要なのは、毎tickでiMAを作り直さないことです。handle生成はOnInitなどの初期化処理で行い、OnTickでは既存handleを使って値を取得する形にすると、処理負荷や不安定な挙動を抑えやすくなります。

原因1:INVALID_HANDLEになっている

CopyBufferで値が取れない時に最初に確認するのは、handleがINVALID_HANDLEになっていないかです。

handleが正しく作成できていない状態でCopyBufferを呼んでも、期待する値は取得できません。

原因起きやすい状況確認方法
インジケーター名が違うiCustomでファイル名やパスを間違えているhandle作成直後にINVALID_HANDLEを確認する
input引数が違うカスタムインジケーターのinput順序とEA側指定が一致していないiCustomの引数をインジ側input順に合わせる
対象銘柄が不正Market Watchにない銘柄やsuffix違いSymbolSelectや_symbol名を確認する
時間足指定が不正想定外のtimeframeを渡しているPERIOD_CURRENTやENUM_TIMEFRAMESを確認する
初期化前に使っているhandle生成前にCopyBufferを呼ぶOnInit完了ログとCopyBufferログの順序を見る

handle生成失敗時は、CopyBuffer側ではなく、iMA、iRSI、iCustomなどのhandle作成部分を先に確認してください。

handle作成時にログへ出す項目

handle作成時は、単に「失敗」と出すだけでは原因が追いにくくなります。少なくとも、symbol、timeframe、indicator name、input、last_errorをログに残します。

int CreateMaHandle(const string symbol,
                   const ENUM_TIMEFRAMES timeframe,
                   const int period)
{
   ResetLastError();

   int handle = iMA(symbol, timeframe, period, 0, MODE_SMA, PRICE_CLOSE);
   int err = GetLastError();

   Print("HANDLE_CREATE",
         " indicator=iMA",
         " symbol=", symbol,
         " timeframe=", timeframe,
         " period=", period,
         " handle=", handle,
         " last_error=", err);

   if(handle == INVALID_HANDLE)
      return INVALID_HANDLE;

   return handle;
}

このようにログ化すると、対象銘柄、時間足、periodのどれで失敗しているかを確認できます。

原因2:BarsCalculatedが不足している

handleが作れていても、インジケーター側の計算がまだ終わっていない場合、CopyBufferで値が取れないことがあります。

この時に確認するのがBarsCalculatedです。BarsCalculatedは、対象インジケーターで計算済みのバー数を確認するために使います。

bool IsIndicatorReady(const int handle, const int required_bars)
{
   int calculated = BarsCalculated(handle);

   Print("BARS_CALCULATED",
         " handle=", handle,
         " calculated=", calculated,
         " required=", required_bars);

   if(calculated < required_bars)
      return false;

   return true;
}

EA起動直後、時間足変更直後、銘柄変更直後、テスター開始直後、iCustomで重いカスタムインジケーターを呼んだ直後は、BarsCalculatedが十分でない場合があります。

場面起きやすい問題対応
EA起動直後handleは作れたが、まだ計算済みバー数が不足BarsCalculatedが必要本数以上になるまで待つ
時間足変更直後内部計算が再構築される初回数tickは取得失敗を許容し、ログを抑制する
複数時間足上位足のバー数が不足する対象timeframeのiBarsも確認する
カスタムインジケーター内部計算やバッファ初期化に時間がかかるiCustom成功後、BarsCalculatedとCopyBufferを分けて確認する

BarsCalculated不足は異常ではなく、準備未完了の状態です。売買判定に使うEAでは、準備未完了のままENTRY判定へ進まないようにします。

原因3:buffer番号が間違っている

CopyBufferの第2引数には、取得するインジケーターバッファ番号を指定します。

このbuffer番号が違うと、意図したラインではなく別のラインを読んだり、何も値が入っていないバッファを読んだりすることがあります。

確認対象内容注意点
標準インジケーターiMAなら通常buffer 0複数ライン系ではbufferが複数ある
iBands上限・中央・下限など複数bufferどのbufferがどのラインか確認する
カスタムインジケーターSetIndexBufferの順序に依存チャート上の見た目だけで判断しない
非表示バッファ計算用bufferが存在する場合がある表示ラインと取得bufferが一致しない場合がある

カスタムインジケーターでは、SetIndexBufferで割り当てた順序と、EA側で指定するbuffer番号を一致させる必要があります。

buffer番号を確認する時の考え方

カスタムインジケーターのEA化では、インジ側のバッファ定義を確認します。

double BuyBuffer[];
double SellBuffer[];

int OnInit()
{
   SetIndexBuffer(0, BuyBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, SellBuffer, INDICATOR_DATA);

   return INIT_SUCCEEDED;
}

このようなインジケーターなら、EA側ではBuyBufferをbuffer 0、SellBufferをbuffer 1として取得する設計になります。

double buy_signal[];
double sell_signal[];

ArraySetAsSeries(buy_signal, true);
ArraySetAsSeries(sell_signal, true);

int copied_buy  = CopyBuffer(custom_handle, 0, 0, 3, buy_signal);
int copied_sell = CopyBuffer(custom_handle, 1, 0, 3, sell_signal);

buffer番号が分からない場合は、インジケーターのソースコード、SetIndexBuffer、PlotIndexSetInteger、表示ラインの順序、データウィンドウでの表示を確認します。

原因4:shiftの指定を取り違えている

CopyBufferでは、どのバーから値を取得するかを指定します。

EAの判定では、現在足の値を使うのか、1本前の確定足を使うのかを明確にする必要があります。

shift意味の目安注意点
0現在足未確定で変動中。リペイントや値変化の影響を受けやすい
11本前の確定足バー確定型EAで使いやすい
2以降さらに過去のバークロス判定や連続条件で使う

「チャート上ではサインが出ているのにEAが反応しない」という場合、EA側がshift 1を見ているのに、チャート表示はshift 0の変動中サインを見ていることがあります。

逆に、EA側でshift 0を使うと、足が確定する前に値が変わり、バックテストや実運用でシグナルの見え方が変わる場合があります。

現在足と確定足を分けてログに出す

shiftの取り違えを避けるため、現在足と確定足を同時にログへ出すと確認しやすくなります。

double values[];
ArraySetAsSeries(values, true);

int copied = CopyBuffer(handle, 0, 0, 3, values);

if(copied >= 3)
{
   Print("COPYBUFFER_VALUES",
         " current_shift0=", DoubleToString(values[0], _Digits),
         " closed_shift1=", DoubleToString(values[1], _Digits),
         " closed_shift2=", DoubleToString(values[2], _Digits));
}

EAのENTRY判定に使う値は、現在足か確定足かを仕様として決め、ログにも basis=SHIFT0basis=SHIFT1 のように残すと切り分けしやすくなります。

原因5:取得本数と配列参照が合っていない

CopyBufferで取得する本数が少ないのに、配列の過去要素を参照すると、想定外の値や配列範囲外の問題につながります。

たとえば、クロス判定で現在値と1本前、2本前を比較するなら、少なくとも3本以上を取得する必要があります。

用途必要本数の目安
現在値だけ確認1本values[0]
確定足を見る2本以上values[1]
クロス判定3本以上values[1]とvalues[2]を比較
連続条件条件本数以上直近3本連続など

CopyBufferの戻り値は、実際にコピーできた要素数です。要求した本数と同じとは限らないため、戻り値を確認してから配列を参照します。

原因6:ArraySetAsSeriesの向きが合っていない

配列の向きも、CopyBufferで値を扱う時の混乱原因になります。

ArraySetAsSeriesをtrueにした配列では、通常、index 0を最新バーとして扱いやすくなります。一方、falseの場合は、配列の並びを別の前提で読むことになります。

設定考え方注意点
ArraySetAsSeries(values, true)values[0]を最新側として扱いやすいEAの時系列処理でよく使う
ArraySetAsSeries(values, false)通常配列として扱う参照位置を取り違えないようにする

どちらが正しいというより、EA内で一貫していることが重要です。取得後にvalues[0]、values[1]、values[2]をログに出し、想定したバーの値になっているか確認してください。

原因7:EMPTY_VALUEを値なしと区別できていない

CopyBuffer自体は成功していても、取得した値がEMPTY_VALUEの場合があります。

EMPTY_VALUEは、インジケーター側で「このバーには描画しない」「この位置にはサインがない」という意味で使われることがあります。サイン系インジケーターや矢印インジケーターでは特に重要です。

状態意味対応
CopyBuffer戻り値が0以下値のコピー自体に失敗GetLastError、BarsCalculated、handleを確認
CopyBufferは成功したがEMPTY_VALUEそのバーに描画値がないサインなしとして扱う
0.0が返る実値として0の場合と未初期化が混ざるインジ側の仕様を確認する
DBL_MAXに近い値EMPTY_VALUE相当の可能性EMPTY_VALUE比較を行う

サイン系インジケーターでは、「値が取れない」のではなく、「値は取れているが、そのバーにサインがない」だけの場合があります。CopyBufferの戻り値と取得値の中身を分けて確認してください。

EMPTY_VALUE確認コード例

bool HasSignalValue(const double value)
{
   if(value == EMPTY_VALUE)
      return false;

   if(!MathIsValidNumber(value))
      return false;

   return true;
}

void PrintSignalValue(const double value, const int shift)
{
   if(value == EMPTY_VALUE)
   {
      Print("SIGNAL_VALUE shift=", shift, " status=EMPTY_VALUE");
      return;
   }

   if(!MathIsValidNumber(value))
   {
      Print("SIGNAL_VALUE shift=", shift, " status=INVALID_NUMBER");
      return;
   }

   Print("SIGNAL_VALUE shift=", shift,
         " value=", DoubleToString(value, _Digits));
}

EA側では、EMPTY_VALUEをエラー扱いするのか、単に「サインなし」と扱うのかを仕様として分けます。通常、サイン系インジケーターではEMPTY_VALUEは異常ではなく、シグナルなしの状態として扱います。

原因8:error 4806が出ている

CopyBufferで値が取れない時に、GetLastErrorでerror 4806が出る場合があります。

このエラーは、インジケーターのデータ取得や計算状態に関係して発生することがあります。原因を1つに断定するのではなく、handle、BarsCalculated、対象buffer、バー本数、iCustom引数、テスター条件を順番に確認してください。

確認項目見る内容対応
handleINVALID_HANDLEではないかhandle生成直後のログを確認する
BarsCalculated必要本数以上あるか計算不足なら判定を待つ
buffer番号存在するbufferを読んでいるかSetIndexBufferの順序を確認する
count要求本数が過大ではないかまず1〜3本で確認する
iCustom引数input順序・型・ファイル名が合っているかインジ側inputとEA側指定を照合する
履歴データ対象時間足のバーが十分あるかiBars、チャート読み込み、テスター期間を確認する

error 4806が出た時に、すぐにロジック全体を作り直す必要はありません。まずは、CopyBuffer直前の状態をログへ出し、どの前提が不足しているかを確認します。

error 4806確認用のログ例

bool CopyIndicatorValue(const int handle,
                        const int buffer_index,
                        const int shift,
                        double &out_value)
{
   out_value = EMPTY_VALUE;

   if(handle == INVALID_HANDLE)
   {
      Print("COPYBUFFER_BLOCK reason=INVALID_HANDLE");
      return false;
   }

   int calculated = BarsCalculated(handle);

   if(calculated <= shift)
   {
      Print("COPYBUFFER_BLOCK reason=BARS_NOT_READY",
            " calculated=", calculated,
            " shift=", shift);
      return false;
   }

   double temp[];
   ArraySetAsSeries(temp, true);

   ResetLastError();

   int copied = CopyBuffer(handle, buffer_index, shift, 1, temp);
   int err = GetLastError();

   Print("COPYBUFFER_TRACE",
         " handle=", handle,
         " buffer=", buffer_index,
         " shift=", shift,
         " copied=", copied,
         " calculated=", calculated,
         " last_error=", err);

   if(copied != 1)
      return false;

   out_value = temp[0];
   return true;
}

このように、handle、buffer、shift、copied、BarsCalculated、last_errorを同じログに出すと、CopyBuffer失敗時の原因を追いやすくなります。

原因9:iCustomの指定が合っていない

カスタムインジケーターをEAから呼ぶ場合は、iCustomの指定ミスが原因になることがあります。

iCustomでは、インジケーター名、配置パス、input引数の順序、input型、対象symbol、timeframeを正しく指定する必要があります。

確認項目内容よくあるミス
ファイル名インジケーター名拡張子、フォルダ名、全角半角、スペース違い
配置場所MQL5/Indicators配下サブフォルダ指定漏れ
input順序インジ側inputとEA側引数の順序途中のinputを省略して順序がズレる
input型int、double、bool、string、enumなど型違いによりhandle生成失敗
buffer番号取得したいライン表示ラインとbuffer番号の誤認

iCustomは、EA側だけ見ても原因が分からないことがあります。カスタムインジケーター側のinput定義、SetIndexBuffer、描画条件、EMPTY_VALUE出力条件を合わせて確認してください。

iCustomの基本確認コード例

int custom_handle = INVALID_HANDLE;

int OnInit()
{
   ResetLastError();

   custom_handle = iCustom(_Symbol,
                           PERIOD_CURRENT,
                           "MyCustomIndicator",
                           20,
                           2.0,
                           true);

   int err = GetLastError();

   Print("ICUSTOM_HANDLE",
         " symbol=", _Symbol,
         " timeframe=", PERIOD_CURRENT,
         " handle=", custom_handle,
         " last_error=", err);

   if(custom_handle == INVALID_HANDLE)
      return INIT_FAILED;

   return INIT_SUCCEEDED;
}

この例では、iCustomに3つのinput値を渡しています。実際には、対象インジケーターのinput順序と完全に一致させる必要があります。

インジケーター側でinputが増減した場合、EA側のiCustom引数も修正しなければ、handle生成や値取得が崩れる可能性があります。

原因10:インジケーター側がまだ値を出していない

CopyBufferが成功しても、インジケーター側がそのバーに値を出していなければ、EA側では有効な値として使えません。

たとえば、矢印サイン、条件成立時だけ値を出すバッファ、一定期間を過ぎないと計算しないインジケーターでは、値が空になるバーがあります。

インジケーターの種類値がない理由EA側の扱い
移動平均などの連続線計算期間不足の初期バー必要本数がそろうまで判定しない
矢印サインサインが出たバーだけ値が入るEMPTY_VALUEはサインなしとして扱う
ヒストグラム条件により0やEMPTY_VALUEを出す0とEMPTY_VALUEの意味を分ける
リペイント系未確定足で値が変わる確定足基準で確認する
複数時間足系上位足の確定まで値が変わる時間足同期と確定足を確認する

「値が取れない」と判断する前に、そのインジケーターが本当に毎バー値を出す設計なのか、条件成立時だけ値を出す設計なのかを確認してください。

チャート表示とEA取得値が違う時の確認

チャート上では値やサインが見えているのに、EA側で取得した値と違う場合があります。

この場合は、表示と取得の基準が一致しているかを確認します。

確認項目内容確認方法
対象時間足チャート時間足とEAのtimeframe指定PERIOD_CURRENTか固定時間足かを見る
対象バー現在足か確定足かshift 0 / 1をログで比較する
buffer番号表示ラインと取得bufferSetIndexBufferとData Windowを確認する
リペイント未確定足で値が変わるか確定後の値と比較する
表示条件描画だけ非表示になっていないかEMPTY_VALUEやPlot設定を確認する

EA化では、チャート上の見た目ではなく、EAがどのbufferのどのshiftを見ているかが重要です。ログにbuffer、shift、value、bar timeを出すと、チャート表示との照合がしやすくなります。

複数時間足でCopyBufferを使う時の注意点

複数時間足のインジケーター値をEAへ取り込む場合、現在チャートのバーと上位足のバーが一致するとは限りません。

たとえば、M5チャート上でH1のインジケーター値を取得する場合、M5の新バーごとにH1の確定値が変わるわけではありません。

確認項目内容注意点
対象timeframePERIOD_H1などチャート時間足と混同しない
iBars上位足のバー数対象時間足に十分な履歴があるか確認する
バー時刻iTimeやCopyTimeどの上位足バーを参照しているか確認する
確定足shift 1を使うか上位足の未確定値を使わない設計にする

複数時間足では、CopyBufferだけでなく、CopyTime、iTime、iBarShiftなどと組み合わせて、どのバーの値を使っているか確認する場合があります。

バックテストで値が取れない時の確認

Strategy TesterでCopyBufferの値が取れない場合、実チャートとは別の確認が必要です。

テスターでは、対象期間、ヒストリカルデータ、時間足、使用インジケーター、初期化タイミングによって、起動直後に必要本数が足りない場合があります。

確認項目見る内容ログ例
テスト期間インジ計算に必要な過去バーがあるかTEST_PERIOD
BarsCalculated計算済みバー数BARS_CALCULATED
CopyBuffer戻り値要求本数を取得できたかCOPYBUFFER_TRACE
初期バー計算期間不足の最初のバーWARMUP_SKIP
カスタムインジテスターで読み込めているかICUSTOM_HANDLE

バックテストでは、開始直後の数バーで値が取れないことがあります。この場合は、すぐに異常扱いせず、ウォームアップ期間として判定を見送る設計が必要です。

EAのENTRY判定へ使う時の責務分離

CopyBufferで取得した値をそのまま発注処理へ渡すのは避けます。

実務上は、値取得、値の妥当性確認、signal判定、entry可否、executionを分けると原因を追いやすくなります。

責務内容ログ例
取得CopyBufferで値を取得するCOPYBUFFER_TRACE
妥当性確認EMPTY_VALUE、NaN、取得本数を確認するVALUE_VALIDATE
signal判定インジ値からBUY / SELL / WAITを判断するSIGNAL_EVAL
entry gateスプレッド、時間、ポジション数などを見るENTRY_GATE
executionOrderSendやCTradeで発注するORDER_SEND

この分離がないと、CopyBufferの失敗なのか、signal条件不成立なのか、entry gateで止まったのか、発注処理で失敗したのかが分かりにくくなります。

ログに残すべき項目

CopyBuffer関連の不具合は、ログが不足していると原因を追えません。

ログ名出す内容目的
HANDLE_CREATEindicator、symbol、timeframe、handle、last_errorhandle生成の成否を確認する
BARS_CALCULATEDhandle、calculated、required計算済みバー数を確認する
COPYBUFFER_TRACEbuffer、shift、count、copied、last_errorCopyBufferの取得結果を確認する
VALUE_VALIDATE取得値、EMPTY_VALUE、NaN判定値の妥当性を確認する
SIGNAL_EVAL判定basis、shift、signal結果EA側の判定理由を確認する
ICUSTOM_HANDLEインジ名、input、handle、last_erroriCustom連携の失敗を確認する

ログ名を固定すると、Expertsログで検索しやすくなります。特に、error 4806や値なし状態を調べる時は、CopyBufferの戻り値だけでなく、直前のBarsCalculatedとhandle状態も一緒に確認してください。

よくある失敗パターン

失敗パターン起きる問題確認すること
OnTickで毎回handleを作る処理が重くなり、値取得が不安定になるhandleはOnInitで作る
INVALID_HANDLEを確認しないCopyBuffer失敗の原因が分からないhandle生成直後にログを出す
BarsCalculatedを見ない計算前に値を取りに行く必要本数以上になるまで待つ
buffer番号を推測する別ラインや空バッファを読むSetIndexBufferの順序を確認する
shift 0とshift 1を混同するチャート表示とEA判定がズレる現在足と確定足を分ける
EMPTY_VALUEをエラー扱いするサインなしを異常と誤認するCopyBuffer成功と値の有無を分ける
iCustom引数がズレるhandle生成失敗や値取得失敗インジ側input順と一致させる
ログが少ない原因調査ができないhandle、buffer、shift、copiedを出す

開発・改修依頼前に整理したい情報

CopyBufferやiCustomの値取得不具合を相談する場合は、事前に以下を整理しておくと、原因確認が進めやすくなります。

整理項目記入例確認理由
対象EA / インジ名SampleEA、CustomSignal.ex5どのファイルを確認するか特定するため
MT5環境デモ / リアル、ブローカー、銘柄銘柄名やsuffixの違いを確認するため
対象時間足M15、H1などチャート時間足と取得時間足の違いを確認するため
取得したいbufferBuyBuffer、SellBuffer、MAラインなどbuffer番号を確認するため
shift0、1、確定足基準など現在足か確定足かを確認するため
ExpertsログHANDLE_CREATE、COPYBUFFER_TRACEhandle、copied、last_errorを確認するため
インジ側inputperiod、threshold、modeなどiCustom引数の順序を確認するため
ソース有無mq5あり / ex5のみSetIndexBufferや内部仕様を確認できるか判断するため

口座番号、認証情報、Webhook URL、APIキー、個人情報は共有しないでください。ログを共有する場合は、必要な箇所だけを伏せ字にして整理してください。

実務チェックリスト

  • handleがINVALID_HANDLEではないことを確認した
  • handle生成時にGetLastErrorをログへ出した
  • BarsCalculatedが必要本数以上あることを確認した
  • 対象symbolとtimeframeが正しいことを確認した
  • buffer番号が取得したいラインと一致していることを確認した
  • shift 0とshift 1の違いを確認した
  • CopyBufferの戻り値copiedを確認した
  • 取得本数と配列参照位置が合っていることを確認した
  • ArraySetAsSeriesの向きと参照位置を確認した
  • EMPTY_VALUEをサインなしとして扱うか、異常として扱うかを決めた
  • error 4806が出る時は、handle、BarsCalculated、buffer、shiftを順番に確認した
  • iCustomでは、インジ名、パス、input順序、input型を確認した
  • チャート表示とEA取得値を、bar time、buffer、shiftで照合した
  • EAのENTRY判定へ使う前に、値取得、妥当性確認、signal判定を分けた

よくある質問

CopyBufferの戻り値が0になるのはなぜですか?

取得できたデータ数が0という意味です。handle、BarsCalculated、対象時間足のバー数、buffer番号、取得本数、iCustom引数を確認してください。EA起動直後や時間足変更直後は、まだインジケーター計算が終わっていない場合があります。

CopyBufferの戻り値が-1になる場合は何を見ますか?

GetLastErrorを確認し、handleがINVALID_HANDLEになっていないか、buffer番号が正しいか、iCustomの指定が正しいかを確認します。あわせてBarsCalculatedと対象時間足のバー数もログに出してください。

error 4806が出た場合はどうすればよいですか?

まず、handle、BarsCalculated、buffer番号、shift、取得本数、iCustom引数を順番に確認します。error番号だけで原因を断定せず、CopyBuffer直前の状態をログへ出して、計算不足なのか指定ミスなのかを切り分けてください。

チャートではサインが出ているのにEAで取得できないのはなぜですか?

EA側が見ているbuffer番号やshiftが、チャート上で見ているサインと違う可能性があります。また、チャート表示は現在足の変動中サインで、EAは確定足を見ている場合もあります。buffer、shift、bar timeをログで照合してください。

EMPTY_VALUEはエラーですか?

必ずしもエラーではありません。サイン系インジケーターでは、そのバーにサインがないことをEMPTY_VALUEで表す場合があります。CopyBufferの失敗と、CopyBuffer成功後のEMPTY_VALUEは分けて扱ってください。

iCustomで値が取れない時は何を確認しますか?

インジケーター名、サブフォルダ、input引数の順序、input型、buffer番号、SetIndexBuffer、EMPTY_VALUEの出力条件を確認します。EA側だけでなく、カスタムインジケーター側の仕様確認が必要です。

関連ページ

関連テーマ確認ページ確認できること
iCustom連携MQL5 iCustomでインジケーターをEA化する時の注意点iCustomでカスタムインジケーターをEAから呼ぶ時の確認
ハンドル管理MQL5 CopyBufferとインジケーターハンドル管理を実コードで解説handle、IndicatorRelease、CopyBuffer取得helperの整理
インジケーター関数MQL5インジケーター関数辞典iCustom、CopyBuffer、SetIndexBuffer、OnCalculateの概要
EAへの値取り込みMQL5でインジケーター値をEAに取り込む方法標準インジケーターやカスタムインジケーター値をEAへ渡す基本
インジ開発とEA連携MQL5インジケーター開発・EA連携完全ガイドOnCalculate、SetIndexBuffer、CopyBuffer、EA連携の全体像
OnInit確認MQL5 OnInitの役割と初期化失敗の確認handle生成、初期化失敗、INIT_FAILEDの確認
イベント処理MQL5イベント処理完全ガイドOnInit、OnTick、OnTimer、OnDeinitの責務分離
ログ設計MQL5デバッグ・ログファースト開発完全ガイド値取得失敗や判定不成立をログで追う考え方
EAサンプルコードMQL5 EAサンプルコードの読み方OnInit、OnTick、OrderSend、CopyBufferを含むEA構造の読み方
開発・改修相談MT4/MT5の開発・改修相談はこちらCopyBufferやiCustomの値取得不具合を相談する前の整理

まとめ

MQL5のCopyBufferで値が取れない場合は、CopyBufferの呼び出し部分だけを見ても原因を特定できないことがあります。

まずは、handleがINVALID_HANDLEではないか、BarsCalculatedが必要本数以上あるか、buffer番号が正しいか、shiftと取得本数が合っているか、EMPTY_VALUEを誤解していないかを確認してください。

iCustomでカスタムインジケーターを呼んでいる場合は、インジケーター名、配置パス、input順序、input型、SetIndexBuffer、表示ラインとbuffer番号の対応も確認が必要です。

error 4806が出る場合も、エラー番号だけで原因を断定せず、handle、buffer、shift、copied、BarsCalculated、GetLastErrorを同じログに出して切り分けることが重要です。

EA化では、CopyBufferの値取得、値の妥当性確認、signal判定、entry gate、発注処理を分けて設計してください。ログで各段階を追えるようにしておくと、バックテスト、実運用、問い合わせ対応で原因を確認しやすくなります。

ABOUT ME
記事URLをコピーしました