Если цена десять свечей держится выше среднего, close > average может быть истинным десять раз. Чтобы отметить только переход снизу вверх, нужна и связь значений на прошлой свече.

Положение и его начало

Пусть среднее сейчас и на прошлой свече равно 100, прошлое закрытие 99, текущее 101. Сейчас цена выше среднего и пересекла его относительно прошлой свечи.

При следующем закрытии 102 цена останется выше. Нового пересечения вверх нет, потому что на прошлой свече она уже была выше.

ta.crossover(first, second) истинно, когда первое значение сейчас больше второго, а на прошлом выполнении было меньше либо равно. ta.crossunder является нисходящей парой.

Текущее равенство ещё не пересечение: если первое лишь достигло второго, > ложно. Равенство на прошлой свече, напротив, допускает пересечение при текущем переходе выше.

Быть выше и пересечь снизу вверхЦена закрытия пересекает среднюю снизу вверх только на третьей свече. На четвёртой она остаётся выше без нового сигнала. Равенство на предыдущей свече также допускает пересечение. close: 99 → 100 → 101 → 102. average: 100 → 100 → 100 → 100. close > average: False → False → True → True. ta.crossover(close, average): False → False → True → False.Цена закрытияaverage = 100991FalseFalse1002FalseFalse1013TrueTrue1024TrueFalseСвечаclose > averageta.crossover(close, average)
Быть выше и пересечь снизу вверхЦена закрытия пересекает среднюю снизу вверх только на третьей свече. На четвёртой она остаётся выше без нового сигнала. Равенство на предыдущей свече также допускает пересечение.

Пересечение двух средних

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

Создайте cross_signals.py:

"""
@pyne edge
"""
from pynecore.lib import close, color, input, location, plot, plotshape, script, shape, ta


@script.indicator("Average Crossings", overlay=True)
def main(
    fast_length: int = input.int(5, title="Fast length", minval=1, maxval=200),
    slow_length: int = input.int(20, title="Slow length", minval=1, maxval=200),
):
    fast_average = ta.sma(close, fast_length)
    slow_average = ta.sma(close, slow_length)
    crosses_up = ta.crossover(fast_average, slow_average)
    crosses_down = ta.crossunder(fast_average, slow_average)
    plot(fast_average, "Fast average", color=color.blue, linewidth=2)
    plot(slow_average, "Slow average", color=color.orange, linewidth=2)
    plotshape(crosses_up, "Cross up", style=shape.triangleup,
              location=location.belowbar, color=color.green)
    plotshape(crosses_down, "Cross down", style=shape.triangledown,
              location=location.abovebar, color=color.red)

Запустите на демонстрационных данных со значениями 5 и 20. Отметки появляются только на свечах пересечений. На длинном участке, где синяя линия остаётся выше оранжевой, новой зелёной отметки на каждой свече нет.

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

Почему пересечение вычисляется отдельно?

ta.crossover и ta.crossunder выполняются на каждой свече. Поэтому их прошлое выполнение относится к предыдущей обработанной свече.

Если вызывать функцию только при другом условии, прошлое состояние может относиться не к прошлой свече. Линия и отметки могли бы изучать разные временные ряды.

Следуем прежнему правилу: на каждой свече вычисляем нужные результаты с состоянием, затем принимаем решения по готовым значениям.

Прогрев заметен и здесь

SMA длиной двадцать допустима лишь с двадцатой свечи. При первом допустимом значении её прошлое значение ещё отсутствует, поэтому двух полных свечей для определения пересечения нет.

Нужны текущие и прошлые значения обеих средних.

Не стоит заменять na нулём ради сигнала. Нулевая средняя могла бы создать искусственное пересечение там, где реальная ещё не вычисляется.

Момент известности данных

В книге мы запускаем программы на закрытых исторических свечах. Сигнал по дневному закрытию использует данные, известные при закрытии свечи.

Закрытие ещё формирующейся свечи может меняться. Пересечение, заметное внутри неё, к концу может исчезнуть. Это не то же самое, что проверка закрытых свечей.

Историческая отметка не означает автоматически сделку на той же свече. Индикатор рисует сигнал; приказы и время исполнения мы зададим в стратегии.

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

Скопируйте как price_crossings.py. Вместо пересечения средних отметьте переход закрытия выше и ниже медленного среднего. Медленное среднее оставьте.

Решение
crosses_up = ta.crossover(close, slow_average)
crosses_down = ta.crossunder(close, slow_average)

Отметки используют две логические переменные, поэтому строки plotshape менять не требуется. Заголовки стоит заменить на Price cross up и Price cross down.

Если быстрая средняя больше не нужна, удалите её расчёт, рисование и input. Тогда интерфейс предлагает только используемые настройки.

Проследите пересечение

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