恥は/dev/nullへ by 初心者

プログラミング素人がのろのろと学んだことをつづっています♪

任意のローソク足のvolume値が、過去N本のvolume値の上位 X番目までにランクインしているか調べてみる

任意の足の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」の方が良かったですね。

降順に並び替えた後なので、配列の最終要素は最小値です。
だから、配列の最終要素に対しては何の処理も不要ですね。