EAでCopyBufferを使う際は、インジケーターの計算完了を確認しないと未準備の値を売買判定へ流す恐れがあります。BarsCalculated、戻り値、配列方向、参照バーを確認し、取得失敗を安全に処理するMQL5実装を解説します。
値が取れない瞬間を売買判定に流さない
MQL5でインジケーター値をEAへ渡すとき、CopyBufferが呼べたことと、有効な値を取得できたことは同じではない。ハンドル作成直後や、時間足・シンボルを切り替えた直後、履歴データの読み込み中には、必要なバー数の計算がまだ終わっていないことがある。
この状態で戻り値を確認せずに配列を売買判定へ渡すと、古い値や未初期化値を使う可能性がある。EAの安定性を上げるには、シグナル計算の前に「データが準備済みか」を確認する層を設ける必要がある。
ハンドル生成と値取得を分離する
iMA、iRSI、iATR、iCustomなどはインジケーターそのものの値ではなく、インジケーターハンドルを返す。ハンドルは原則としてOnInitで一度生成し、INVALID_HANDLEでないことを確認する。
OnTickのたびに同じハンドルを作り直す設計は避けたい。計算準備が繰り返され、取得失敗の原因も追いにくくなる。
終了時にはIndicatorReleaseで解放する。生成、利用、解放というライフサイクルを明示しておけば、複数インジケーターを使うEAでも状態管理が分かりやすい。
BarsCalculatedで準備状態を確認する
BarsCalculatedは、指定したハンドルについて計算済みのバー数を返す。エラー時は-1となり、作成直後には必要なデータがまだ揃っていない場合がある。
例えば直近3本を取得したいなら、CopyBufferを呼ぶ前にBarsCalculated(handle)が少なくとも3以上あることを確認する。長い履歴を利用する処理なら、必要数に達するまでシグナル判定を行わない。
複数のインジケーターを組み合わせる場合は、一つだけ準備できていても不十分である。移動平均、ATR、RSIを使うなら、三つすべてが必要本数まで計算済みかを確認してから次へ進む。
CopyBufferの戻り値を必ず使う
CopyBufferは、実際にコピーできた要素数を返し、失敗時には負の値を返す。要求数と戻り値が一致しているかを確認することが基本になる。
直近2本を要求したなら、戻り値が2であることを確認してから配列を読む。1本しか取得できていない状態を成功扱いすると、前バーとの比較やクロス判定が成立しない。
失敗時はResetLastErrorとGetLastErrorを組み合わせ、ハンドル、buffer番号、要求件数、BarsCalculatedの値をログへ残す。単に失敗だけを記録するより再現しやすい。
buffer番号とバー位置を混同しない
CopyBufferではbuffer_numとstart_posを別々に指定する。buffer_numはインジケーター内部のバッファ番号であり、start_posは現在から何本前を読み始めるかを表す。
start_posの0は現在形成中のバーである。確定足だけで判定したいEAが0番を使うと、ティックごとに値が変化し、バックテストと実運用でシグナル数がずれることがある。
確定足ベースなら1番以降を使うなど、売買ルールと参照位置を明示する。カスタムインジケーターでは、どのbuffer番号に何が格納されているかも確認する必要がある。
配列の向きも仕様として固定する
CopyBufferは現在から過去へ指定できるが、受け取り配列の物理配置を直感だけで扱うとインデックスを取り違えやすい。ArraySetAsSeriesの有無と、どの要素を「最新値」と定義するかをEA内で統一する。
ある配列では0番が最新、別の配列では末尾が最新という状態は避けたい。
値取得関数を一つ用意し、「確定足の最新値を返す」「必要本数が揃わなければfalseを返す」といったインターフェースにすると、売買ロジック側からCopyBuffer固有の処理を切り離せる。
再取得は無限リトライにしない
履歴同期やインジケーター計算の遅延で一時的に値が取得できない場合、次のティックで再試行する設計は合理的である。一方、一つのOnTick内で取得成功まで無限に待つ設計は避けるべきである。
EAでは「今回は判定しない」という選択肢を持たせる。データ取得失敗時に注文を出さず、その理由をログへ残し、次回イベントで再確認する方が安全である。
検証時には、CopyBuffer失敗回数、発生時刻、対象シンボル、時間足を集計する。失敗率が起動直後などに集中するなら、売買ロジックではなくデータ準備工程の問題として切り分けられる。
まとめ
CopyBufferを安全に使うには、ハンドル生成、データ準備、取得、検証、売買判定を別工程として扱う必要がある。INVALID_HANDLE、BarsCalculated、CopyBufferの戻り値、エラーコードを順番に確認すれば、未準備のインジケーター値が注文ロジックへ混入する可能性を減らせる。
さらに、参照バー、buffer番号、配列方向を固定し、取得失敗時は注文を見送る。EAの性能はシグナル式だけでなく、入力データが正しく準備されたかを毎回確認できるかでも変わる。






