Массивы Pine Script: индексы и операции на примере

Обложка статьи «Массивы Pine Script: индексы и операции на примере»: Три ячейки очереди стоят в ряд. Слева пунктиром показано самое старое значение, которое уходит, справа пунктиром новое, которое встаёт в конец.

Чем массив отличается от ряда значений

Ряд хранит по одному значению на каждый бар истории, а массив держит много значений сразу на одном баре. Руководство TradingView описывает это так: ряд похож на горизонтальную линию значений, уходящую в прошлое, а массив - на вертикальную структуру, которая стоит на каждом баре. Бар здесь - одна свеча выбранного таймфрейма.

Из этого следуют три отличия, на которых чаще всего спотыкаются.

  • Квадратные скобки работают иначе. Запись close[1] берёт закрытие на один бар раньше текущего. К элементу массива так не обратиться: по руководству, оператора индексации для элементов в языке нет, их читают и пишут функциями.
  • Обычная математика к массиву не подходит. Набор элементов не является временным рядом, поэтому привычные функции расчёта к нему не применяют. Для массивов есть свои, например array.avg() для среднего.
  • Тип один на весь массив. Все элементы должны быть одного типа: только числа, только строки и так далее. Размер тоже ограничен: в одном массиве не больше 100 тысяч элементов.

Устройство языка в целом разобрано в руководстве Pine Script: что это за язык.

Как читать и менять элементы по индексу

Элемент читают вызовом array.get(id, index), а меняют вызовом array.set(id, index, value). Индекс первого элемента равен 0, индекс последнего равен размеру массива минус один.

Возьмём массив prices из трёх чисел: 102, 101, 104.

  • array.get(prices, 0) даёт 102, это первый элемент.
  • Последний элемент, 104, читается вызовом array.get(prices, 2).
  • array.size(prices) вернёт 3. Это число элементов, последний индекс на единицу меньше.
  • array.set(prices, 1, 103) заменит 101 на 103. Массив станет [102, 103, 104], размер останется 3.

В руководстве для шестой версии языка описан и отрицательный индекс: -1 указывает на последний элемент. Запись array.get(prices, -1) в нашем примере вернёт те же 104.

Не путайте индекс элемента со смещением по истории. Запись prices[1] второй элемент не достанет. Это обращение к истории переменной: она вернёт тот массив, который был записан в prices на прошлом баре. Чем шестая версия отличается от пятой, читайте в ответе Pine Script v5 и v6: что изменилось.

Очередь из трёх цен: push и shift по шагам

Такую очередь собирают двумя функциями: array.push() добавляет новое закрытие в конец, а array.shift() убирает самое старое из начала. Такой порядок называют FIFO: первым пришёл, первым ушёл.

//@version=6
indicator("Очередь из трёх цен")
var prices = array.new<float>(0)
array.push(prices, close)
if array.size(prices) > 3
    array.shift(prices)
plot(array.avg(prices))

Пройдём этот код вручную на четырёх учебных барах с закрытиями 100, 102, 101 и 104. Это ручная трассировка по правилам руководства. В редакторе пример мы не запускали.

Бар и закрытиеЧто делает кодМассив после бара
Первый, 100push добавил 100[100]
Второй, 102push добавил 102[100, 102]
Третий, 101push добавил 101[100, 102, 101]
Четвёртый, 104push добавил 104, shift вернул 100[102, 101, 104]

На четвёртом баре размер на мгновение стал равен 4, условие сработало, и shift убрал самое старое закрытие. Среднее по трём оставшимся: (102 + 101 + 104) / 3 = 307 / 3 = 102,33.

Учебный пример: очередь хранит три последних закрытия

учебная схема · не котировка и не сигнал

Четыре бара, закрытия подписаны

Четыре бара, закрытия подписаны1100102101104

Очередь после бара 4, индексы

Очередь после бара 4, индексы2. Среднее012
  1. 1Закрытие 100 пришло первым и первым ушло: на четвёртом баре его убрал shift
  2. 2Среднее трёх оставшихся закрытий: 307 / 3 = 102,33. Индекс 0 у самого старого из них, индекс 2 у самого нового
Схема учебная, цены вымышленные. Слева четыре бара с закрытиями 100, 102, 101 и 104. Справа те три закрытия, что остались в очереди после четвёртого бара, с их индексами.

Здесь два места, где легко ошибиться.

Первое - слово var. Оно создаёт массив один раз, и его содержимое сохраняется от бара к бару. Без var на каждом баре появлялся бы новый пустой массив. После push в нём был бы один элемент, и очередь никогда не набрала бы три цены.

Второе - направление счёта. В очереди индекс 0 у самого старого закрытия, 102. У ряда всё наоборот: close[0] даёт текущий бар, то есть 104. Одинаковая цифра в скобках у массива и у ряда означает разные вещи.

Как вывести длину очереди в настройки индикатора, показано в ответе input в Pine Script.

Почему возникает ошибка выхода за границы

Ошибка появляется, когда код просит элемент с индексом, которого в массиве нет. Руководство TradingView называет её самой частой ошибкой при работе с массивами. Сообщение выглядит так: «Index xx is out of bounds. Array size is yy», где на месте xx стоит запрошенный индекс, а на месте yy размер массива.

В нашей очереди после четвёртого бара три элемента с индексами 0, 1 и 2. Вызов array.get(prices, 3) выходит за границы: четвёртого элемента нет. Чаще всего к этому приводят три ситуации.

  • Индекс равен размеру. Последний элемент читают как array.get(prices, array.size(prices) - 1), а не как array.get(prices, array.size(prices)).
  • Массив ещё не наполнен. На первом баре в очереди один элемент. Запрос array.get(prices, 2) допустим только с третьего бара.
  • Массив пуст. Если в массив ещё ничего не добавили или элементы удалены, размер равен 0, и любой индекс окажется лишним.

Защита одна: перед чтением сравнить индекс с размером.

float last = na
if array.size(prices) > 2
    last := array.get(prices, 2)

Риски и ограничения. Цены в примере и на схеме вымышленные, это учебная трассировка, а не рыночные данные и не результат запуска скрипта. Код собран по руководству для шестой версии Pine Script. Перед работой сохраните его в редакторе и убедитесь, что он компилируется без ошибок. Отрицательные индексы и запись array.new<float>(0) сверены только с руководством шестой версии. Правила языка сверены 07.10.2026 и могут меняться. Массив помогает хранить и считать значения, но не делает расчёт прибыльным и не гарантирует прибыль. Любой индикатор - инструмент анализа, а не сигнал к сделке. Рынок волатилен, торговля связана с риском потери капитала, прошлые данные не говорят о будущих. Материал образовательный, это не индивидуальная инвестиционная рекомендация.

Источники

График TradingView с сигналами Buy и Sell индикатора Midas
Midas multi-индикатор for TradingViewОдин из самых продвинутых индикаторов для трейдинга
  • Сигналы без перерисовки
  • Интерактивный теханализ
  • 7 стратегий на выбор
Midas multi-индикатор for TradingViewСигнал, стоп и 3 цели - прямо на графике
  • Сигнал фиксируется по закрытию свечи
  • Стоп и 3 цели строятся автоматически
  • План сделки виден до входа