iCustomの使い方とFX自動売買で指標の値を照合する手順

iCustomの使い方は、指標の名前だけを指定して終わりではありません。MQL4では、銘柄・時間足・ファイル名・入力値・バッファ番号・参照する足をそろえて、カスタムインジケーターの数値を読みます。FX自動売買の条件に使う前に、その数値がチャート上の同じ足の値と対応するかを確かめましょう。この記事ではMT4を対象に、引数の確認から発注しない照合例まで説明します。MT5のハンドルを使う方式とは区別して進めます。
- 名前と相対パスを実際の指標ファイルに合わせる方法
- 入力値の順序・型とmode・shiftの読み分け
- 注文を出さず同じ足の表示値と照合する手順
- 0・空値・取得エラーを混同しない確認方法
iCustomの使い方とFX自動売買の引数確認

MQL4とMQL5の違いを押さえる
MT4のMQL4では、iCustomの戻り値はdouble型の数値です。呼び出しの末尾で指定したバッファと足から、一つの値を受け取る形になります。まずは「どの指標の、どの設定の、どの列の、どの足か」を一組で決めると、長い引数も整理しやすくなります。
double value = iCustom(symbol, timeframe, name, 入力値の並び, mode, shift);
これは引数の位置を示す説明用の書式で、そのままコンパイルするコードではありません。nameまでの三つの引数と、末尾のmode・shift、その間にある指標固有の入力値を分けて読みます。詳しい定義はMQL4のiCustom公式リファレンスで確認できます。
一方、MT5のMQL5では、iCustomで受け取るものは指標のハンドルです。そのハンドルを使い、CopyBufferで必要なバッファのデータを取得します。MQL4の末尾にあるmode・shiftを、そのままMQL5のiCustomへ付け足す方法ではありません。MQL5のiCustomとCopyBufferの公式説明は別の仕様として読みましょう。
検索で見つかったコードを流用する場合も、先に言語と拡張子を確かめます。MQL4の数値をハンドルとして扱う、またはMQL5のハンドルを指標の価格として比較すると、処理の意味が変わります。この記事の照合例はMQL4用です。
名前と相対パスを合わせる

nameには、MT4のMQL4/Indicatorsを基準にした指標の名前を指定します。ソースのmq4があるだけでなく、コンパイル済みのex4が必要です。チャートで見える短い表示名と、実際のファイル名が違うこともあるため、タイトル欄だけから推測しないようにします。
たとえばIndicators直下のSampleLine.ex4なら、呼び出しで使う名前の例は"SampleLine"です。Studyというサブフォルダにあるなら、MQL4のコード内では"Study\\SampleLine"と書きます。文字列リテラルの中では、区切りのバックスラッシュを二つ続ける点が間違いやすいところです。
この例のSampleLineは説明用の仮名で、配布している製品ではありません。自分の環境の実ファイル名に置き換えてください。ファイル管理画面で拡張子を非表示にしていると、名前の末尾へ拡張子を重ねて付けるなどの取り違えが起こるため、実体まで確かめると安心です。
MT4を複数インストールしている場合は、今使う端末のデータフォルダを開いて確認します。別の端末に同名ファイルがあっても、今回の参照先が正しい証拠にはなりません。同じ名前の旧版と新版が混在していれば、比較する指標のバージョンもそろえます。
まだ指標をチャートへ表示できていない場合は、MT4のインジケーターの入れ方と導入後の確認を先に済ませてください。ここでは導入済みの指標から、意図した数値を読む工程に絞ります。
入力値は宣言順と型で渡す

指標名の後ろには、その指標が受け取る入力値を並べます。期間だけを変える指標もあれば、倍率、価格の種類、時間足、表示の切替などを受け取る指標もあります。呼び出す側の都合で順番を変えず、指標側のinputやexternの宣言順と型に合わせる必要があります。
例として、指標側に次の三つの入力がこの順で定義されているとします。期間は整数、倍率は小数を扱う数値、終値を使うかどうかは真偽値です。この三つは仮の仕様であり、すべてのインジケーターに共通する引数ではありません。
input int PeriodLength = 14;
input double Scale = 1.5;
input bool UseClose = true;
この仕様なら、指標名の後ろの入力部分は14, 1.5, trueという対応です。trueを文字列の"true"へ変えたり、ScaleとPeriodLengthを入れ替えたりしません。整数へ小数を渡して意図せず値を変えるなど、型の変換に頼る書き方も避けます。
入力を省略した場合は、指標で宣言された既定値が使われます。途中の項目だけを空欄にして、後ろの値を飛び越して指定する書き方にはしません。最初の照合では必要な入力をすべて明示しておくと、どの設定で計算したかを追いやすいです。順序と不足時の扱いは入力変数の公式説明に記載されています。
チャートへ手動で入れた指標の設定を変更しても、その変更値がiCustomの引数へ自動で引き継がれるとは考えません。表示用と読み取り用の両方で値をそろえます。また、入力画面の分かりやすい説明名とソース上の変数名が異なることもあるため、市販品などソースがなければ提供元の入力仕様を確認しましょう。
modeはバッファ番号を指定する

modeは、取得したい指標バッファの番号です。バッファは、指標が足ごとの計算値を用意する配列と考えると分かりやすいです。「0なら買い、1なら売り」という共通ルールはありません。中心線、上側の線、下側の線、買い矢印など、番号に対応する内容は指標ごとに異なります。
ソースがある場合は、SetIndexBufferでどの番号にどの配列を結び付けているかを調べます。たとえばSetIndexBuffer(0, MainBuffer)なら、0番にMainBufferを対応付けています。ただし、配列名だけで用途を断定せず、値を書き込む計算部分と表示の設定も確認します。SetIndexBufferの公式説明では、番号が0から始まることも示されています。
数値の意味と単位も重要です。矢印の位置を示す価格が入る場合と、方向を表す符号が入る場合では、買い条件の書き方が違います。値が正なら買い、値が0以外なら売買あり、と一律に判定することはできません。買い・売り・サインなしのそれぞれで何が入るかを、仕様として確かめます。
また、見える矢印が必ずバッファとして用意されているとは限りません。MQL4にはOBJ_ARROWという図形オブジェクトもあります。オブジェクトだけで描画し、対応する値を指標バッファへ出していない実装なら、iCustomのmodeを変えるだけではその矢印を読めません。提供元がバッファ連携に対応しているか確認してください。
shiftは読む足の位置を指定する
shiftは、現在から何本前の足の値を読むかを指定します。0は形成途中の現在足、1はその一つ前の足、2はさらに一つ前の足です。同じmodeでもshiftが違えば別の足を読んでいるため、表示との照合では両方を固定します。入力パラメーターにもShiftという項目があっても、iCustom末尾のshiftとは別の指定です。
銘柄を現在のチャートに合わせるならNULLまたは適切な現在銘柄の指定を使い、時間足を合わせるなら0を使えます。ただし、照合中にチャートの銘柄や時間足を変更すると参照条件も変わります。別の銘柄を文字列で指定するなら、接尾辞を含め、その端末で扱う正確な銘柄名が必要です。
まずは同じチャートの一つ前の足を読むと、足の途中の値動きによる比較の難しさを減らせます。ただし、shift=1にしただけで指標の過去値が将来も固定されるわけではありません。リペイントの判定は今回の引数確認とは分け、値の対応が確認できてから調べます。
iCustomの使い方を同じ足の値で確かめる

表示側と読み取り側の条件をそろえる
照合の出発点は、値を出す側と読む側の条件を一致させることです。画面の見た目が似ているだけでは、同じ計算結果とは限りません。最初は一つの銘柄・時間足・指標・バッファに絞り、複数指標や売買条件の組合せを追加する前に、一件ずつ対応を確認します。
| 確認するもの | 表示側 | iCustom側 |
|---|---|---|
| 指標の実体 | 使っているファイルと版 | nameが指すファイルと版 |
| 計算条件 | 銘柄・時間足・入力設定 | symbol・timeframe・入力値 |
| 取得する系列 | 対応する線や矢印の意味 | modeと値の単位 |
| 対象の足 | 足の開始時刻 | shiftとiTimeの開始時刻 |
| 比較する値 | 対象系列の表示数値 | 返された生の数値と空値仕様 |
チャートでは対象足の時刻と、該当する系列の数値を確認します。線の高さや矢印の位置を目測するだけで一致としないようにします。データウィンドウに表示される値があれば補助に使えますが、そこに出るラベルの順番だけでmodeを確定せず、仕様やソースとの対応を確かめてください。
足の開始時刻はiTimeで確認できます。iTimeの公式説明では、対象の銘柄・時間足・shiftの時刻を返し、履歴が読み込まれていない場合は0になるとされています。時刻が得られない状態で、近くに見える別の足を代用して一致を判断しないことが大切です。
照合をやり直すまでに新しい足ができると、同じshift=1でも対象は別の足に移ります。結果には足の時刻を添え、再確認時もその時刻の足を見ます。指標の値とチャート表示を別々の時点で読んだ場合は、その差だけで設定ミスと決めつけず、読み取り時点も合わせて確認しましょう。
発注しない読み取り例で確かめる

次は、Study/SampleLine.ex4という仮の指標を読む観察用スクリプト例です。入力が前述の整数・小数・真偽値の三つで、0番バッファに確認対象の値がある、という仮定です。実ファイルと仕様がなければ使えません。名前だけを別の指標へ変更しても、入力とバッファの対応が違えば正しい読み取りにはなりません。
このコードは解説用で、ここではMetaEditorでのコンパイルやMT4での実行を確認していません。手元の指標仕様に合わせて修正し、コンパイル結果を確認してから、発注しない検証用の環境で確かめてください。注文関数を含まない例ですが、呼び出される指標自体の仕様や外部依存は別途確認が必要です。
#property strict
void OnStart()
{
string symbol = Symbol();
int timeframe = Period();
int mode = 0;
int shift = 1;
ResetLastError();
datetime barTime = iTime(symbol, timeframe, shift);
int timeError = GetLastError();
if(barTime == 0 || timeError != 0)
{
Print("Bar time unavailable. error=", timeError);
return;
}
ResetLastError();
double value = iCustom(symbol, timeframe,
"Study\\SampleLine",
14, 1.5, true, mode, shift);
int readError = GetLastError();
if(readError != 0)
{
Print("Read check required. error=", readError);
return;
}
ResetLastError();
datetime barTimeAfter = iTime(symbol, timeframe, shift);
int afterError = GetLastError();
if(afterError != 0 || barTimeAfter != barTime)
{
Print("Bar changed or time unavailable. Retry check.");
return;
}
Print("symbol=", symbol, " timeframe=", timeframe,
" mode=", mode, " shift=", shift,
" bar=", TimeToString(barTime, TIME_DATE|TIME_MINUTES),
" raw=", DoubleToString(value, 12),
" default_empty=", (value == EMPTY_VALUE));
}
出力のbarが照合する足、rawが読み取った値です。取得前後に足の時刻を比べているのは、処理の途中で新しい足へ切り替わった結果を見落としにくくするためです。時刻が変わった行は今回の比較に採用せず、条件を確認してやり直します。これは指標の再計算を完全に防ぐ仕組みではありません。
default_emptyは標準のEMPTY_VALUEと同じかを出しているだけです。対象指標の空値仕様が違う場合、この判定だけではサインなしを分類できません。また、rawの小数点以下12桁は比較用の表示設定で、指標の精度を保証する数字ではありません。出力形式の仕様はDoubleToStringの公式説明を参照できます。
0と空値と取得エラーを切り分ける

取得値が0でも、それだけで呼び出し失敗とは判断できません。0が正常な計算結果の指標もあれば、サインなしを0で表す指標もあります。反対に、大きな数値が出た場合も、そのまま価格として売買条件へ渡さず、EMPTY_VALUEなどの空値に該当しないか確認します。
MQL4のSetIndexEmptyValueの公式説明では、標準の空値はEMPTY_VALUEで、別の値へ変更できるとされています。空値は描画やデータウィンドウに表示されません。したがって、表示欄が空でも、取得した数値が常に0になるとは限りません。どの番号で何を空値として使うかを確認しましょう。
エラー確認では、呼び出す直前にResetLastErrorで以前のエラー状態を消し、呼び出した直後にGetLastErrorを一度読み、変数に保存します。GetLastErrorを呼ぶと内部のエラー値がリセットされるため、後で再度呼んだ値を今回のエラーとして説明しないようにします。
エラー番号が0であることと、選んだバッファが目的の系列であることは別の確認です。間違った入力やmodeでも数値らしい結果が出る可能性があるため、最終的には同じ条件の表示値と照合します。反対にエラーが出ている行は、買い・売り・サインなしの判断材料へ進めず、原因を調べる対象とします。
| 観察結果 | 最初に確かめること | この時点の扱い |
|---|---|---|
| 0が返った | 正常値か、仕様で定めた空値か | 0だけで失敗としない |
| EMPTY_VALUEが返った | そのバッファの空値定義 | 価格や売買方向に使わない |
| エラー番号が残った | 名前・入力・履歴・指標側の状態 | 照合の採用を保留する |
| 数値はあるが表示と違う | 系列・足時刻・設定・単位 | 条件差を一つずつ調べる |
値が合わないときの確認順を決める
不一致が出たら、まず銘柄と時間足、それから足の開始時刻を確認します。次に、ファイルの版、入力の順序と型、modeの対応を見直します。いくつも同時に変えると、合った理由が分からなくなるため、一つの条件だけ直して同じ手順を繰り返します。
たとえば表示側の期間が20、呼び出し側が14なら、値が違うことは不自然ではありません。modeを片端から変えて近い数値を探す前に、入力をそろえる方が原因を絞れます。小数の末尾だけ違う場合も、表示桁数の丸めと生の値を区別し、価格・比率など指標の単位に合わせて比較します。
線を横へずらして描く指標にも注意します。SetIndexShiftの公式説明にあるように、計算した足に対して描画位置を左右へ移すことができます。その場合は、線が見える位置と、バッファ値が対応する計算元の足が同じとは限りません。単純にカーソル位置の足とshiftを合わせず、描画のずれを仕様で確認します。
ソースがない場合は、提供元へ「入力の宣言順と型」「読み取れるバッファ番号と意味」「サインなしの値」「描画位置のずれ」を具体的に質問します。一度だけ似た値が出たことは仕様の代わりになりません。複数の足で線の変化や、矢印あり・なしの状態を照合し、説明できない箇所は未確認のまま分けておきます。
同じ足と条件で値が対応してから、時間経過によるサインの変化を確認します。過去値が書き変わるかの記録方法は、EAのリペイントを見分けるシグナル検証で扱っています。値の取得確認と、過去シグナルの安定性の確認を一度に済ませたことにはしないようにしましょう。
iCustomの使い方を確認して次へ進む

読み取りを確認したと言えるのは、数値が一つ表示されたときではなく、どの条件のどの足を読んだか説明できたときです。次の項目がそろえば、その指標を売買条件へ組み込むための前提を整理できます。未確認の項目が残る場合は、その部分を先に提供元の仕様と照合してください。
- 指標の実ファイルと版、名前の相対パスが一致している
- 入力値の順序と型をそろえ、省略時の既定値も把握している
- modeに対応する系列、値の単位、空値が分かっている
- 同じ銘柄・時間足・開始時刻の足で数値を照合している
- 取得エラーとサインなしを別々に扱っている
iCustomはカスタム指標の数値を読むための入口です。任意の矢印を自動でEA化する機能ではなく、バッファがない描画や未公開の仕様にまで共通の読み方を用意するものではありません。今回の照合ができた後も、売買条件の定義、重複注文を防ぐ処理、資金管理、検証は別の工程です。
まずは発注しない状態で、一つのバッファと一つの足の時刻を決めてください。その表示値と取得値が一致する理由を確認できれば、設定の取り違えと指標自身の仕様を分けて、次の検証へ進みやすくなります。
