クロスの印は、イベントが起きた場所を示します。データの先頭から何回起きたかも知りたければ、カウンターの値を覚えておく必要があります。

普通の変数では足りない理由

この2行では、各ローソク足で数え直してしまいます。

count = 0
count += 1

最初の行は、main()の実行ごとに0を代入します。次の行で1を加えるため、最終結果は毎回1です。

+=は代入の省略形です。count += 1はcount = count + 1と同じ意味です。元の値を読み、1を加え、結果を変数に戻します。

イベントを累計するには、最初の扱いを変える必要があります。0にするのは、カウンターを初めて作るときだけにしたいからです。

Persistent変数

count: Persistent[int] = 0

Persistentは、値を次のローソク足まで保持する指定です。初期値の0は一度だけ設定します。次の足では、前の確定足から残っている値で続けます。

intは、整数のカウンターであることを示します。Persistentは、以前のSeriesと同じように、pynecoreからインポートします。

この指定でディスクにデータを保存するわけではありません。新しく実行すると、データの先頭から、カウンター0で始まります。1回の実行内で、ローソク足の間の値を保持する仕組みです。

上抜けを数える

event_counter.pyを作ります。

"""
@pyne edge
"""
from pynecore import Persistent
from pynecore.lib import close, color, plot, script, ta


@script.indicator("Crossing Counter", overlay=False)
def main():
    fast_average = ta.sma(close, 5)
    slow_average = ta.sma(close, 20)
    crosses_up = ta.crossover(fast_average, slow_average)
    count: Persistent[int] = 0
    if crosses_up:
        count += 1
    plot(count, "Crossing count", color=color.blue, linewidth=2)

デモデータで実行してください。別パネルのカウンターは0から始まります。上抜けが起こるたびに1増え、その間の足では同じ値を保ちます。

event_counter.pyの横に、クロスの累計回数を示す線がPyneIDEのチャートに表示されている。
上抜けのたびに1増え、他のローソク足では値を保持するカウンター。

最後の値が例えば12なら、処理したデータ全体に上抜けが12回あったことを意味します。画面に見える短い期間には、印がそれより少ないこともあります。チャートを拡大しても、カウンターは初期化されません。

状態と履歴

2つの指定は、それぞれ別の役割を持ちます。

指定実行環境への要求
Series[float]ローソク足ごとの過去の値を参照可能にする
Persistent[int]次のローソク足を保存済みの値で始める

Seriesは各足で代入し、その値から履歴を作ります。Persistentの初期代入は一度だけで、それ以降はコードによる変更で状態を引き継ぎます。

カウンターの過去の値も直接参照したければ、現在のカウントを別のSeries変数に入れられます。値の保持と、添字による過去の参照は別の問題です。

永続変数を置く場所

カウンターは、すべての足で使えるように、条件の前で宣言します。条件を満たさなくても値があり、毎回plotで描けます。

main()の外に、通常の変更可能なグローバルカウンターを作らないでください。ローソク足間の状態は、使う場所でこの指定によって表します。

ここでの過去データの実行は、各足で1回計算します。同じ足を複数回評価する実行モードでは、Persistentは前の確定足の状態に戻って始まります。そのため、内部的な全実行回数を保存するものではありません。この本では、確定足でのイベントを数えるために使います。

条件で値をリセットする

陽線が連続する本数を数える場合は、陰線や始値と終値が同じ足で0にできます。

if close > open:
    streak += 1
else:
    streak = 0

streakは、あらかじめPersistent[int]として作ります。この0への代入は意図した条件付きの操作です。各足の始めに自動で行うものではありません。

自分で試す

永続カウンターをもう1つ追加してください。下抜けを数え、オレンジの線として表示します。両方の計算をすべての足で実行します。

解答

上抜けの計算とともに、次を加えます。

crosses_down = ta.crossunder(fast_average, slow_average)
down_count: Persistent[int] = 0
if crosses_down:
    down_count += 1
plot(down_count, "Downward count", color=color.orange, linewidth=2)

元のcountとその描画は残します。2つのカウンターは独立しています。新しい実行では、両方とも0から計算し直します。

シグナルの位置で確認する

同じデータで、クロスの章のマーカーと、カウンターの変化を比べてください。上抜けした足で、ちょうど1増えるはずです。次の足で再び増えるのは、新しい上抜けがあった場合だけです。