Автоматический конвертер — старт, а не доказательство корректности. Pine v6 меняет систему типов и отдельные правила исполнения. Код может успешно компилироваться и при этом давать другой набор сигналов, заявок или запрошенных данных.
Главные изменения в одной таблице
| Область | Было в v5 | Стало в v6 | Риск при переносе |
|---|---|---|---|
| Число в bool-контексте | Допускалось неявное приведение | Нужен явный bool() или сравнение |
Ошибка компиляции |
| Значение bool | true, false, na |
Только true или false |
Потеря третьего состояния |
and и or |
Операнды могли вычисляться заранее | Ленивое вычисление | Побочный вызов может не выполниться |
request.*() |
По умолчанию статические | По умолчанию динамические | Другой контекст данных |
strategy.*(when=...) |
Параметр использовался | Параметр удален | Нужно условное ветвление |
| Маржа стратегии | Старые defaults | Long и short по умолчанию 100% | Меняется доступный размер позиции |
| Деление const int | Могло давать целое | Может вернуть дробное | Меняется формула |
| Лимит сделок | Ошибка после 9000 | Старые сделки обрезаются | История результатов меняется |
Полный перечень и примеры опубликованы в официальном руководстве по переходу на Pine Script v6. Перед работой сохраните исходную v5-версию отдельно.
Как запускать миграцию
Pine Editor конвертирует только v5-код, который уже компилируется. Исправьте старые ошибки до перехода, затем выберите Convert code to v6 в меню управления скриптом.
Рабочий порядок:
- сделайте копию v5 под новым именем;
- зафиксируйте настройки inputs и свойства стратегии;
- выгрузите список сделок или сделайте контрольные скриншоты;
- запустите конвертер;
- устраните ошибки компиляции по одной группе;
- сравните значения ключевых series на одних барах;
- сравните входы, выходы и размер позиции;
- только после этого заменяйте опубликованную версию.
Bool больше не бывает na
В v5 логика могла различать true, false и na. Например, направление позиции до первого входа было неизвестно. В v6 неизвестный boolean превращается в false, а na(), nz() и fixnan() больше не принимают bool.
Старый замысел:
true = long
false = short
na = позиции нет
В v6 его лучше выразить числом:
//@version=6
int direction = if strategy.position_size > 0
1
else if strategy.position_size < 0
-1
else
0
Это не косметическая правка. Если просто удалить проверку na, состояние «нет позиции» смешается с short и может покрасить фон, включить алерт или вызвать выход не в тот момент.
Числа также больше не приводятся к bool неявно. Вместо if bar_index пишите конкретное условие: if bar_index > 0. Явное сравнение читается лучше, чем bool(bar_index), потому что сообщает намерение.
Ленивые and и or
В v6 правая часть and вычисляется только когда левая истинна, а правая часть or — только когда левая ложна. Это стандартное короткое замыкание и позволяет безопасно проверять границы:
bool hasPrevious = bar_index > 0 and close[1] > open[1]
Но код с расчетом или изменением состояния внутри функции справа может повести себя иначе. Функции, от которых зависит series, лучше вычислять заранее и сохранять в переменную:
float average = ta.sma(close, 20)
bool signal = enabled and close > average
Так серия средней строится на каждом баре, а условие остается прозрачным.
Динамические request.* по умолчанию
В v6 request.security() и другие request.*() могут использовать series-аргументы для символа и таймфрейма, выполняться в циклах и локальных блоках. Компилятор отключает динамический режим, когда он не требуется.
Это упрощает мультисимвольные индикаторы, но повышает требования к проверке:
- какие наборы данных реально запрашиваются;
- доступна ли история для всех символов;
- нет ли будущих данных через lookahead;
- одинаково ли ведет себя вложенный запрос;
- укладывается ли скрипт в лимиты уникальных запросов.
Если v5-скрипт после конвертации получает другие значения, официальный migration guide предлагает для диагностики явно поставить dynamic_requests = false, когда структура кода это допускает. Не оставляйте флаг только ради совпадения: сначала поймите, какой контекст изменился.
Изменения стратегий
Параметр when удален
Вместо:
strategy.entry("Long", strategy.long, when = longCondition)
используйте:
if longCondition
strategy.entry("Long", strategy.long)
Отдельный блок проще отлаживать и расширять проверками сессии, риска и состояния позиции.
Маржа по умолчанию стала 100%
Если v5-тест не задавал margin_long и margin_short, результат v6 может измениться. Зафиксируйте свойства стратегии явно и сравнивайте одинаковые настройки. Не подгоняйте маржу под красивую кривую — она должна отражать реальный счет и правила инструмента.
strategy.exit обрабатывает относительные и абсолютные параметры иначе
В v6 вызов больше не игнорирует относительные параметры автоматически, когда одновременно заданы связанные абсолютные. Код с profit и limit, loss и stop, trailing-параметрами нужно просмотреть вручную. Один выход должен иметь однозначную модель цены.
Старые ордера обрезаются после лимита
Вместо ошибки при превышении 9000 сделок стратегия удаляет самые старые из отчета. Это удобнее для длинного теста, но начало выборки становится подвижным. Записывайте фактический диапазон сделок, а не только даты графика.
Подробнее модель стратегий, комиссии, проскальзывание и Bar Magnifier описаны в официальной документации Strategies.
Другие несовместимости, которые легко пропустить
Деление констант
Результат деления двух const int может стать дробным. Проверьте вычисления периодов, долей и индексов. Если нужен целый результат, выразите округление явно.
timeframe.period всегда содержит множитель
Дневной период возвращается как 1D, а не D. Сравнения строк и формирование ключей нужно обновить.
transp удален
Прозрачность задается через color.new(baseColor, transparency). Это обычно механическая правка, но динамический цвет удобнее вычислить один раз.
Уникальные типы не принимают na
Параметры вроде стиля plot должны получать конкретную константу. if требует ветку else, а switch — fallback, если иначе могло получиться na.
Граница for пересчитывается
Конечное значение цикла теперь может оцениваться перед каждой итерацией. Не меняйте внутри цикла коллекцию, от размера которой зависит граница, без явного плана завершения.
Как проверить эквивалентность v5 и v6
Не начинайте с чистой прибыли. Итоговая цифра скрывает место первого расхождения.
Сравнивайте слоями:
- исходные OHLCV и requested series;
- промежуточные индикаторы;
- логические условия;
- номера баров сигналов;
- цену и время моделируемого исполнения;
- размер позиции;
- комиссии и проскальзывание;
- итоговые метрики.
Временно выводите расхождение через plot, label или table. Первый бар, где значения разошлись, обычно указывает на конкретное изменение языка. Если сигналы меняются после перезагрузки, дополнительно проверьте причины перерисовки. Если отчет стратегии выглядит слишком хорошо, используйте чек-лист ошибок бэктестинга.
Стоит ли переводить старый рабочий скрипт
Оставить v5 разумно, когда скрипт стабилен, критичен для работы и не требует функций v6. Новую разработку лучше начинать с v6: актуальная документация и примеры ориентированы на него.
Миграция оправдана, если нужны динамические запросы, новые возможности языка или дальнейшая поддержка кода. Планируйте ее как небольшой релиз: копия, тестовый набор, сравнение и журнал изменений.
Официальные изменения продолжают выходить, поэтому перед использованием новой функции сверяйтесь с release notes Pine Script, а не с устаревшим примером из форума.
Вывод
Самые рискованные изменения v6 находятся в поведении, а не в строке //@version=6. Bool потерял третье состояние, запросы стали динамическими, логические операторы — ленивыми, а стратегия получила новые defaults. Автоконвертер экономит ручную работу, но эквивалентность подтверждается только послойным сравнением на одинаковых данных.
