#compiler-construction #interpreter #pine-script
#построение компилятора #интерпретатор #pine-script
Вопрос:
Введение
Pinescript — это подходящий язык программирования для тестирования торговых алгоритмов. Язык всегда был мне интересен, потому что он ориентирован на ряды, в результате чего определенные функции работают таким образом, который отличается от обычных языков.
Четыре основные переменные ряда, open
, high
, low
и close
указывают на массивы, которые формируют столбчатые данные, поэтому, если бы вы написали код
plot(close)
Это отобразило бы цены закрытия на графике. Это достаточно легко понять, поскольку под капотом переменная close
просто указывает на массив данных с плавающей ценой, а plot
метод выводит этот массив.
Аналогично код
plotchar(close > open, 'A')
Отобразит символ «A», где значение закрытия больше значения открытия в массивах.
Операторы If работают уникальными способами при сравнении двух рядов:
1.
if (close > open)
strategy.entry(id="EL", long=true, qty=5)
Что эквивалентно
2.
strategy.entry(id="EL", when = close > open, long=true, qty=5)
В примере 1 результаты оператора if применяются ко всем аргументам strategy.entry
метода (везде, где есть ссылка на любой ряд, если он находится в области действия оператора if). Ключевым параметром в этом случае является when
параметр. Когда не определен, when
параметр указывает на массив, полный истинных значений. Однако, поскольку он находится внутри области, где значения рядов могут быть оценены только где close > open
, результатом является то, что он работает точно так же, как в примере 2.
Приведенный выше пример не имеет прямого отношения к моему вопросу, но я сохранил его, чтобы подчеркнуть, как Pinescript работает по-разному по сравнению с тем, что можно ожидать от традиционного языка программирования.
Динамические данные
Часть, которую я не понимаю, заключается в том, что определенные специальные переменные смешиваются с обычными выражениями. Данные этих переменных не существуют до тех пор, пока не будут вызваны определенные функции, однако они, по-видимому, оцениваются так, как можно было бы интуитивно ожидать, независимо от того факта, что их данные не могут существовать во время чтения анализатором входного кода. Например, переменная серии strategy.position_size
является переменной серии (с плавающими значениями), которая содержит общий размер позиции по мере оценки ордеров. Например.
strategy.entry(id="EL", when = close > open, long=true, qty=5)
plot(strategy.position_size)
Это отобразит размер позиции на графике. Это достаточно просто, за исключением того, что приведенный ниже код также даст те же результаты:
plot(strategy.position_size)
strategy.entry(id="EL", when = close > open, long=true, qty=5)
Это говорит о том, что positon_size
переменная обрабатывается как какая-то специальная переменная, которая не будет вычисляться до тех пор, пока не будет выполнена какая-либо из функций заказа ( strategy.entry
). Возможно, компилятор обнаружит, что строка кода plot(strategy.position_size)
не может быть вычислена в этот момент, поэтому сохраняется до тех пор, пока не будет выполнен любой код, влияющий на эту переменную ( strategy.entry
).
Однако немного сбивает с толку тот факт, что вы можете использовать эти специальные переменные в выражениях, которые непосредственно влияют на результат этой переменной. Например:
strategy.entry(id="EL", when = strategy.position_size==0, long=true, qty=5)
Когда компилятор достигает strategy.entry
метода, он видит, что он должен вводить позицию только в том случае, если position_size == 0
. Однако position_size
переменная data напрямую зависит от того, когда strategy.entry
вызывается. Это похоже на сценарий catch 22, и я не уверен относительно того, как компилятор будет обрабатывать этот код.
Есть ли у вас какие-нибудь идеи о том, как компилятор Pinescript обрабатывает эти специальные «динамические» переменные? Существуют ли какие-либо документированные примеры подобного сценария, происходящего на разных языках программирования?
Прошу прощения, если моя терминология не соответствует действительности или сбивает с толку. Я занимаюсь дизайном переводчиков всего год, и мне еще многому предстоит научиться.
Ответ №1:
Здесь нет волшебства. Вы должны понимать, что strategy.entry / exit / etc только РАЗМЕСТИТ ордер, а ордер будет выполнен позже, и только после этого позиция откроется или закроется, а значение strategy.position_size изменится.
Ответ №2:
Принцип работы PineScript заключается в том, что весь ваш код выполняется для каждой свечи и вычисляются новые значения.
В вашем примере, когда вы вызываете:
strategy.entry(id="EL", when = strategy.position_size==0, long=true, qty=5)
значение strategy.position_size
— это значение, которое было рассчитано для предыдущей свечи.