MQL5でインジケーター値をEAに取り込む方法|iMA・iATR・iRSI・CopyBufferの基本
MQL5でEAを開発する時、移動平均線、ATR、RSIなどのインジケーター値をEA側で取得して、シグナル判定やフィルターに使う場面があります。MT5では、インジケーター値を直接関数の戻り値として読むのではなく、インジケーターハンドルを作成し、CopyBufferでバッファ値を取得する構成が基本になります。
CopyBufferは、MQL5でEAからインジケーター値を取得する時に重要な関数です。ただし、ハンドル作成、BarsCalculated、取得本数、バッファ番号、shift、現在足と確定足、ArraySetAsSeries、EMPTY_VALUE、INVALID_HANDLEを理解していないと、値が取れていないのにシグナル判定へ進んでしまうことがあります。
この記事では、MQL5でEAにインジケーター値を取り込むために、iMA、iATR、iRSI、iCustom、CopyBuffer、BarsCalculated、IndicatorRelease、現在足と確定足、ArraySetAsSeries、カスタムインジケーター連携、ログ設計、バックテスト確認までを実務目線で整理します。
なお、この記事はMT5 / MQL5のEA開発、インジケーター値取得、CopyBuffer、ログ確認を目的とした技術記事です。特定の売買判断、利益、勝率、損失回避、推奨ロット、推奨銘柄を案内するものではありません。
- この記事で確認すること
- MQL5でEAにインジケーター値を取り込む基本
- インジケーターハンドルとは
- iMAで移動平均線の値を取得する
- iATRでATR値を取得する
- iRSIでRSI値を取得する
- CopyBufferの基本構造
- BarsCalculatedで計算済み本数を確認する
- 現在足と確定足を分けて扱う
- ArraySetAsSeriesと配列方向の注意
- EMPTY_VALUEと取得失敗を混同しない
- iCustomでカスタムインジケーター値を取得する
- カスタムインジケーター連携で確認すること
- IndicatorReleaseでハンドルを解放する
- MTFでインジケーター値を取得する時の注意
- マルチシンボルでインジケーター値を取得する時の注意
- CopyBuffer失敗時に確認すること
- バックテストでCopyBufferを確認する
- EAに取り込んだインジケーター値をどこで使うかを分ける
- 標準インジケーター別のEA取り込み方
- CopyBufferで取得できた値を使える値として扱う前の確認
- 現在足を使うEAと確定足を使うEAの違い
- iCustomでサイン系インジケーターをEA化する時の確認順序
- 値取得できているのにEAが動かない時の切り分け
- ATRをSL幅やトレーリングに使う時の注意点
- 通知・半裁量・完全自動で確認項目を変える
- 検証時に残すべき証跡
- CopyBufferのログ設計
- 開発依頼前に整理する情報
- CopyBuffer実務チェック表
- よくある質問
- 関連ページ
- まとめ
この記事で確認すること
- MQL5でEAにインジケーター値を取り込む基本
- インジケーターハンドルとは何か
- iMA、iATR、iRSIで標準インジケーターのハンドルを作る方法
- CopyBufferでバッファ値を取得する方法
- BarsCalculatedで計算済み本数を確認する方法
- INVALID_HANDLEとハンドル作成失敗の確認
- shift=0とshift=1、現在足と確定足の違い
- ArraySetAsSeriesによる配列方向の注意点
- EMPTY_VALUEと取得失敗を混同しない考え方
- iCustomでカスタムインジケーターをEAに取り込む時の注意点
- IndicatorReleaseでハンドルを解放する方法
- CopyBuffer失敗時のログ設計
- バックテストでインジケーター値を確認する方法
MQL5でEAにインジケーター値を取り込む基本
MQL5では、EAからインジケーター値を使いたい場合、まずインジケーターハンドルを作成します。ハンドルとは、MT5内部で作成されたインジケーター計算結果へアクセスするための識別子です。
たとえば、移動平均線ならiMA、ATRならiATR、RSIならiRSIでハンドルを作成します。その後、CopyBufferを使って、指定したバッファ番号、開始位置、取得本数に応じた値を配列へコピーします。
MQL4の感覚で「iMAを呼べば値が返る」と考えていると、MQL5では混乱しやすくなります。MQL5では、ハンドル作成と値取得を分けて考えることが重要です。
| 工程 | 内容 | 確認ポイント |
|---|---|---|
| ハンドル作成 | iMA、iATR、iRSI、iCustomなどでハンドルを作成します。 | INVALID_HANDLEでないか確認します。 |
| 計算状態確認 | BarsCalculatedで計算済み本数を確認します。 | 必要本数が揃っているか確認します。 |
| 値取得 | CopyBufferで値を配列へ取得します。 | 戻り値が要求本数と一致しているか確認します。 |
| 判定利用 | 取得した値をシグナルやフィルターに使います。 | 現在足か確定足かを明確にします。 |
| 終了処理 | IndicatorReleaseでハンドルを解放します。 | OnDeinitで後処理します。 |
インジケーターハンドルとは
インジケーターハンドルは、インジケーターの計算結果をEAから参照するための識別子です。MQL5では、標準インジケーターやカスタムインジケーターを使う時に、まずハンドルを作成します。
ハンドル作成に失敗すると、CopyBufferで値を取得することはできません。ハンドルがINVALID_HANDLEでないかをOnInitで確認し、失敗した場合は理由をログに出すことが重要です。
int ma_handle = INVALID_HANDLE;
int OnInit()
{
ma_handle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);
if(ma_handle == INVALID_HANDLE)
{
PrintFormat("HANDLE_FAIL name=iMA symbol=%s tf=%d last_error=%d",
_Symbol,
PERIOD_CURRENT,
GetLastError());
return INIT_FAILED;
}
PrintFormat("HANDLE_OK name=iMA handle=%d symbol=%s tf=%d",
ma_handle,
_Symbol,
PERIOD_CURRENT);
return INIT_SUCCEEDED;
}この例では、iMAで移動平均線のハンドルを作成し、INVALID_HANDLEかどうかを確認しています。ハンドル作成に失敗した状態でOnTickへ進むと、CopyBufferが失敗し続けるため、OnInitで止める設計が安全です。
iMAで移動平均線の値を取得する
iMAは、移動平均線のインジケーターハンドルを作成する関数です。EAでは、移動平均線の傾き、価格との位置関係、短期線と長期線のクロスなどを判定するために使うことがあります。
iMAで作成したハンドルから値を取得するにはCopyBufferを使います。移動平均線は通常バッファ0に値が入ります。現在足を使うか、確定足を使うかは、EAの仕様として明確にしてください。
bool GetMAValue(int handle, int shift, double &ma_value)
{
if(handle == INVALID_HANDLE)
{
Print("MA_VALUE_FAIL reason=INVALID_HANDLE");
return false;
}
double buffer[];
ArraySetAsSeries(buffer, true);
ResetLastError();
int copied = CopyBuffer(handle, 0, shift, 1, buffer);
if(copied != 1)
{
PrintFormat("COPYBUFFER_FAIL name=iMA shift=%d copied=%d last_error=%d",
shift,
copied,
GetLastError());
return false;
}
ma_value = buffer[0];
PrintFormat("COPYBUFFER_OK name=iMA shift=%d value=%.5f",
shift,
ma_value);
return true;
}この例では、指定shiftの移動平均線値を1本取得しています。shift=0なら現在足、shift=1なら1本前の確定足を参照する考え方になります。シグナル判定の再現性を重視する場合は、確定足を使う設計が一般的です。
iATRでATR値を取得する
iATRは、ATRのインジケーターハンドルを作成する関数です。ATRは、ボラティリティや値幅の確認に使われることがあります。EAでは、SL/TP幅、トレーリング幅、ボラティリティフィルターなどに使う場合があります。
ATRもCopyBufferで値を取得します。ATRが0に見える場合、値が本当に0なのか、CopyBufferに失敗しているのか、計算本数が不足しているのかを分けて確認してください。
int atr_handle = INVALID_HANDLE;
int OnInit()
{
atr_handle = iATR(_Symbol, PERIOD_CURRENT, 14);
if(atr_handle == INVALID_HANDLE)
{
PrintFormat("HANDLE_FAIL name=iATR last_error=%d", GetLastError());
return INIT_FAILED;
}
PrintFormat("HANDLE_OK name=iATR handle=%d", atr_handle);
return INIT_SUCCEEDED;
}
bool GetATRValue(int shift, double &atr_value)
{
double buffer[];
ArraySetAsSeries(buffer, true);
ResetLastError();
int copied = CopyBuffer(atr_handle, 0, shift, 1, buffer);
if(copied != 1)
{
PrintFormat("COPYBUFFER_FAIL name=iATR shift=%d copied=%d last_error=%d",
shift,
copied,
GetLastError());
return false;
}
atr_value = buffer[0];
PrintFormat("COPYBUFFER_OK name=iATR shift=%d value=%.5f",
shift,
atr_value);
return true;
}ATRをSL/TPやトレーリング幅に使う場合は、pointやdigits、銘柄仕様もあわせて確認する必要があります。ATR値をそのまま価格距離として使えるかどうかは、銘柄や仕様によって確認が必要です。
iRSIでRSI値を取得する
iRSIは、RSIのインジケーターハンドルを作成する関数です。EAでは、買われすぎ・売られすぎの確認、エントリーフィルター、逆張り条件、トレンド中の過熱確認などに使われることがあります。
RSIも、ハンドル作成後にCopyBufferで値を取得します。RSIは通常0〜100の範囲で表示されますが、値が取れていない場合に初期値や0.0を判定に使ってしまうと、誤判定につながります。
int rsi_handle = INVALID_HANDLE;
bool CreateRSIHandle()
{
rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE);
if(rsi_handle == INVALID_HANDLE)
{
PrintFormat("HANDLE_FAIL name=iRSI last_error=%d", GetLastError());
return false;
}
PrintFormat("HANDLE_OK name=iRSI handle=%d", rsi_handle);
return true;
}
bool GetRSIValue(int shift, double &rsi_value)
{
double buffer[];
ArraySetAsSeries(buffer, true);
ResetLastError();
int copied = CopyBuffer(rsi_handle, 0, shift, 1, buffer);
if(copied != 1)
{
PrintFormat("COPYBUFFER_FAIL name=iRSI shift=%d copied=%d last_error=%d",
shift,
copied,
GetLastError());
return false;
}
rsi_value = buffer[0];
PrintFormat("COPYBUFFER_OK name=iRSI shift=%d value=%.2f",
shift,
rsi_value);
return true;
}RSIを使う場合も、現在足か確定足かを明確にします。現在足のRSIは価格更新に応じて変化するため、シグナルが出たり消えたりすることがあります。確定足のRSIを使う場合は、shift=1を基準にすることが多くなります。
CopyBufferの基本構造
CopyBufferは、インジケーターハンドルから指定したバッファの値を取得する関数です。主に、ハンドル、バッファ番号、開始位置、取得本数、出力先配列を指定します。
CopyBufferを使う時は、戻り値を必ず確認します。戻り値は実際にコピーできた要素数です。要求本数を満たしていない場合は、値を使わずにログへ出して処理を止める方が安全です。
| 引数・要素 | 意味 | 確認ポイント |
|---|---|---|
| handle | インジケーターハンドル。 | INVALID_HANDLEでないか確認します。 |
| buffer number | 取得するバッファ番号。 | 標準インジなら0が多いですが、カスタムでは仕様確認が必要です。 |
| start position | 取得開始位置。 | shift=0かshift=1かを明確にします。 |
| count | 取得本数。 | 判定に必要な本数を指定します。 |
| buffer array | 値を受け取る配列。 | ArraySetAsSeriesの設定を確認します。 |
| return value | 実際に取得できた本数。 | 要求本数と一致しているか確認します。 |
bool CopyIndicatorValues(int handle, int buffer_index, int start_shift, int count, double &values[])
{
if(handle == INVALID_HANDLE)
{
Print("COPYBUFFER_FAIL reason=INVALID_HANDLE");
return false;
}
ArraySetAsSeries(values, true);
ResetLastError();
int copied = CopyBuffer(handle, buffer_index, start_shift, count, values);
if(copied != count)
{
PrintFormat("COPYBUFFER_FAIL buffer=%d start=%d count=%d copied=%d last_error=%d",
buffer_index,
start_shift,
count,
copied,
GetLastError());
return false;
}
PrintFormat("COPYBUFFER_OK buffer=%d start=%d count=%d value0=%.5f",
buffer_index,
start_shift,
count,
values[0]);
return true;
}この例では、CopyBufferの戻り値が要求本数と一致するかを確認しています。取得本数が不足した状態で配列を参照すると、誤判定や配列範囲エラーにつながる可能性があります。
BarsCalculatedで計算済み本数を確認する
BarsCalculatedは、インジケーターの計算済み本数を確認するために使います。ハンドルが作成できても、必要な本数がまだ計算されていない場合、CopyBufferで十分な値を取得できないことがあります。
EA起動直後、バックテスト開始直後、MTF、マルチシンボル、iCustom利用時などは、計算済み本数が不足することがあります。BarsCalculatedで必要本数に達しているか確認してからCopyBufferへ進むと、失敗原因を切り分けやすくなります。
bool IsIndicatorReady(int handle, int needed_bars)
{
if(handle == INVALID_HANDLE)
{
Print("INDICATOR_READY_FAIL reason=INVALID_HANDLE");
return false;
}
ResetLastError();
int calculated = BarsCalculated(handle);
if(calculated < needed_bars)
{
PrintFormat("INDICATOR_NOT_READY calculated=%d needed=%d last_error=%d",
calculated,
needed_bars,
GetLastError());
return false;
}
PrintFormat("INDICATOR_READY calculated=%d needed=%d",
calculated,
needed_bars);
return true;
}この例では、BarsCalculatedの値が必要本数を満たしているかを確認しています。計算済み本数が不足している場合は、シグナル判定へ進まず、ログを出して見送る方が安全です。
現在足と確定足を分けて扱う
インジケーター値をEAに取り込む時は、現在足と確定足を分けて扱う必要があります。現在足は価格更新に応じて値が変化します。確定足はすでに閉じた足なので、判定の再現性が高くなります。
CopyBufferでstart positionに0を指定すると、現在足の値を取得する構成になります。start positionに1を指定すると、1本前の確定足の値を取得する構成になります。どちらを使うかは、EAの仕様として明確にしてください。
| 指定 | 意味 | 注意点 |
|---|---|---|
| shift=0 | 現在足の値。 | 価格更新により変化します。 |
| shift=1 | 1本前の確定足の値。 | 判定の再現性を高めやすいです。 |
| 現在足判定 | 早い反応が可能。 | シグナルが出たり消えたりする場合があります。 |
| 確定足判定 | 値が確定してから判定。 | 反応は遅くなりますが、検証しやすくなります。 |
バックテストで再現性を重視する場合や、シグナルの出たり消えたりを避けたい場合は、確定足を使う設計が扱いやすいです。一方で、リアルタイム性を重視するEAでは現在足を使う場合もあります。その場合は、ログで値の変化を確認できるようにしてください。
ArraySetAsSeriesと配列方向の注意
CopyBufferで取得した値を配列で扱う時は、ArraySetAsSeriesの設定を確認します。ArraySetAsSeriesをtrueにすると、配列の0番目を最新側として扱いやすくなります。
配列方向を確認せずにbuffer[0]やbuffer[1]を使うと、現在足と確定足を取り違える可能性があります。特にCopyBuffer、CopyRates、CopyCloseを混在させるEAでは、配列方向を統一しておくと確認しやすくなります。
| 設定 | 意味 | 確認ポイント |
|---|---|---|
ArraySetAsSeries(buffer, true) | 0番目を最新側として扱います。 | buffer[0]が取得開始位置の値として扱いやすくなります。 |
ArraySetAsSeries(buffer, false) | 通常配列方向で扱います。 | インデックスの意味をログで確認します。 |
| buffer[0] | 配列方向とCopyBuffer指定により意味が変わります。 | 時刻やshiftとセットで確認します。 |
| buffer[1] | 2本以上取得した時に使います。 | クロス判定や前回値比較で注意します。 |
EMPTY_VALUEと取得失敗を混同しない
インジケーターによっては、値が存在しない場所にEMPTY_VALUEが入ることがあります。特に矢印系インジケーター、サイン系インジケーター、条件成立時だけ値を出すカスタムインジケーターでは、EMPTY_VALUEの確認が重要です。
CopyBufferの失敗とEMPTY_VALUEは別です。CopyBufferが成功していても、取得した値がEMPTY_VALUEの場合、そのバーではシグナルが出ていない可能性があります。一方で、CopyBuffer自体が失敗している場合は、インジケーター値を判定に使うべきではありません。
bool GetSignalValue(int handle, int buffer_index, int shift, double &signal_value)
{
double buffer[];
ArraySetAsSeries(buffer, true);
ResetLastError();
int copied = CopyBuffer(handle, buffer_index, shift, 1, buffer);
if(copied != 1)
{
PrintFormat("SIGNAL_COPY_FAIL buffer=%d shift=%d copied=%d last_error=%d",
buffer_index,
shift,
copied,
GetLastError());
return false;
}
if(buffer[0] == EMPTY_VALUE)
{
PrintFormat("SIGNAL_EMPTY buffer=%d shift=%d", buffer_index, shift);
return false;
}
signal_value = buffer[0];
PrintFormat("SIGNAL_VALUE buffer=%d shift=%d value=%.5f",
buffer_index,
shift,
signal_value);
return true;
}この例では、CopyBuffer失敗とEMPTY_VALUEを分けてログに出しています。サイン系インジケーターをEAへ取り込む場合は、この切り分けが非常に重要です。
iCustomでカスタムインジケーター値を取得する
iCustomは、カスタムインジケーターのハンドルを作成するために使います。EAから自作インジケーターや外部インジケーターの値を取得したい場合、iCustomでハンドルを作成し、CopyBufferでバッファ値を取得します。
iCustomを使う時は、インジケーターファイル名、input引数の順番、バッファ番号、サブウィンドウ、EMPTY_VALUE、再描画の有無を確認します。カスタムインジケーター側の仕様が分からないままEAへ取り込むと、値の意味を誤解する可能性があります。
int custom_handle = INVALID_HANDLE;
bool CreateCustomIndicatorHandle()
{
custom_handle = iCustom(_Symbol, PERIOD_CURRENT, "MyCustomIndicator", 14, 2.0);
if(custom_handle == INVALID_HANDLE)
{
PrintFormat("HANDLE_FAIL name=MyCustomIndicator last_error=%d",
GetLastError());
return false;
}
PrintFormat("HANDLE_OK name=MyCustomIndicator handle=%d",
custom_handle);
return true;
}この例では、MyCustomIndicatorというカスタムインジケーターをiCustomで呼び出しています。実際には、ファイル名、パス、input引数、バッファ番号が正しいかを確認してください。
カスタムインジケーター連携で確認すること
カスタムインジケーターをEAに取り込む場合は、標準インジケーターよりも確認項目が増えます。特に、どのバッファに何の値が入っているか、サインが出ない時にEMPTY_VALUEになるのか0になるのか、現在足で値が変わるのか、確定足で固定されるのかを確認します。
インジケーター側が描画用に作られている場合、EAから読み取る用途に適していないこともあります。バッファが公開されているか、CopyBufferで取得できるか、描画オブジェクトだけで値を出していないかを確認してください。
| 確認項目 | 内容 | 注意点 |
|---|---|---|
| ファイル名 | iCustomで指定するインジケーター名。 | 拡張子やフォルダ階層の扱いに注意します。 |
| input引数 | カスタムインジケーターの設定値。 | 順番や型が違うと期待値になりません。 |
| バッファ番号 | CopyBufferで指定する番号。 | 買いサイン・売りサインなどの対応を確認します。 |
| EMPTY_VALUE | 値なしの扱い。 | サインなしを注文条件と混同しないようにします。 |
| 現在足更新 | 現在足で値が変わるか。 | リペイントや再計算の有無を確認します。 |
| 確定足 | 確定足で値が固定されるか。 | バックテスト再現性に影響します。 |
| ログ | 値、shift、buffer、copied。 | EA側で取得状態を確認します。 |
IndicatorReleaseでハンドルを解放する
EA終了時には、作成したインジケーターハンドルをIndicatorReleaseで解放します。OnDeinitで後処理を行うことで、リソース管理が明確になります。
短いサンプルでは省略されることがありますが、複数インジケーター、MTF、マルチシンボル、iCustomを多用するEAでは、ハンドル管理を整理しておくと保守しやすくなります。
void OnDeinit(const int reason)
{
if(ma_handle != INVALID_HANDLE)
{
IndicatorRelease(ma_handle);
PrintFormat("HANDLE_RELEASE name=iMA handle=%d reason=%d",
ma_handle,
reason);
ma_handle = INVALID_HANDLE;
}
if(atr_handle != INVALID_HANDLE)
{
IndicatorRelease(atr_handle);
PrintFormat("HANDLE_RELEASE name=iATR handle=%d reason=%d",
atr_handle,
reason);
atr_handle = INVALID_HANDLE;
}
if(rsi_handle != INVALID_HANDLE)
{
IndicatorRelease(rsi_handle);
PrintFormat("HANDLE_RELEASE name=iRSI handle=%d reason=%d",
rsi_handle,
reason);
rsi_handle = INVALID_HANDLE;
}
}この例では、各ハンドルが有効な場合だけIndicatorReleaseを呼び出し、その後INVALID_HANDLEへ戻しています。ログにreasonを出しておくと、EA終了理由の確認にも役立ちます。
MTFでインジケーター値を取得する時の注意
MTFでは、現在チャートとは別の時間足のインジケーター値を取得します。たとえば、M5チャート上でEAを動かしながら、H1の移動平均線やRSIをフィルターに使うような構成です。
MTFで注意すべきなのは、現在チャートのバー更新と上位足のバー更新が一致しないことです。上位足のshift=0は形成中であり、値が変わります。上位足をフィルターに使う場合は、shift=1の確定足を使うか、現在足を使うかを仕様として明確にします。
int h1_ma_handle = INVALID_HANDLE;
bool CreateH1MAHandle()
{
h1_ma_handle = iMA(_Symbol, PERIOD_H1, 20, 0, MODE_SMA, PRICE_CLOSE);
if(h1_ma_handle == INVALID_HANDLE)
{
PrintFormat("HANDLE_FAIL name=H1_MA last_error=%d", GetLastError());
return false;
}
PrintFormat("HANDLE_OK name=H1_MA handle=%d", h1_ma_handle);
return true;
}上位足の値が取得できない場合は、時間足データ不足、バックテスト開始直後、BarsCalculated不足を確認します。MTFでは、CopyBuffer失敗をシグナル不成立と混同しないようにしてください。
マルチシンボルでインジケーター値を取得する時の注意
マルチシンボルEAでは、現在チャートとは別の銘柄のインジケーター値を取得することがあります。この場合、対象銘柄がMarket Watchに表示されているか、SymbolSelectで選択できているか、ヒストリーデータがあるかを確認する必要があります。
別銘柄のiMAやiRSIハンドルを作る場合は、_Symbolに固定せず、対象symbolを引数として渡す構成にします。銘柄ごとにハンドルを管理する必要があるため、単一ハンドルのEAよりも管理が複雑になります。
bool PrepareSymbol(string symbol)
{
ResetLastError();
if(!SymbolSelect(symbol, true))
{
PrintFormat("SYMBOL_SELECT_FAIL symbol=%s last_error=%d",
symbol,
GetLastError());
return false;
}
PrintFormat("SYMBOL_SELECT_OK symbol=%s", symbol);
return true;
}SymbolSelectに失敗した状態でインジケーターハンドルを作成すると、ハンドル作成やCopyBufferに失敗する可能性があります。マルチシンボルEAでは、対象銘柄ごとの準備ログを残してください。
CopyBuffer失敗時に確認すること
CopyBufferが失敗する場合は、ハンドル、バッファ番号、取得開始位置、取得本数、計算済み本数、配列方向、対象銘柄、対象時間足、GetLastErrorを確認します。値が取れない理由を1つに決めつけないことが重要です。
| 症状 | 確認する場所 | 主な原因候補 |
|---|---|---|
| copiedが要求本数より少ない | CopyBuffer戻り値、BarsCalculated。 | 計算本数不足、ヒストリー不足、起動直後。 |
| INVALID_HANDLEになる | iMA、iATR、iRSI、iCustomの戻り値。 | 引数不正、ファイル名違い、銘柄・時間足データ不足。 |
| 値が0.0に見える | CopyBuffer成功可否、値の意味。 | 取得失敗、値なし、初期値、実際に0。 |
| EMPTY_VALUEになる | 取得値、カスタムインジ仕様。 | サインなし、描画なし、条件不成立。 |
| MTFだけ失敗する | 上位足ハンドル、BarsCalculated。 | 上位足データ不足、バックテスト開始直後。 |
| 別銘柄だけ失敗する | SymbolSelect、銘柄名、Market Watch。 | 銘柄未選択、銘柄名違い、ヒストリー不足。 |
| バッファ番号が合わない | インジケーター仕様。 | 買いサイン・売りサインのバッファ番号違い。 |
バックテストでCopyBufferを確認する
バックテストでは、EAの損益結果だけでなく、インジケーター値が正しく取得できているかを確認します。特に、CopyBufferの取得本数、BarsCalculated、shift、現在足と確定足、MTF、iCustomのバッファ番号をログで確認してください。
バックテスト開始直後は、インジケーター計算に必要な本数が揃っていない場合があります。その状態でCopyBuffer結果を使ってしまうと、シグナル不成立や誤判定につながります。
- EA名とバージョンを記録する
- 使用したsetファイルを保存する
- 銘柄、時間足、期間を記録する
- インジケーターハンドル作成ログを確認する
- BarsCalculatedの値を確認する
- CopyBufferの戻り値を確認する
- 現在足と確定足を混同していないか確認する
- iCustom利用時はバッファ番号を確認する
- EMPTY_VALUEをシグナル不成立として扱うか確認する
- バックテスト結果を将来成績保証として扱わない
EAに取り込んだインジケーター値をどこで使うかを分ける
EAにインジケーター値を取り込む時は、値を取得できたかどうかだけでなく、その値をEA内部のどこで使うかを先に分ける必要があります。
同じMA値やRSI値でも、エントリー方向を決めるために使うのか、エントリーを見送るフィルターとして使うのか、決済条件として使うのか、通知やパネル表示だけに使うのかで、必要な確認内容が変わります。
たとえば、RSIが30未満になったことを通知するだけなら、値取得と通知重複防止が中心です。一方で、自動発注EAとして使う場合は、スプレッド、既存ポジション、Magic Number、証拠金、ロット、OrderCheck、取引時間、外部停止条件まで確認する必要があります。
| 責務 | インジケーター値の使い方 | 確認ポイント |
|---|---|---|
| signal | BUY / SELL / WAITの候補を作る | 値取得、shift、EMPTY_VALUE、判定方向を確認する |
| filter | エントリー許可・見送り条件に使う | トレンド方向、過熱感、ボラティリティ、時間帯と分ける |
| risk | SL幅、トレーリング幅、ロット補助に使う | ATR値、point、pips、銘柄仕様、証拠金を確認する |
| exit | 決済条件や撤退条件に使う | エントリー条件と決済条件を混同しない |
| notification | 通知だけに使う | 重複通知、通知対象足、通知タイミングを確認する |
| UI / panel | 画面表示や状態確認に使う | 取得失敗時の表示、更新頻度、表示値の説明を確認する |
EA設計では、インジケーター値を取得した時点で発注へ直結させないことが重要です。値取得、値の妥当性確認、signal判定、entry gate、risk確認、executionを分けることで、後からログを見た時にどの段階で止まったのかを確認できます。
この分離がないと、「CopyBufferは成功しているのにEAが入らない」という状態になった時、値が悪いのか、判定条件が悪いのか、発注前条件で止まったのか、注文処理で失敗したのかを切り分けできません。
標準インジケーター別のEA取り込み方
EAへ取り込む標準インジケーターは、それぞれ値の性質が異なります。すべてを同じ「数値」として扱うのではなく、値の単位、意味、使う責務を分けて確認してください。
| インジケーター | 値の性質 | EAでの主な使い方 | 注意点 |
|---|---|---|---|
| iMA | 価格に近いライン値 | 方向確認、クロス、価格との位置関係 | 価格とMAのshiftを合わせる |
| iRSI | 0〜100のオシレーター値 | 過熱感、押し目、逆張り候補の補助 | 価格やpipsとは単位が違う |
| iATR | 価格変動幅 | ボラティリティ確認、SL幅、トレーリング補助 | point、pips、価格単位への換算を確認する |
| iBands | 上限・中央・下限の価格値 | 価格位置、バンド内外、ボラティリティ確認 | buffer番号を必ず確認する |
| iMACD | MACD線やシグナル線など複数buffer | 方向、勢い、クロス補助 | どのbufferを読むか確認する |
| iStochastic | %K / %Dなどのオシレーター値 | 過熱感、クロス、レンジ補助 | 現在足の変動と確定足を分ける |
たとえば、ATRはエントリー方向を直接決めるインジケーターではありません。ATRが大きいからBUY、ATRが小さいからSELLという使い方ではなく、相場の値幅やボラティリティ環境を確認するために使う方が自然です。
一方で、MAは価格と同じような水準の値を返すため、価格との比較や短期線・長期線の比較に使いやすいです。ただし、現在足の終値と確定足のMAを比較するなど、参照足がズレると判定が不自然になります。
RSIやStochasticは、価格そのものではなく指標値です。0〜100の範囲で評価する値を、価格差やpipsと同じ単位で扱わないようにしてください。
CopyBufferで取得できた値を使える値として扱う前の確認
CopyBufferが成功したように見えても、その値をEA判定に使ってよいとは限りません。取得本数が足りているか、値がEMPTY_VALUEではないか、NaNではないか、意図したshiftの値か、buffer番号が正しいかを確認する必要があります。
| 状態 | 意味 | EA側の扱い |
|---|---|---|
| copiedが要求本数と一致 | CopyBufferの取得処理は成功 | 次に値の妥当性を確認する |
| copiedが0 | 取得できた値がない | BarsCalculated、履歴、buffer番号を確認する |
| copiedが-1 | CopyBuffer失敗 | GetLastErrorとhandle状態を確認する |
| EMPTY_VALUE | そのバーに値やサインがない可能性 | サインなしとして扱うか仕様で決める |
| 0.0 | 有効値の場合も初期値の場合もある | インジケーター仕様とログを照合する |
| 異常に大きい値 | EMPTY_VALUE相当や未初期化の可能性 | MathIsValidNumberなどで確認する |
| 想定と違う方向の値 | buffer番号違いの可能性 | SetIndexBufferやData Windowを確認する |
値取得の成功、値の有効性、signal成立は別の段階です。CopyBufferが成功しても、EMPTY_VALUEならサインなしの可能性があります。値が有効でも、EAのsignal条件を満たしていないならWAITです。
この段階を分けずに実装すると、正常なWAIT状態をエラー扱いしたり、取得失敗をシグナル不成立として見逃したりします。ログ上でも、COPYBUFFER_FAIL、VALUE_EMPTY、SIGNAL_WAIT、ENTRY_BLOCKを分けると確認しやすくなります。
現在足を使うEAと確定足を使うEAの違い
インジケーター値をEAへ取り込む時、現在足を使う設計と、確定足を使う設計では挙動が大きく変わります。
現在足は価格更新に応じて変化します。シグナルが早く出る一方で、同じバーの中で条件が成立したり不成立になったりすることがあります。確定足は反応が遅くなりますが、検証結果と実運用の照合がしやすくなります。
| 方式 | 特徴 | 向いている用途 | 注意点 |
|---|---|---|---|
| 現在足方式 | 価格更新中の値を使う | リアルタイム通知、早い反応を狙う判定 | サインが出たり消えたりする可能性がある |
| 確定足方式 | 1本前の確定した値を使う | バー確定型EA、再現性重視の検証 | 反応は現在足方式より遅くなる |
| 現在足通知+確定足発注 | 通知と発注で基準を分ける | 半裁量、確認用EA | ユーザーに基準差を明示する必要がある |
| 複数本確認方式 | 直近数本の値を比較する | クロス、傾き、連続条件 | 取得本数不足に注意する |
「チャートではサインが出ているのにEAが入らない」という相談では、現在足と確定足の違いが原因になっていることがあります。チャート上で見ているサインが現在足の変動中サインで、EAが確定足を見ている場合、見え方が違って当然です。
そのため、EA仕様書やinput説明では、判定basisを明記してください。たとえば、SignalShift=1なら確定足基準、SignalShift=0なら現在足基準というように、利用者が分かる形にしておくと問い合わせ対応もしやすくなります。
iCustomでサイン系インジケーターをEA化する時の確認順序
サイン系カスタムインジケーターをEA化する場合、標準インジケーターより確認項目が多くなります。
特に、買いサインと売りサインがどのbufferに入っているのか、サインがない時にEMPTY_VALUEを返すのか0を返すのか、現在足でサインが消えるのか、確定足で固定されるのかを確認する必要があります。
| 順番 | 確認項目 | 確認内容 |
|---|---|---|
| 1 | インジケーター名 | iCustomで指定するファイル名と配置場所を確認する |
| 2 | input引数 | インジ側inputの順序、型、初期値とEA側指定を照合する |
| 3 | handle作成 | INVALID_HANDLEでないか、GetLastErrorを確認する |
| 4 | buffer番号 | BUYサイン、SELLサイン、フィルター値のbufferを確認する |
| 5 | shift | 現在足で見るか、確定足で見るかを決める |
| 6 | EMPTY_VALUE | サインなしをどの値で表しているか確認する |
| 7 | リペイント | 未確定足や過去足の値が変わるか確認する |
| 8 | EA側signal化 | 値取得をBUY / SELL / WAITへ変換する |
カスタムインジケーターのソースコードがある場合は、SetIndexBuffer、OnCalculate、EMPTY_VALUEの入れ方を確認できます。ソースコードがない場合は、Data Window、チャート表示、CopyBufferログを使って推測することになります。
ex5のみのインジケーターをEA化する場合、内部bufferの意味が完全には分からないことがあります。この場合は、すぐに自動発注へつなげず、まず通知やログ出力でサイン検出の再現性を確認する方が安全です。
値取得できているのにEAが動かない時の切り分け
CopyBufferで値が取れているにもかかわらず、EAがエントリーしない場合があります。この場合、インジケーター値の取得は成功しているため、次にsignal判定、filter、entry gate、risk、executionを確認します。
| 段階 | 確認内容 | よくある停止理由 |
|---|---|---|
| value | CopyBufferで値が取得できているか | 取得失敗、EMPTY_VALUE、buffer番号違い |
| signal | 取得値からBUY / SELL / WAITへ変換できているか | 条件未達、現在足と確定足の違い |
| filter | 追加条件を通過しているか | MA方向、RSI範囲、ATR環境、時間帯 |
| entry gate | 発注前制限を通過しているか | スプレッド過大、既存ポジションあり、取引停止 |
| risk | ロットや証拠金条件が通っているか | 最小ロット未満、証拠金不足、StopLevel違反 |
| execution | 注文結果が成功しているか | OrderSend失敗、retcode異常、約定拒否 |
EAが動かない時に「インジケーター値が取れていない」と決めつけるのは危険です。実際には、インジケーター値は正常に取れているが、entry gateやrisk条件で止まっている場合があります。
そのため、ログでは、VALUE_OK、SIGNAL_EVAL、FILTER_BLOCK、ENTRY_BLOCK、RISK_BLOCK、ORDER_RESULT のように段階を分けると原因を追いやすくなります。
ATRをSL幅やトレーリングに使う時の注意点
ATRは、EAでSL幅、トレーリング幅、ボラティリティ判定に使われることがあります。ただし、ATR値をそのままpipsとして扱うと、銘柄や桁数によって誤った距離になる可能性があります。
| 確認項目 | 内容 | 注意点 |
|---|---|---|
| Digits | 銘柄の小数桁 | 5桁、3桁、2桁、XAUUSDなどで感覚が違う |
| Point | 最小価格単位 | pips換算と混同しない |
| ATR値 | 価格単位の変動幅 | そのままSL距離に使えるか確認する |
| StopLevel | 注文時の最小距離 | ATR由来のSL幅が近すぎる場合がある |
| Spread | 現在スプレッド | 低ATR環境ではスプレッド比率が大きくなる |
| 銘柄仕様 | 最小ロット、tick value、contract size | risk計算と組み合わせて確認する |
ATRを使う場合は、単に「ATRが大きいから広いSL」「ATRが小さいから狭いSL」とするだけでは不十分です。銘柄仕様、StopLevel、スプレッド、証拠金、ロット計算と合わせて確認する必要があります。
また、ATRは相場環境を示す値であり、売買方向そのものを決める値ではありません。EA内部では、signalではなく、risk補助、volatility filter、exit補助として扱う方が自然な場面が多くあります。
通知・半裁量・完全自動で確認項目を変える
同じインジケーター値取得でも、通知ツール、半裁量EA、完全自動EAでは、必要な確認項目が異なります。
通知ツールでは、値取得と重複通知防止が中心です。半裁量EAでは、サイン表示や手動実行ボタン、誤操作防止が重要です。完全自動EAでは、発注前のentry gate、risk、execution、注文結果確認まで必要になります。
| 用途 | インジケーター値の扱い | 追加確認 |
|---|---|---|
| 通知ツール | サイン検出や条件成立を通知する | 重複通知、通知先、通知文、ログ |
| 情報パネル | 現在値や状態を表示する | 更新頻度、取得失敗時の表示、色分け |
| 半裁量EA | サインを確認して手動操作する | ボタン、確認表示、誤操作防止 |
| 完全自動EA | signalから注文処理へ進める | entry gate、risk、OrderCheck、retcode確認 |
| 検証EA | 条件成立や値変化を記録する | CSVログ、検証期間、再現条件 |
インジケーター値を取得できるようになったからといって、すぐに完全自動発注へ接続する必要はありません。まず通知やログで検証し、サインの再現性、リペイント有無、確定足での残り方を確認してから、発注処理へ進める方が安全です。
EAファンクラブでは、インジケーター値取得を、通知、表示、判定、発注、決済、リスク管理へ分けて扱います。これにより、後から「通知だけ使う」「発注を止める」「ログ検証だけ行う」といった運用に切り替えやすくなります。
検証時に残すべき証跡
EAにインジケーター値を取り込む処理を検証する場合、単にバックテストを実行するだけでは不十分です。どの値を、どの足で、どのbufferから取得し、どの判定に使ったのかを確認できる証跡が必要です。
| 証跡 | 残す内容 | 目的 |
|---|---|---|
| setファイル | input設定、使用インジ、shift、期間 | 同じ条件を再現する |
| Expertsログ | handle、BarsCalculated、CopyBuffer、signal | 値取得から判定まで追跡する |
| バックテスト条件 | 銘柄、時間足、期間、モデル、スプレッド | 検証条件を明確にする |
| チャートスクリーンショット | サイン位置、インジ表示、EAログ | 表示と取得値を照合する |
| CSVログ | 時刻、値、signal、block reason | 大量データを後から分析する |
| バージョン情報 | EAバージョン、インジバージョン | 修正前後の差分を確認する |
不具合調査では、「動かない」という説明だけでは原因を特定できません。値取得に失敗しているのか、値は取れているがsignal条件を満たしていないのか、entry gateで止まっているのか、注文処理で失敗しているのかをログで分けてください。
特にCopyBuffer関連では、buffer、shift、copied、last_error、BarsCalculated、取得値、basisを同じ行に残すと、後から原因を確認しやすくなります。
CopyBufferのログ設計
CopyBufferを使うEAでは、ログ設計が重要です。EAが注文しない時、ロジック条件ではなく、インジケーター値が取得できていないことが原因の場合があります。
ログ名は、HANDLE_OK、HANDLE_FAIL、INDICATOR_READY、INDICATOR_NOT_READY、COPYBUFFER_OK、COPYBUFFER_FAIL、SIGNAL_EMPTYのように分けると検索しやすくなります。
| ログ名 | 残す内容 | 目的 |
|---|---|---|
HANDLE_OK | インジケーター名、handle、symbol、timeframe。 | ハンドル作成成功を確認します。 |
HANDLE_FAIL | インジケーター名、GetLastError。 | ハンドル作成失敗を確認します。 |
INDICATOR_READY | BarsCalculated、必要本数。 | 計算済み本数を確認します。 |
INDICATOR_NOT_READY | 計算済み本数不足。 | 起動直後やデータ不足を確認します。 |
COPYBUFFER_OK | buffer、shift、count、value。 | 値取得成功を確認します。 |
COPYBUFFER_FAIL | buffer、shift、要求本数、取得本数、GetLastError。 | 値取得失敗を確認します。 |
SIGNAL_EMPTY | EMPTY_VALUE、buffer、shift。 | サインなしと取得失敗を分けます。 |
開発依頼前に整理する情報
EAにインジケーター値を取り込みたい場合や、CopyBufferが失敗する不具合を相談する場合は、対象EA、対象インジケーター、setファイル、銘柄、時間足、ハンドル作成ログ、CopyBufferログ、バッファ番号、shift指定を整理してください。
特にカスタムインジケーターをEAに取り込む場合は、インジケーター側のバッファ仕様が重要です。買いサイン、売りサイン、ライン、フィルター値がどのバッファに入っているのか、値なしがEMPTY_VALUEなのか0なのかを確認してください。
| 整理する情報 | 内容 | 理由 |
|---|---|---|
| EA名・バージョン | 対象ファイル名、更新日、バージョン。 | 確認対象を特定するため。 |
| インジケーター名 | iMA、iATR、iRSI、iCustom対象。 | 取得対象を明確にするため。 |
| setファイル | input設定一式。 | 同じ条件を再現するため。 |
| 銘柄・時間足 | _Symbol、参照時間足、MTF。 | ハンドル作成条件に関係するため。 |
| バッファ番号 | CopyBufferで指定する番号。 | 取得する値を特定するため。 |
| shift | 現在足か確定足か。 | 判定再現性に関係するため。 |
| ログ | HANDLE、BarsCalculated、CopyBuffer。 | 取得失敗の切り分けに必要です。 |
| 送らない情報 | 口座番号、パスワード、APIキー、Webhook URL。 | 機密情報を保護するため。 |
CopyBuffer実務チェック表
- OnInitでインジケーターハンドルを作成している
- INVALID_HANDLEを確認している
- ハンドル作成失敗時にログを出している
- BarsCalculatedで計算済み本数を確認している
- CopyBufferの戻り値を確認している
- 要求本数に満たない場合は判定へ進んでいない
- shift=0とshift=1の意味を明確にしている
- 現在足と確定足を混同していない
- ArraySetAsSeriesの配列方向を確認している
- EMPTY_VALUEとCopyBuffer失敗を分けている
- iCustom利用時にバッファ番号を確認している
- OnDeinitでIndicatorReleaseを行っている
- バックテスト条件とsetファイルを保存している
- 口座情報や認証情報をログへ出していない
よくある質問
MQL5でiMAを呼べば移動平均線の値が直接返りますか?
MQL5では、iMAは基本的にインジケーターハンドルを返します。移動平均線の値を取得するには、そのハンドルを使ってCopyBufferでバッファ値を取得します。
CopyBufferの戻り値は何を意味しますか?
CopyBufferの戻り値は、実際にコピーできた要素数です。要求本数と一致していない場合は、取得不足として扱い、ログを出して判定を止める方が安全です。
shift=0とshift=1はどちらを使えばよいですか?
shift=0は現在足、shift=1は1本前の確定足として扱うことが多いです。現在足は値が変化するため、再現性を重視する場合は確定足を使う設計が扱いやすいです。
BarsCalculatedは必ず確認すべきですか?
確認した方が安全です。ハンドルが有効でも、インジケーターの計算本数が不足していると、CopyBufferで必要本数を取得できないことがあります。
iCustomで値が取れない時は何を確認しますか?
インジケーター名、ファイルパス、input引数、バッファ番号、EMPTY_VALUE、ハンドル作成結果、BarsCalculated、CopyBufferの戻り値を確認します。カスタムインジケーター側の仕様確認も必要です。
CopyBufferで0.0が返った場合は取得成功ですか?
0.0が有効な値である場合もありますが、取得失敗や初期値の可能性もあります。CopyBufferの戻り値、GetLastError、BarsCalculated、EMPTY_VALUEを確認し、値の意味を分けて判断してください。
関連ページ
インジケーター値をEAに取り込む時は、時系列データ、インジケーター開発、マルチシンボル、ログ確認、EA設計、バックテストもあわせて確認すると、CopyBuffer失敗やシグナル不成立の原因を切り分けやすくなります。
| 確認したい内容 | 関連ページ |
|---|---|
| 時系列データと価格取得を確認する | MQL5時系列データ・価格取得完全ガイド |
| インジケーター開発とEA連携を確認する | MQL5インジケーター開発・EA連携完全ガイド |
| マルチシンボル・MTF対応を確認する | MQL5マルチシンボル・マルチタイムフレーム完全ガイド |
| MQL5関数全体を確認する | MQL5関数辞典 |
| 時系列・価格取得関数を確認する | MQL5時系列・価格取得関数辞典 |
| MT5インジケーターを確認する | MT5インジケーター辞典 |
| ログ確認とデバッグを確認する | MQL5デバッグ・ログファースト開発完全ガイド |
| EA設計の責務分離を確認する | MQL5 EA設計パターン完全ガイド |
| バックテストと最適化を確認する | MT5ストラテジーテスター・最適化完全ガイド |
| 注文・ポジション・履歴管理を確認する | MQL5注文・ポジション・履歴管理完全ガイド |
| ロット・証拠金・銘柄仕様を確認する | MQL5ロット・証拠金・銘柄仕様完全ガイド |
| CSVログ出力を確認する | MQL5ファイル操作・CSVログ出力完全ガイド |
| EAログを問い合わせ前に確認する | EAのログを問い合わせ前に確認する方法 |
| 開発・改修相談の入口を確認する | 開発・改修の相談ページ |
まとめ
MQL5でEAにインジケーター値を取り込む時は、iMA、iATR、iRSI、iCustomでハンドルを作成し、CopyBufferで値を取得します。ハンドル作成と値取得は別の工程として考え、INVALID_HANDLE、BarsCalculated、CopyBufferの戻り値を必ず確認してください。
CopyBufferでは、バッファ番号、shift、取得本数、配列方向、EMPTY_VALUEを確認することが重要です。現在足と確定足を混同すると、シグナルが出たり消えたりすることがあります。再現性を重視する場合は、確定足を使う設計が扱いやすいです。
カスタムインジケーターをiCustomでEAに取り込む場合は、ファイル名、input引数、バッファ番号、値なしの扱いを確認してください。バックテストや不具合調査では、ハンドル作成ログ、BarsCalculated、CopyBufferの戻り値、取得値、setファイル、検証条件を整理して確認することが重要です。
