任意の足のvolume値が、過去N本のvolume値の上位 X番目までにランクインしているか調べる関数を書いてみました。ただ、これは依頼されて作った関数なので、私は使用していません^^;。(関数のコードは本記事の末尾にあります)
関数が行っていること
a本目のローソク足から過去N本の範囲の出来高(volume)を調べます。
その範囲の上位X番目のvolume値と指定したローソク足pのvolume値を比較します。
指定したローソク足pのvolume値が、上位X番目のvolume値以上ならtrueを返します。
WithinTopXvolume(p, a, N, X)
具体例
2本目のローソク足の出来高(volume)が、「3本目から過去10本(3本目~12本目)の出来高のうち、上位5番目」までにランクインしているか調べる場合、引数は以下のようになります。
WithinTopXvolume(2, 3, 10, 5)
戻り値
ランクインしている場合は true を返します。
ランクインしていない場合は false を返します。
備考
チャート上に存在しない足を検索対象として指定した場合、上述の調査をしない
で処理を中止します。この時、関数はfalseを返し、アラートを出します。
アラートが出た場合の戻り値 falseは、「調査を実行できなかった」という意味のfalseです。
チャート上に存在しない足を検索対象にしないという観点で言えば、第1引数~第3引数は「0以上」でなくてはなりません。
それと、ランキングの先頭は1番目という前提で以下のコードは書かれているので、第4引数は「1以上」でなくてはなりません。
コード
//------------------------------------------------------------------------------ // 任意のローソク足のvolume値が、過去N本のvolume値の上位 X番目以内か調べる関数 //------------------------------------------------------------------------------ // [この関数が行っていること] // a本目のローソク足から過去N本の範囲の出来高(volume)を調べる。 // その範囲の上位X番目のvolume値と指定したローソク足のvolume値を比較する。 // 指定したローソク足のvolume値が、上位X番目のvolume値以上ならtrueを返す。 // // [使用例] // 2本目のローソク足の出来高(volume)が、「3本目から過去10本(3本目~12本目) // の出来高のうち、上位5番目」までにランクインしているか調べる場合、引数は // 以下のとおり。 // // WithinTopXvolume(2, 3, 10, 5) // // [戻り値] // ランクインしている場合は true を返す。 // ランクインしていない場合は false を返す。 // // [備考] // チャート上に存在しない足を検索対象として指定した場合、上述の調査をしない // で処理を中止する。この時、関数はfalseを返し、アラートを出す。 // アラートが出た場合、「調査を実行できなかった」という意味でfalse。 //------------------------------------------------------------------------------ bool WithinTopXvolume(int targetShift, // 対象とする足のシフト int startShift, // 範囲の開始シフト int bars, // 範囲(開始シフトを含めてN本) int rank) // 範囲の上位 X 番目 { //----------------------------------------------------------------------------- // チャート上に存在しない足を検索対象にした場合、処理を中止してアラートを出す //----------------------------------------------------------------------------- if(Bars - 1 < startShift + bars - 1) { // 左辺と右辺の「-1」は無くてもOK Alert("Function Error [WithinTopXvolume] : Read the message on Expert."); printf("Function Error [WithinTopXvolume] : You tried to access the candle out of range."); return(false); } bool res = false; // 関数の戻り値 int counter = 0; // 配列操作用のカウンタ long array[]; // iVolume関数の戻り値がlong型なので配列もlong型 ArrayResize(array, bars); // 配列の要素数をセット // 指定したシフトから過去bars本の出来高を配列に格納 for(int k = startShift; k < startShift + bars; k++) { array[counter] = iVolume(NULL, PERIOD_CURRENT, k); counter++; } //----------------------------------------------------------------------------- // 配列内に同じ値が2つ以上あったら、1つは残し、残りは最小値に書き換える //----------------------------------------------------------------------------- // 最初に配列の中身を降順で並び替えておく ArraySort(array, WHOLE_ARRAY, 0, MODE_DESCEND); // 配列内の最小値をminValueに格納 // (降順ソート済なので long minValue = array[bars - 1] でも可) long minValue = array[ArrayMinimum(array, WHOLE_ARRAY, 0)]; long tmp = array[0]; // 配列の先頭要素の値をtmpに代入 for(int j = 1; j < bars; j++) { // 要素の値が最小値と同じならループを抜ける(無駄な処理を減らす) if(array[j] == minValue) break; // 要素の値がtmpと同じなら、その要素をminValueに書き換える if(tmp == array[j]) { array[j] = minValue; } // 要素の値がtmpと違うなら、tmpにその要素の値を代入する else { tmp = array[j]; } } ArraySort(array, WHOLE_ARRAY, 0, MODE_DESCEND); // 改めて降順で並び替え // 比較対象とするローソク足のvolume値をtargetValueに格納 long targetValue = iVolume(NULL, PERIOD_CURRENT, targetShift); // targetValueが上位X番目のvolume値以上ならresにtrueを代入 if(targetValue >= array[rank - 1]) { res = true; } return res; }
追記
この記事を書き終えてから思ったのですが・・・。
for(int j = 1; j < bars; j++) {
この行の「bars」のところは「bars - 1」の方が良かったですね。
降順に並び替えた後なので、配列の最終要素は最小値です。
だから、配列の最終要素に対しては何の処理も不要ですね。