Время и предыдущие свечи
Изучите посвечное исполнение и вычислите изменения по предыдущим значениям.
В прошлой главе вы считали по данным одной свечи. Для изменения закрытия нужны две: текущая и предыдущая. Здесь вы свяжете их.
Программа та же, свеча меняется
На демонстрационных данных PyneCore идёт по свечам в хронологическом порядке. main() работает с первой, затем второй и так далее. close каждый раз означает закрытие обрабатываемой свечи.
Поэтому один вызов plot(close, "Close") рисует целую линию. Одно выполнение добавляет точку, последовательность свечей образует всю линию.
Строка midpoint = (high + low) / 2 тоже выполняется заново на каждой свече. Присваивание пересчитывает её середину. Имя переменной сохраняется, значение может меняться.
Порядок обработки обеспечивает среда исполнения. Писать собственный цикл для всего графика не нужно.
Обращение к прошлому в квадратных скобках
close[1] означает закрытие одной свечой ранее. Число в скобках задаёт глубину обращения.
| Выражение | Какое закрытие? |
|---|---|
close | Обрабатываемой свечи |
close[0] | Тоже обрабатываемой свечи |
close[1] | Одной свечой ранее |
close[2] | Двумя свечами ранее |
Если три последовательных дневных закрытия равны 100, 103 и 101, на третьей свече close равно 101, close[1] равно 103, close[2] равно 100.
Тогда close - close[1] означает 101 - 103, то есть −2. Это разница последовательных закрытий. close - open сравнивает открытие и закрытие одной свечи. Расчёты отвечают на разные вопросы.
Глубина измеряется свечами, не календарными днями. Выходные или торговый праздник могут отделять предыдущую дневную свечу несколькими днями.
У собственного значения тоже есть история
История встроенных цен уже доступна. Для обращения к собственному расчёту пометьте переменную Series:
midpoint: Series[float] = (high + low) / 2После двоеточия идёт аннотация типа. float обозначает число с возможной дробной частью. Series[float] также просит сохранять историю переменной по свечам.
Присваивание всё так же происходит на каждой свече. midpoint является текущим результатом, midpoint[1] значением, сохранённым на предыдущей свече. Имя Series импортируется из pynecore.
Два вида изменений на графике
Создайте history_change.py в папке scripts:
"""
@pyne edge
"""
from pynecore import Series
from pynecore.lib import close, color, high, low, plot, script
@script.indicator("Changes Between Candles", overlay=False)
def main():
midpoint: Series[float] = (high + low) / 2
close_change = close - close[1]
midpoint_change = midpoint - midpoint[1]
plot(close_change, "Close change", color=color.blue)
plot(midpoint_change, "Midpoint change", color=color.orange)Сохраните, выберите Run Pyne code и данные demo. В отдельной панели появятся две линии. Синяя показывает изменение закрытия, оранжевая изменение середины. Положительная точка означает рост относительно прошлой свечи.

Наведите указатель на свечу. Значения графика относятся к моменту под указателем; отдельно выбирать его в файле не требуется.
Что происходит на самой первой свече?
У первой свечи нет предыдущей в файле данных. Поэтому close[1] является отсутствующим значением na, сокращением от «not available».
Отсутствующая цена не равна нулю. Результат close - close[1] тоже отсутствует, и программа не рисует допустимое изменение на первой свече. Это верно: разницу двух свечей нельзя вычислить по одной.
Вызов na(value) проверяет отсутствие значения. Условия вы изучите в главе об условиях и отметках. Пока не пытайтесь исправить отсутствующую точку в начале графика, считая цену нулевой.
Будущие свечи эта запись не открывает. close[-1] тоже не означает следующее закрытие. Решение может использовать только данные, доступные на этом выполнении.
Попробуйте самостоятельно
Измените синюю линию: сравнивайте закрытие с закрытием пятью свечами ранее. Укажите расстояние и в названии линии.
Предскажите, на скольких начальных свечах будет отсутствовать результат.
Решение
close_change = close - close[5]
plot(close_change, "Five-candle change", color=color.blue)На первых пяти свечах нет закрытия пятью свечами ранее. На шестой уже есть: закрытие первой свечи файла.
Оранжевая линия не изменится. Для обоих изменений на пяти свечах нужно также изменить midpoint[1].
Проверьте расчёт
Выберите три последовательные свечи. Запишите закрытия и вручную вычислите односвечное изменение для второй и третьей. Синяя линия должна показывать те же значения. При расхождении сначала проверьте моменты и глубину обращения.
Дополнительное задание: сохранённое значение вместо истории
Одно предыдущее значение можно использовать, сохранив его для следующей свечи. Для этого служит Persistent, который изучается в главе о памяти программы. Задание можно выполнить после неё.
Перепишите history_change.py без close[1] и midpoint[1]. Две персистентные переменные должны хранить прошлые закрытие и середину. Линии должны совпадать с оригиналом, а первое изменение оставаться отсутствующим.
Продумайте порядок: когда читать сохранённое значение и когда заменять текущим?
Решение
Замените импорт Series на Persistent:
from pynecore import PersistentДобавьте na в импорт pynecore.lib. Сохраните начальную метку и настройки индикатора, замените main():
def main():
previous_close: Persistent[float] = na
previous_midpoint: Persistent[float] = na
midpoint = (high + low) / 2
close_change = close - previous_close
midpoint_change = midpoint - previous_midpoint
plot(close_change, "Close change", color=color.blue)
plot(midpoint_change, "Midpoint change", color=color.orange)
previous_close = close
previous_midpoint = midpointНачальные значения обеих переменных равны na: на первой свече предыдущей цены нет. Первая разность тоже отсутствует. В конце функции сохраняем текущие значения для расчёта на следующей свече.
Если поместить previous_close = close перед вычитанием, из текущего закрытия вычтется оно само и получится ноль. Здесь порядок обновления контролируете вы.
Для обращения на одну свечу назад подходят оба способа. Квадратные скобки короче и позволяют напрямую обратиться на несколько свечей назад. Две переменные сохраняют только последние записанные цены.
Запустите оба варианта на одних данных и сравните линии на нескольких свечах.