Отметка показывает место события. Чтобы узнать число таких событий от начала данных, программе нужно запоминать счётчик.

Почему обычной переменной недостаточно?

Эти строки начинают счёт заново на каждой свече:

count = 0
count += 1

Первая строка при каждом выполнении main() присваивает ноль. Вторая прибавляет один, итог всегда 1.

+= является сокращённым присваиванием: count += 1 означает то же, что count = count + 1. Читается прежнее значение, прибавляется один и результат сохраняется.

Для накопления событий нужен другой старт. Обнулять следует лишь при первом создании счётчика.

Переменная Persistent

count: Persistent[int] = 0

Persistent означает сохранение значения между свечами. Начальный ноль задаёт переменную один раз. На следующей свече продолжаем со значением прошлой закрытой свечи.

int задаёт целочисленный тип. Persistent импортируется из pynecore, как ранее Series.

Эта метка не сохраняет данные на диск. Новый запуск начинается с начала данных и нулевого счётчика. Речь о сохранении между свечами внутри программы.

Сосчитайте пересечения вверх

Создайте 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)

Запустите на демонстрационных данных. Счётчик в отдельной панели начинается с нуля. При пересечении вверх увеличивается на один, между событиями остаётся прежним.

Рядом с event_counter.py линия графика PyneIDE показывает общее число пересечений.
При пересечении вверх счётчик растёт на один, на остальных свечах сохраняет значение.

Если последнее значение 12, это двенадцать пересечений во всех обработанных данных. В видимом коротком периоде сигналов может быть меньше. Масштабирование не перезапускает счётчик.

Состояние и история

Метки решают разные задачи:

МеткаЧто просим у среды?
Series[float]Доступ к истории значений по свечам
Persistent[int]Начать следующую свечу с сохранённого значения

Присваивание Series выполняется на каждой свече и формирует историю. Начальное присваивание Persistent происходит один раз; затем состояние меняет код.

Для прямого обращения к прошлому счётчику можно поместить текущее значение в отдельную Series. Сохранение и индексирование прошлого являются разными задачами.

Где объявлять сохраняемую переменную

Счётчик объявлен перед условием, в месте, доступном на каждой свече. Поэтому он имеет значение и без условия, а plot всегда может его показать.

Не создавайте обычный изменяемый глобальный счётчик над main(). Опишите состояние между свечами меткой там, где оно используется.

Здесь исторический запуск считает раз на свечу. В режиме с несколькими оценками одной свечи Persistent снова начинает с состояния предыдущей закрытой. Он не хранит число всех технических выполнений. Наш счётчик предназначен для событий закрытых свечей.

Условие может сбросить значение

При подсчёте растущих свечей подряд счётчик можно обнулять на падающей или равной:

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

streak нужно заранее объявить как Persistent[int]. Здесь обнуление намеренно и условно, а не происходит автоматически в начале свечи.

Попробуйте самостоятельно

Добавьте второй сохраняемый счётчик пересечений вниз и покажите оранжевой линией. Оба расчёта выполняются на каждой свече.

Решение

Рядом с расчётом пересечения вверх:

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 и рисование. Счётчики независимы. Новый запуск строит оба с нуля.

Проверьте у сигнала

Сравните отметки из главы о пересечениях с изменениями счётчика на тех же данных. При пересечении вверх он должен вырасти ровно на один. На следующей свече рост допустим только при новом пересечении.