「直近20本の中で一番高い値段を知りたい」と思って`iHighest()`を使ってみたら、
返ってきた数値が価格として見るとおかしい(1や5のような小さい整数しか出てこない)——という戸惑いはないでしょうか。
実は`iHighest()`・`iLowest()`が返すのは価格そのものではなく、
「その最高値・最安値がついた足が、何本前にあるか」を表すインデックス(シフト)です。
実際の価格を知るには、このインデックスをもう一度`iHigh()`・`iLow()`に渡す、
という2段階の手順が必要になります。
この記事では、`iHighest()`・`iLowest()`の戻り値がインデックスである理由と、
実際の価格を取り出す手順、そして`hl-line.md`(前日の高値・安値表示)では扱わなかった「直近N本」
という任意の期間内で高値・安値を探す方法を、実際に動くコードで解説します。
iHighest・iLowestの書式
int iHighest( string symbol, //通貨ペア(NULLで現在の通貨ペア) int timeframe, //時間足(0で現在の時間足) int type, //探す対象(MODE_HIGH=高値、MODE_LOW=安値、MODE_CLOSEなど) int count=WHOLE_ARRAY, //何本前まで遡って探すか(既定値は全履歴) int start=0 //探索を始める足(0=最新の確定していない足を含む) ); int iLowest( string symbol, int timeframe, int type, int count=WHOLE_ARRAY, int start=0 );
`type`には価格の種類を指定します。
高値を探すのが目的でも、`MODE_HIGH`以外に`MODE_CLOSE`(終値ベースで最大値を探す)なども指定でき、
「ヒゲを含めた高値」と「実体(終値)ベースの高値」のどちらを探すかを使い分けられます。
戻り値は「価格」ではなく「インデックス」
`iHighest()`・`iLowest()`の戻り値は、
`count`本の範囲の中で最も条件に合う値を持つ足の、`start`からの相対的なインデックス(シフト)です。
価格そのものではありません。
//誤解: これで「直近20本の最高値」が取れると思ってしまう
int highestValue = iHighest(Symbol(), 0, MODE_HIGH, 20, 0);
Print("最高値=", highestValue); //実際には「0〜19本」のインデックス(例: 3)が出るだけ
実際の高値を得るには、返ってきたインデックスをもう一度`iHigh()`に渡す必要があります。
//正しい: インデックスを使ってiHigh()で実際の価格を取得する
int shift = iHighest(Symbol(), 0, MODE_HIGH, 20, 0);
double highestPrice = iHigh(Symbol(), 0, shift);
Print("直近20本の最高値=", highestPrice, "(", shift, "本前)");
`iLowest()`も同様に、返ってきたインデックスを`iLow()`に渡して初めて実際の安値が得られます。
hl-line.mdとの違い: 「前日」固定ではなく「直近N本」を自由に探せる
既存記事の前日の高値・安値を表示するインジケーターは、`iHigh(Symbol(), PERIOD_D1, 1)`のように「1日足の1本前(=前日)」
というインデックスをあらかじめ固定して高値・安値を取得していました。
これは「探す」のではなく「決まった位置の値をそのまま読む」処理です。
一方`iHighest()`・`iLowest()`は、`count`で指定した本数の範囲全体を検索し、
条件に合う足を「探し出す」処理です。
「直近5本の中で一番高い値」
「直近100本の中で一番安い値」のように、範囲を自由に変えられる点が、
固定インデックスを読むだけのhl-line.mdとの違いです。
直近スイング高値・安値を使ったブレイクアウト判定や、トレーリングストップの基準値を作る場面でよく使われます。
実際に動くコード全体
直近N本(input変数で指定)の中の最高値・最安値と、それぞれ何本前かを表示する、
実際にMetaEditorでコンパイルできるスクリプトです。
//+------------------------------------------------------------------+
//| HighestLowestDemo.mq4 |
//| Copyright 2026, FX-EA System Project Creator |
//| https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, FX-EA System Project Creator"
#property link "https://creator.fx-ea-system-project.com/"
#property version "1.00"
#property strict
#property script_show_inputs
input int RangeBars = 20;//直近何本の中から探すか
void OnStart()
{
if(RangeBars <= 0)
{
Print("RangeBarsは1以上を指定してください。");
return;
}
//直近RangeBars本の中で最も高い足のインデックスを探す(start=0なので最新足も含む)
int highestShift = iHighest(Symbol(), 0, MODE_HIGH, RangeBars, 0);
//直近RangeBars本の中で最も安い足のインデックスを探す
int lowestShift = iLowest(Symbol(), 0, MODE_LOW, RangeBars, 0);
if(highestShift < 0 || lowestShift < 0)
{
Print("iHighest/iLowestが失敗しました。エラーコード=", GetLastError());
return;
}
//インデックスをiHigh()/iLow()に渡して実際の価格を取得する
double highestPrice = iHigh(Symbol(), 0, highestShift);
double lowestPrice = iLow(Symbol(), 0, lowestShift);
PrintFormat("直近%d本: 最高値=%.5f(%d本前) / 最安値=%.5f(%d本前) / 値幅=%.5f",
RangeBars, highestPrice, highestShift,
lowestPrice, lowestShift,
highestPrice - lowestPrice);
}
//+------------------------------------------------------------------+
MetaEditorで実際に動かす手順
- MT4のMetaEditorで「ファイル」→「新規作成」→「スクリプト」を選び、名前を「HighestLowestDemo」にして作成する
- テンプレートの中身を全て削除し、上のコードを丸ごと貼り付ける
- F7キーでコンパイルし、「0 error(s), 0 warning(s)」になることを確認する
- 任意のチャートへドラッグ&ドロップし、RangeBarsの値を入力欄で確認・変更して実行する
- 「エキスパート」タブに最高値・最安値と、それぞれ何本前かが表示されることを確認する
コピペしてコンパイルが通らない・値がおかしいときに確認すること
- `iHighest()`・`iLowest()`の戻り値をそのまま価格として使っていないか(必ず`iHigh()`・`iLow()`へインデックスとして渡す)
- `count`(この記事の`RangeBars`)を大きくしすぎて、実際のヒストリーデータの本数を超えていないか(超えた分は取得可能な範囲までしか検索されない)
- 戻り値が`-1`になる場合、指定した通貨ペア・時間足のヒストリーデータがまだダウンロードされていない可能性がある
- `type`に`MODE_HIGH`と`MODE_LOW`を取り違えていないか(高値を探すつもりで`MODE_LOW`を指定すると、意図と逆の値になる)
まとめ
`iHighest()`・`iLowest()`は、直近N本の範囲から最も高い/安い足を検索し、
その足の「インデックス(何本前か)」を返す関数です。
価格そのものが欲しい場合は、返ってきたインデックスを`iHigh()`・`iLow()`にもう一度渡す2段階の手順が必要になります。
hl-line.mdのように決まった位置の値を読むだけでなく、
任意の範囲から高値・安値を「探す」処理が必要な場面(ブレイクアウト判定やトレーリングストップの基準値作成など)で活用してください。
コメント