前回は、CopyRates関数が取得できる複数のバー情報のうち、1つだけをコピーして取得するCopy関数について紹介しました。
———————————————————–
・CopyOpen関数:各バーの始値を取得する関数
※前回作った「OriginalCBarsクラス」のメンバ関数では、Open関数 にあたる
・CopyClose関数:各バーの終値を取得する関数
前回作った「OriginalCBarsクラス」のメンバ関数ではClose関数 にあたる
・CopyHigh関数:各バーの高値を取得する関数
前回作った「OriginalCBarsクラス」のメンバ関数ではHigh関数 にあたる
前回作った「OriginalCBarsクラス」のメンバ関数ではLow関数 にあたる
・CopyTime関数:各バーのオープン時間を取得する関数
前回作った「OriginalCBarsクラス」のメンバ関数ではTime関数 にあたる
・CopyTickVolume関数:各バーのティック数を取得する関数
前回作った「OriginalCBarsクラス」のメンバ関数ではTickVolume関数 にあたる
・CopyRealVolume関数:各バーの取引量を取得する関数
前回作った「OriginalCBarsクラス」のメンバ関数ではVolume関数 にあたる
———————————————————–
第104回で作った「OriginalCBarsクラス」と前回解説したコピー関数を押さえていればバー情報取得に関して困る事はないでしょう。
さて、今回は指定期間における「最高値」「最安値」について解説していきたいと思います。
指定期間における「最高値」「最安値」を適切に取得する事は、トレードロジックの構築~EAへの実装にあたって重要な部分となります。
トレンドフォロー戦略やトレーリングストップなどをのアイディアを取り込むにあたっても、関連してくる部分かとおもいますので、是非今回の記事で楽しく学んで頂ければと思います。
最高値・最安値とは?
特定期間における最高値・最安値とは、ある定められた期間内におけるもっとも高い価格、もっとも安い価格の事を指します。
最高値・最安値は相場の中で常に意識されるポイントであり、最高値・最安値のラインを突き抜ければしばらく同じ方向にトレンドが続く、逆に最高値・最安値が防衛線となって、跳ね返されればしばらくレンジ相場が続く、という原理原則(とされるもの)があります。
必然的にトレード戦略の中核に据えられることも多くなります。
従って、これらの最高値・最安値を上回る、あるいは下回ったらエントリーする、いわゆるブレイクアウト狙いのトレンドフォローエントリーや、ストップロスエントリーの目安にする
などの戦略は割と一般的かと思います。
————————————————–
※トレンドフォローについては以下の記事も参考になるかと思います。↓
————————————————–
とはいえ指定期間における「最高値」「最安値」実装については今回の記事が初めての解説、という訳ではありません。
や
にて、取り扱っていますし、<MQL5でEAを作ろう講座>内の記事では↓の講座記事でも登場しています。
直近高値・直近安値の取得方法について
直近高値・直近安値の取得方法については大きく分けて以下の2パターンがあります。
1:iHighest関数やiLowest関数を使って取得する方法
2:ArrayMaximum関数やArrayMinimum関数を使って取得する方法
そのうち、1のiHighest関数やiLowest関数を使った直近高値・直近安値の取得方法については↓
にてすでに解説を行っていますので、コチラをご覧ください。
今回は、2のArrayMaximum関数やArrayMinimum関数を使って取得する方法
を紹介したいと思います。
まずは、ArrayMaximum関数やArrayMinimum関数とはどのような関数なのか?という事を、引数や戻り値などを紹介しながら見ていきます。
ArrayMaximum関数について
ArrayMaximum関数は指定した配列の、指定した期間中における最高値が格納されている
※あくまで、「インデックス(通し番号)=最安値の価格がある場所」を戻り値として返すのであって、最高値の価格そのものを返す訳ではないので注意が必要です。
ArrayMaximum関数の戻り値と引数構成は以下のようになっています。
int ArrayMaximum(
const void& array[], // 検索される配列
int start=0, // チェック開始インデックス
int count=WHOLE_ARRAY // チェックされた要素数
);
//戻り値はチェックした要素数の中で最高値があった箇所のインデックス
ArrayMaximum関数の戻り値
ArrayMaximum関数の戻り値は、チェックした要素の中で最高値があった箇所のインデックス番号を返します。
※インデックスというのは配列に格納されている箱が何番目に存在するかを示す通し番号だと思ってください。
↑の説明だけではよくわからない方も多いと思いますが、現時点ではそれで問題ないのでこの先の、引数構成部分を読み進めて頂ければと思います。
第1引数には「検索対象の配列名」を記述する
ArrayMaximum関数の第1引数には「検索対象の配列名」を記述します。
メインプログラムにおいては、事前に高値を格納する配列を用意しておき、その配列が記述される想定です。
第2引数には「チェックを開始する配列のインデックス位置」を記述する
ArrayMaximum関数の第2引数には「チェックを開始する配列のインデックス位置」を記述します。
ところで
とはどういうことでしょうか?
後述しますが、第1引数に記述する配列はArraySetAsSeries関数によって、直近の時間軸から順番に高値データが配列に格納されるようになっています。
インデックス番号が大きくなるほど、過去のデータになる、と言い換えることもできますね。
インデックス番号が「0」の場合は、現在足のデータという事になります。
従って、もし現在足からデータの検索をしたい場合にはメインプログラムにおいて、ここに「0」と記述すればよいことになります。
第3引数には「チェックされた要素数」を記述する
ArrayMaximum関数の第3引数には「チェックされる要素数」を記述します。
第2引数で検索開始位置を指定する、というのは先程書いた通りですが、その検索開始位置から何個分の要素数をチェックするのか?
という事をこの第3引数で指定する訳です。
例えば第2引数で「0」を記述し、この第3引数で「10」を記述した場合、
「現在足から過去に遡って10期間分の高値情報をチェックする」
という事を意味します。
※なお、この第3引数の初期値には「WHOLE_ARRAY」という定数値が設定されており、記述を省略した場合、このWHOLE_ARRAYが適用されます。
WHOLE_ARRAYとは?
WHOLE_ARRAYとは、配列全体を対象とする事を指定する定数値です。
第3引数の初期値はこのWHOLE_ARRAYが設定されています。
従って、第3引数の記述を省略した場合や、WHOLE_ARRAYを記述した場合は配列全体をチェックすることになります。
ArrayMaximum関数を使った最高値の取得手順
ArrayMaximum関数の戻り値・引数についての説明が終わった所で、実際にArrayMaximum関数を使った最高値の取得手順について解説していきたいと思います。
ArrayMaximum関数を使った最高値は、以下の手順を踏んで取得します。
4:ArrayMaximum関数を使い配列から最高値のインデックスを取得する。
5:取得した最高値のインデックスを使い、配列から最高値を取得する。
それぞれの工程を順を追って見ていきましょう。
1:高値を格納する配列を用意する。
まずは高値を格納する配列を用意します。
High[]配列は、CopyHigh関数を使って、各足ごとの高値情報を格納する配列です。
//高値の情報を格納する変数配列を宣言
double High[];
※あくまで時間足ごとの高値であり、この時点では特定期間の最高値を格納している配列ではない点に注意してください。
2:配列を時系列にセットする
続いて、最新足から古い時間足に向かってデータが格納されるように配列をセットします。
※インデックス[0]が一番直近の時間足のデータになります。
//配列を時系列にセット
ArraySetAsSeries(High,true);
ArraySetAsSeries関数については↓の記事をご覧ください。
3:高値の情報を配列にコピーする
CopyHigh関数を使って、配列にデータをコピーしていきます。
//高値情報を配列にコピー
CopyHigh(_Symbol,_Period,0,100,High);
↑のサンプルコード例では、第3引数に指定した「0」、すなわち現在足から100期間分の高値データを配列「High」にコピーする、という意味の記述となります。
※Copy~関数については↓の講座記事で解説しておりますので、ご参照ください。
・MQL5 EA講座 第105回「CopyRates関数以外のCopy関数」
4:ArrayMaximum関数を使い配列から最高値のインデックスを取得する。
続いてArrayMaximum関数を使い配列から最高値のインデックスを取得します。
//高値格納配列の最高値インデックスを格納
HighestHigh=ArrayMaximum(High,0,10);
時系列ごとの高値を格納している配列HighのなかからArrayMaximum関数を使って最高値のインデックスを見つけ出し、そのインデックスを変数 「HighestHigh」に格納します。
5:取得した最高値のインデックスを使い、配列から最高値を取得する。
最後に最高値の存在するインデックスを格納した変数 「HighestHigh」を配列「High」に指定し、最高値の値を取得します。
double highestPrice=High[HighestHigh];
ArrayMaximum関数を使った最高値の取得プロセスは以上になります。
続いては、ArrayMinimum関数についての紹介と、そのArrayMinimum関数を使った最安値取得方法を解説していきたいと思います。
ArrayMinimum関数について
ArrayMinimum関数は指定した配列の、指定した期間中における最安値が格納されているインデックス(通し番号)を取得する関数です。
※あくまで、「インデックス(通し番号)=最安値の価格がある場所」を戻り値として返すのであって、最安値の価格そのものを返す訳ではないので注意が必要です。
ArrayMinimum関数の戻り値と引数構成は以下のようになっています。
int ArrayMinimum(
const void& array[], // 検索される配列
int start=0, // チェック開始インデックス
int count=WHOLE_ARRAY // チェックされた要素数
);
ArrayMinimum関数の戻り値
ArrayMinimum関数の戻り値は、チェックした要素の中で最高値があった箇所のインデックス番号を返します。
※インデックスというのは配列に格納されている箱が何番目に存在するかを示す通し番号だと思ってください。
第1引数には「検索対象の配列名」 を記述する
ArrayMinimum関数の第1引数には「検索対象の配列名」を記述します。
メインプログラムにおいては、事前に安値を格納する配列を用意しておき、その配列が記述される想定です。
第2引数には「チェックを開始する配列のインデックス位置」を記述する
ArrayMinimum関数の第2引数には「チェックを開始する配列のインデックス位置」を記述します。
第1引数に記述する配列はArraySetAsSeries関数によって、直近の時間軸から順番に安値データが配列に格納されるようになっています。
インデックス番号が大きくなるほど、過去のデータになる、ということになります。
インデックス番号が「0」の場合は、現在足のデータという事です。
従って、もし現在足からデータの検索をしたい場合にはメインプログラムにおいて、ここに「0」と記述すればよいことになります。
第3引数には「チェックされた要素数」を記述する
第2引数で検索開始位置を記述する訳ですが、その検索開始位置から何個分の要素数をチェックするのか?
という事をこの第3引数で指定します。
例えば第2引数で「0」を記述し、この第3引数で「10」を記述した場合、
「現在足から過去に遡って10期間分の高値情報をチェックする」
という事を意味します。
※第3引数の初期値には「WHOLE_ARRAY」という定数値が設定されています。WHOLE_ARRAYは「全配列をチェックする」事を意味する定数値です。
第3引数の記述を省略した場合、このWHOLE_ARRAYが適用されます。
ArrayMinimum関数を使った最安値の取得手順
ArrayMinimum関数の戻り値・引数についての説明が終わった所で、今度はArrayMinimum関数を使った最安値の取得手順について解説していきたいと思います。
ArrayMinimum関数を使った最安値は以下の手順を踏んで取得します。
4:ArrayMinimum関数を使い配列から最安値のインデックスを取得する。
5:取得した最安値のインデックスを使い、配列から最安値を取得する。
それぞれの工程を順を追って見ていきましょう。
1:安値を格納する配列を用意する。
まずは安値を格納する配列を用意します。
//安値の情報を格納する変数配列を宣言
double Low[];
Low[]配列は、CopyLow関数を使って、各足ごとの高値、安値情報を格納する配列です。
※あくまで時間足ごとの安値であり、この時点では特定期間の最安値を格納している配列ではない点に注意してください。
2:配列を時系列にセットする
続いて、最新足から古い時間足に向かってデータが格納されるように配列をセットします。
配列の時系列セットにはArraySetAsSeries関数を利用します。
※インデックス[0]が一番直近の時間足のデータになります。
//配列を時系列にセット
ArraySetAsSeries(Low,true);
3:安値の情報を配列にコピーする
CopyLow関数を使って、安値データを配列にデータをコピーしていきます。
//安値の情報を配列にコピー
CopyLow(_Symbol,_Period,0,100,Low);
↑のサンプルコード例では、第3引数に指定した「0」、すなわち現在足から100期間分の安値データを配列「Low」にコピーする、という意味の記述となります。
4:ArrayMinimum関数を使い配列から最安値のインデックスを取得する。
続いてArrayMinimum関数を使い配列から最高値のインデックスを取得します。
//安値格納配列の最安値インデックスを格納
LowestLow=ArrayMinimum(Low,0,10);
時系列ごとの安値を格納している配列LowのなかからArrayMinimum関数を使って最安値のインデックスを見つけ出し、そのインデックスを変数 「LowestLow」に格納します。
5:取得した最安値のインデックスを使い、配列から最安値を取得する。
最後に最安値の存在するインデックスを格納した変数 「LowestLow」を配列「Low」に指定し、最安値の値を取得します。
double lowestPrice=Low[LowestLow];
ArrayMinimum関数を使った最安値の取得プロセスは以上になります。
iHighest/iLowest関数とArrayMaximum/ArrayMinimum関数の違い
ここまで、
ArrayMaximum関数 と ArrayMinimum関数 を使った最高値と最安値の取得方法を解説してきました。
その一方でHighest関数とLowest関数を使った最高値と最安値の取得方法については↓
にて解説済みである事は冒頭で書いた通りです。
2パターンある最高値・最安値の取得方法についての解説が終わった所で、一旦
iHighest関数/Lowest関数とArrayMaximum関数/ArrayMinimum関数の違いというものをざっとおさらいしておきましょう。
どちらも最終的に、「指定期間の最高値・最安値のあるインデックスを取得する」という目的は同じです。
では、どこに違いがるのかというと、指定期間の検索対象が違います。
iHighest関数とiLowest関数はチャートの中から、指定期間高安値のインデックスを取得します。
それに対して、
ArrayMaximum関数やArrayMinimum関数はチャートデータを格納した配列の中から指定期間高安値インデックスを取得する、
という違いがあります。
ここまでの解説を読むとわかるように、
ArrayMaximum関数やArrayMinimum関数を使って、最高値・最安値を導き出すのは結構な手順を踏まなければならず面倒です。
そこで、次はその手順を簡略化した最高値・最安値を算出するオリジナル関数を作っていきたいと思います。
最高値・最安値を算出するオリジナル関数を作る
最高値・最安値を算出するオリジナル関数は講座記事第103回で作った「OriginalPrice.mqh」ファイル内に追加していきます。
※インクルードファイルについては↓の記事をご参照ください。
MQL5 EA講座 第56回「#include命令(#include directive)」
HighestHigh関数について
まずは最高値を算出する関数から作っていきます。
double HighestHigh(string parSymbol, ENUM_TIMEFRAMES parPeriod, int parBars, int parStart = 0)
{
double high[];//高値を格納する配列を用意
ArraySetAsSeries(high,true);//配列を時系列にセット
int copied = CopyHigh(parSymbol,parPeriod,parStart,parBars,high);//高値情報を配列にコピー
if(copied == -1) return(copied);//コピーエラーが発生したら終了
int maxIdx = ArrayMaximum(high);//最高値のあるインデックスを取得し変数に格納
double highest = high[maxIdx];//最高値を取得し変数に格納
return(highest);//最高値を戻り値として返す
}
関数名はHighestHigh関数としました。最高値を取得して、戻り値として返す想定なので、戻り値のデータ型はdouble型です。
第1仮引数「parSymbol」には、取引銘柄情報をする。
string型の第1仮引数「parSymbol」には、取引銘柄情報が記述される想定です
第2仮引数「parPeriod」には、チャートの時間軸を記述する。
第2仮引数「parPeriod」はチャートの時間軸が記述される想定です。
データ型はENUM_TIMEFRAMESとなります。
ENUM_TIMEFRAMESはチャートの時間軸を格納するenum列挙型です。
※enum列挙型については↓の記事をご覧ください。
第3仮引数「parBars」には、複製されるデータ数を記述する。
第3仮引数「parBars」には複製されるデータ数が記述される想定です。
第4仮引数「parStart」には、コピー開始位置を記述する
第4仮引数「parStart」には、コピー開始位置が記述される想定です。「parStart」には初期値に「0」を割り当てています。「parStart」への記述を省略した場合、「0」すなわち現在足からコピーが開始されます。
HighestHigh関数の処理実装記述について
HighestHigh関数の処理実装記述についてなのですが、
基本的に、今回の記事における「ArrayMaximum関数を使った最高値の取得手順」セクションで書いた、
4:ArrayMaximum関数を使い配列から最高値のインデックスを取得する。
5:取得した最高値のインデックスを使い、配列から最高値を取得する。
という1~5のプロセスを盛り込んだだけです。違う点は
if(copied == -1) return(copied);//コピーエラーが発生したら終了
↑の箇所と
return(highest);//最高値を戻り値として返す
の部分だけです。
この2か所は要は、処理が失敗した場合と、成功した場合の戻り値についての記述です。
高値情報のコピーに失敗した場合は、-1を戻り値として返し、正常に最高値を取得出来た場合は最高値を戻り値として返す、という事を記述しています。
HighestHigh関数の戻り値、引数、処理実装記述については以上となります。
LowestLow関数について
続いては最安値を取得する関数についてです。
//+------------------------------------------------------------------+
//| 最安値を取得する関数 |
//+------------------------------------------------------------------+
double LowestLow(string parSymbol, ENUM_TIMEFRAMES parPeriod, int parBars, int parStart = 0)
{
double low[];//安値を格納する配列を用意
ArraySetAsSeries(low,true);//配列を時系列にセット
int copied = CopyLow(parSymbol,parPeriod,parStart,parBars,low);//安値情報を配列にコピー
if(copied == -1) return(copied);//コピーエラーが発生したら終了
int minIdx = ArrayMinimum(low);//最安値のあるインデックスを取得し変数に格納
double lowest = low[minIdx];//最安値を取得し変数に格納
return(lowest);//最安値を戻り値として返す
}
関数名はLowestLow関数としました。最安値を取得して、戻り値として返す想定なので、戻り値のデータ型はdouble型です。
第1仮引数「parSymbol」には、取引銘柄情報をする。
string型の第1仮引数「parSymbol」には、取引銘柄情報が記述される想定です
第2仮引数「parPeriod」には、チャートの時間軸を記述する。
第2仮引数「parPeriod」はチャートの時間軸が記述される想定です。データ型はENUM_TIMEFRAMESとなります。ENUM_TIMEFRAMESはチャートの時間軸を格納するenum列挙型です。
第3仮引数「parBars」には、複製されるデータ数を記述する。
第3仮引数「parBars」には複製されるデータ数が記述される想定です。
第4仮引数「parStart」には、コピー開始位置を記述する
第4仮引数「parStart」には、コピー開始位置が記述される想定です。「parStart」には初期値に「0」を割り当てています。「parStart」への記述を省略した場合、「0」すなわち現在足からコピーが開始されます。
LowestLow関数の処理実装記述について
LowestLow関数の処理実装記述についてなのですが、
基本的に、今回の記事における「ArrayMinimum関数を使った最安値の取得手順」セクションで書いた、
4:ArrayMinimum関数を使い配列から最安値のインデックスを取得する。
5:取得した最安値のインデックスを使い、配列から最安値を取得する。
という1~5のプロセスを盛り込んだだけです。違う点は
if(copied == -1) return(copied);//コピーエラーが発生したら終了
↑の箇所と
return(highest);//最高値を戻り値として返す
の部分だけです。
この2か所は要は、処理が失敗した場合と、成功した場合の戻り値についての記述です。
安値情報のコピーに失敗した場合は、-1を戻り値として返し、正常に最安値を取得出来た場合は最安値を戻り値として返す、という事を記述しています。
LowestLow関数の戻り値、引数、処理実装記述については以上となります。
まとめ
今回は指定期間における「最高値」「最安値」の取得方法について解説しました。
直近高値・直近安値の取得方法については大きく分けて、
1:iHighest関数やiLowest関数を使って取得する方法
2:ArrayMaximum関数やArrayMinimum関数を使って取得する方法
の2パターンがあることを伝えた上で、今回の記事では2の方法であるArrayMaximum関数及びArrayMinimum関数を使った最高値・最安値取得手順について主に解説を行いました。
※1の方法については講座記事第81回をご覧ください。
実際の取得手順については↓今回の記事の、
「ArrayMaximum関数を使った最高値の取得手順」セクション
「ArrayMinimum関数を使った最安値の取得手順」セクション
をそれぞれご覧ください。
そして、上記のセクションにてArrayMaximum関数及びArrayMinimum関数を使ったノーマルな最高値・最安値取得手順をお伝えした上で、より手順を簡略化できる、
という2つのオリジナル関数を作り、 「OriginalPrice.mqh」ファイル内に追加しました。
※HighestHigh関数、LowestLow関数の追加に伴い、講座記事第106回時点でのOriginalPrice.mqh」ファイルのソースコード全容は↓のリンク記事にて確認できます。
・講座記事第106回時点でのOriginalPrice.mqhファイル全体のコード記述について
今回は以上とさせていただきます。
最後までお読みいただきありがとうございました。