Поприветствуем Pine Script® v5

7 окт, 2021

Сегодня Pine, наш язык программирования индикаторов и стратегий, переходит на версию 5! В новой версии добавляется ряд долгожданных функций и улучшений. Pine теперь мощнее, чем когда-либо, и v5 поможет нам вывести его на новый уровень. В этом посте упоминаются лишь некоторые из новых функций, доступных в v5; чтобы узнать обо всём новом функционале, прочтите раздел Release Notes в нашем Руководстве пользователя.

Конвертер из v4 в v5 

Уже существующие индикаторы и стратегии, написанные на предыдущих версиях Pine, будут и дальше работать без изменений. Для тех, кто хочет опробовать новый функционал, мы предоставляем возможность автоматически конвертировать скрипты четвёртой версии в пятую — в дальнейшем новый функционал Pine будет выходить исключительно для v5. Инструмент конвертации скриптов v4 в v5 доступен в выпадающем меню по нажатию кнопки Ещё, когда в редакторе открыт скрипт четвёртой версии:

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

Библиотеки

Ключевое нововведение Pine v5 — это библиотеки, новый тип публикации. Библиотеки позволяют создавать и экспортировать пользовательские функции для повторного использования в других скриптах. Когда библиотека опубликована, другие скрипты (будь то индикаторы, стратегии или даже другие библиотеки) могут её импортировать и использовать написанные в ней функции. Вы можете создать библиотеку, которая реализует какой-либо сложный алгоритм или часто запрашиваемую функцию, чтобы вам (или всему сообществу Pine) в будущем было проще их использовать.

Чтобы начать работу с библиотеками, обратитесь к нашей странице Руководства пользователя о библиотеках. В конце этого поста вы найдете примеры библиотек, опубликованные членами нашей команды PineCoders. Все опубликованные библиотеки можно посмотреть здесь, на странице опубликованных скриптов, отфильтрованной по типу «Библиотека».

Значения по умолчанию для пользовательских функций

Улучшение, которое идет рука об руку с библиотеками: теперь для параметров в пользовательских функциях можно определять значение по умолчанию, что фактически делает эти параметры опциональными. В примере ниже мы объявляем функцию customPow(), которая возводит аргумент base в степень exp. Если значение exp не определено, используется 2:

//@version=5
indicator("")
customPow(base, exp = 2) =>
    result = 1
    for i = 1 to exp
        result *= base
plot(customPow(11)) // 11^2
plot(customPow(11, 4)) // 11^4

Оператор switch

Новый оператор switch по своей сути напоминает уже существующий if. Если вам приходилось создавать длинное дерево условий if-else, вы оцените, насколько удобнее делать это же при помощи оператора switch. Больше информации о том, как работает этот оператор, доступно в справочнике Pine, а в коде ниже можно увидеть его в действии: мы переписали наш встроенный индикатор Средний истинный диапазон, чтобы в нём switch использовался для выбора типа скользящей средней:

//@version=5
indicator(title="Average True Range", shorttitle="ATR", timeframe="")
lengthInput = input.int(title="Length", defval=14, minval=1)
smoothingInput = input.string(title="Smoothing", defval="RMA", options = ["RMA", "SMA", "EMA", "WMA"])

maFunction(source, length) =>
    switch smoothingInput
        "RMA" => ta.rma(source, length)
        "SMA" => ta.sma(source, length)
        "EMA" => ta.ema(source, length)
        => ta.wma(source, length)

plot(maFunction(ta.tr(true), lengthInput), title = "ATR", color=#B71C1C)

Коллекции объектов рисования

Значительное улучшение качества жизни для тех, кто работает с объектами рисования в Pine: новые переменные line.all, label.all, box.all и table.all возвращают массив, наполненный ссылками на все нарисованные на графике линии, лейблы, прямоугольники и таблицы соответственно.

Это можно использовать, например, чтобы ограничить количество объектов рисования на графике на основе значения, заданного в настройках индикатора. В скрипте ниже мы рисуем линию на цене открытия каждого дня (до ~50 линий — лимит на количество линий по умолчанию). После этого мы проверяем размер массива line.all и, если он превышает разрешённый, удаляем самую старую линию в массиве:

//@version=5
indicator("Daily Open", overlay = true)

qtyOfLinesInput = input.int(10, "Draw only last n lines", minval = 0, maxval = 50)

if ta.change(time("1D"))
    line.new(bar_index, open, bar_index + 1, open, extend = extend.right)
    if array.size(line.all) > qtyOfLinesInput
        line.delete(array.get(line.all, 0))

Цикл while

Еще одна долгожданная функция Pine, добавленная в v5, это циклы while. Оператор while создает цикл, который останавливается, когда условие ложно или когда в цикле используется команда break.

В качестве примера приведем индикатор, который вычисляет разницу между средним расстоянием, на которое нам нужно обратиться в прошлое, чтобы найти объем вверх и вниз, равный общему объему последних n баров. Чем дальше нам нужно обращаться в прошлое, чтобы найти увеличивающийся или падающий объем, тем более медвежьим или бычьим будет его значение:

//@version=5
var int MAX_BARS_BACK = 500
indicator("Volume bias", max_bars_back = MAX_BARS_BACK)

int lookBackInput = input.int(20, "Volume Look Back (bars)", minval = 2, maxval = int(MAX_BARS_BACK / 4))

// Stop script if the chart does not contain volume data.
bool noVol = na(volume) and nz(math.sum(nz(volume), 200) == 0, true)
if noVol
    runtime.error("No volume data.")

volumeBias(_lookBack, _maxLookBack) =>
    bool  _barUp = ta.rising(close, 1)
    bool  _barDn = ta.falling(close, 1)
    float _upVolume = 0.
    float _dnVolume = 0.
    float _avgVolume = math.sum(nz(volume), _lookBack)
    int[] _upBarNos = array.new_int(0)
    int[] _dnBarNos = array.new_int(0)
    int   _bar = 1
    bool  _volumeFound = false
    while (not _volumeFound) and _bar < _maxLookBack
        if _barUp[_bar] and _upVolume < _avgVolume
            _upVolume += nz(volume[_bar])
            array.push(_upBarNos, _bar)
        else if _barDn[_bar] and _dnVolume < _avgVolume
            _dnVolume += nz(volume[_bar])
            array.push(_dnBarNos, _bar)
        _bar += 1
        _volumeFound := _upVolume >= _avgVolume and _dnVolume >= _avgVolume
    float _volumeBias = _bar >= _maxLookBack ? na : array.avg(_dnBarNos) - array.avg(_upBarNos)

float bias = volumeBias(lookBackInput, MAX_BARS_BACK)
plot(bias, "Volume Bias", bias > 0 ? color.lime : color.red)
hline(0)

Цикл while в скрипте выполняется до тех пор, пока не будет найден требуемый объем (как покупки, так и продажи), и пока мы не запрашиваем данные, выходящие за пределы максимально разрешенного количества баров. Скрипт также демонстрирует еще одну функцию, добавленную в Pine v5: runtime.error().

runtime.error()

Функция runtime.error() теперь позволяет останавливать выполнение скрипта и отображать сообщение об ошибке на основе любого условия, которое вы можете определить в Pine. Это пригодится создателям скриптов, которые хотят, чтобы пользователи не использовали их индикаторы некорректно. Функцию runtime.error() также можно использовать как нестандартный инструмент отладки, например, чтобы остановить выполнение скрипта во время цикла или внутри функции.

Чтобы воспользоваться этим функционалом, просто вызовите функцию runtime.error() внутри какого-либо условия. Когда условие будет выполнено и функция вызовется, скрипт остановится и около названия индикатора появится знакомый восклицательный знак. По клику на восклицательный знак появляется сообщение, которое вы задавали при вызове функции.

Приведенный ниже код представляет собой простой индикатор Средневзвешенная цена объёма (VWAP) с двумя пользовательскими ошибками. Первая появляется, когда для символа нет данных об объеме: VWAP рассчитывается на основе объема, поэтому, если объем отсутствует, скрипт не может работать. Второй появляется, когда таймфрейм на графике 1D или выше. Базовые вычисления VWAP накапливают взвешенные по объему скользящие средние на каждом новом баре и сбрасываются в начале нового дня, поэтому индикатор полезен только на внутридневных временных интервалах.

//@version=5
indicator("VWAP with custom errors")
if na(volume) // Will be true on symbols with no volume data e.g. TVC:SPX
    runtime.error("There is no volume data for this symbol.")
else if timeframe.isdwm // Will be true on 1D and higher timeframes
    runtime.error("Session-based VWAP does not show meaningful data on timeframes >= 1D.
     Please switch to a lower timeframe.")
plot(ta.vwap)

Новые функции для работы со стратегиями

Хорошие новости для любителей стратегий! Мы добавили целый ряд новых переменных и функций, которые позволяют вам запрашивать свойства, статистику и показатели сделок. Их значения обновляются по мере того, как эмулятор брокера выполняет ваши заказы, поэтому вы можете следить за значениями на протяжении всего графика, где стратегия торгуется.

Нажмите здесь, чтобы получить подробную информацию о каждой функции и переменной

strategy.closedtrades.entry_price() / strategy.opentrades.entry_price()

strategy.closedtrades.entry_bar_index() / strategy.opentrades.entry_bar_index()

strategy.closedtrades.entry_time() / strategy.opentrades.entry_time()

strategy.closedtrades.size() / strategy.opentrades.size()

strategy.closedtrades.profit() / strategy.opentrades.profit()

strategy.closedtrades.commission() / strategy.opentrades.commission()

strategy.closedtrades.max_runup() / strategy.opentrades.max_runup()

strategy.closedtrades.max_drawdown() / strategy.opentrades.max_drawdown()

strategy.closedtrades.exit_price()

strategy.closedtrades.exit_bar_index()

strategy.closedtrades.exit_time()

strategy.convert2account()

strategy.convert2symbol()

strategy.account_currency

 

Новые пространства имён

Кодеры из сообщества программистов Pine говорят нам, что ценят беспрецедентное количество нововведений, которые мы внесли в Pine за последние несколько лет, и мы не намерены останавливаться. Однако, при таком темпе Pine постоянно пополняется новыми функциями и встроенными переменными. Чтобы в будущем с языком было проще работать, мы решили реорганизовать все ~600 встроенных функций/переменных, которые доступны в языке. Для этого мы добавили новые пространства имен и сгруппировали уже существующие функции таким образом, чтобы лучше отразить их использование.

Мы понимаем, что изменения имен причиняют неудобство кодерам, использовавшим предыдущие версии Pine, но они необходимы для упорядоченного развития языка, и мы предприняли шаги, чтобы адаптироваться было проще: в случаях, когда новое пространство имен было вставлено перед именем функции, а само имя не поменялось в рамках v5, редактор Pine предложит полное имя v5 для функции, когда вы введете ее старое имя.

Примером нового пространства имен является ta., которое теперь включает все переменные и функции, связанные с техническим анализом. Это упрощает просмотр Справочного руководства и поиск всех переменных и функций, возвращающих значения частоупотребляемых индикаторов. Соответственно, sma() теперь называется ta.sma(), но если вы наберете в редакторе просто «sma», он подскажет новое имя. Многие имена параметров функций также были переименованы, чтобы их было легче понять.

Вы можете увидеть полный список изменений на нашей странице руководства пользователя, которая документирует все изменения в Pine v5.

Примеры библиотек

Приведённые ниже публикации — примеры библиотек, опубликованные на TradingView разработчиками группы PineCoders, которые помогают нам тестировать новый функционал Pine:

ColorScheme by RicardoSantos

Matrix_Functions_Lib_JD by Duyck


Enchanced_ta by HeWhoMustNotBeNamed

Надеемся, что новые функции окажутся для вас полезными. Продолжайте присылать нам отзывы и предложения — мы создаем TradingView для вас и рады узнать, что вы думаете об обновлениях нашей платформы.

Look first Then leap

Мы создали TradingView, чтобы вы могли пользоваться самыми крутыми функциями.
Открыть график