Кастомный ZigZag с фильтрацией по объему в Pine Script v5

Кастомный ZigZag с фильтрацией по объему в Pine Script v5 Pine Script
Пошаговое руководство по созданию кастомного индикатора ZigZag с фильтрацией по объему на Pine Script v5 с использованием динамических массивов.
Суть: Мы реализуем профессиональный индикатор ZigZag на Pine Script v5, который фильтрует ложные ценовые колебания, анализируя накопленный объем внутри каждого колена (leg). Для динамического управления точками разворота и отрисовки линий используются встроенные массивы (array).

Стандартный индикатор ZigZag в TradingView учитывает исключительно ценовое движение (процентное или абсолютное отклонение). Однако в реальном трейдинге движение цены без поддержки крупного объема часто оказывается ложным пробоем или рыночным шумом. Фильтрация колен зигзага по совокупному объему позволяет выделить истинные трендовые движения институциональных игроков.

Использование динамических массивов в Pine Script v5 позволяет гибко управлять историей экстремумов, перезаписывать координаты незавершенных колен и оптимизировать нагрузку на графический движок платформы.

Исходный код

Ниже представлен готовый код индикатора для Pine Script v5. Скрипт накапливает объем текущего колена и сравнивает его со средним ожидаемым объемом за аналогичный период. Если объем не подтвержден, новое колено зигзага не строится.

//@version=5
indicator('Custom Volume-Filtered ZigZag (Arrays)', overlay=true, max_lines_count=500)

// Входные параметры
depth = input.int(10, 'Минимальный шаг (Depth)', minval=2)
deviation = input.float(1.0, 'Отклонение (%)', minval=0.1, step=0.1)
vol_mult = input.float(1.2, 'Мультипликатор объема колена', minval=0.1, step=0.1)
vol_len = input.int(50, 'Период базового объема', minval=1)

// Инициализация массивов для хранения точек ZigZag
var int[] pivot_bars = array.new_int(0)
var float[] pivot_vals = array.new_float(0)
var int[] pivot_dirs = array.new_int(0) // 1: Максимум, -1: Минимум
var line[] zz_lines = array.new_line(0)

// Накопление объема текущего колена
var float leg_volume = 0.0
leg_volume := leg_volume + volume

// Поиск локальных экстремумов (сдвиг на depth для подтверждения)
p_high = ta.highest(high, depth)[depth] == high[depth]
p_low = ta.lowest(low, depth)[depth] == low[depth]

// Базовый средний объем
avg_vol = ta.sma(volume, vol_len)

// Функция для добавления новой точки и отрисовки линии
add_pivot(int p_bar, float p_val, int p_dir) =>
    array.push(pivot_bars, p_bar)
    array.push(pivot_vals, p_val)
    array.push(pivot_dirs, p_dir)
    if array.size(pivot_bars) > 1
        int prev_idx = array.size(pivot_bars) - 2
        line l = line.new(
          x1=array.get(pivot_bars, prev_idx),
          y1=array.get(pivot_vals, prev_idx),
          x2=p_bar,
          y2=p_val,
          color=p_dir == 1 ? color.green : color.red,
          width=2
         )
        array.push(zz_lines, l)

// Логика обновления и построения колен ZigZag
if barstate.isconfirmed
    if array.size(pivot_dirs) == 0
        if p_high
            add_pivot(bar_index - depth, high[depth], 1)
            leg_volume := 0.0
        else if p_low
            add_pivot(bar_index - depth, low[depth], -1)
            leg_volume := 0.0
    else
        int last_dir = array.get(pivot_dirs, array.size(pivot_dirs) - 1)
        int last_bar = array.get(pivot_bars, array.size(pivot_bars) - 1)
        float last_val = array.get(pivot_vals, array.size(pivot_vals) - 1)

        // Расчет ожидаемого объема для текущей длины колена
        int leg_len = bar_index - depth - last_bar
        float expected_vol = (leg_len > 0 ? ta.sma(volume, vol_len)[depth] * leg_len : avg_vol * depth) * vol_mult

        if last_dir == 1 // Предыдущий был Максимум, ищем Минимум
            if p_low
                float price_dev = ((last_val - low[depth]) / last_val) * 100
                if price_dev >= deviation and leg_volume >= expected_vol
                    add_pivot(bar_index - depth, low[depth], -1)
                    leg_volume := 0.0
            else if p_high and high[depth] > last_val // Обновляем текущий максимум, если цена ушла выше
                array.set(pivot_bars, array.size(pivot_bars) - 1, bar_index - depth)
                array.set(pivot_vals, array.size(pivot_vals) - 1, high[depth])
                if array.size(zz_lines) > 0
                    line.set_x2(array.get(zz_lines, array.size(zz_lines) - 1), bar_index - depth)
                    line.set_y2(array.get(zz_lines, array.size(zz_lines) - 1), high[depth])

        else // Предыдущий был Минимум, ищем Максимум
            if p_high
                float price_dev = ((high[depth] - last_val) / last_val) * 100
                if price_dev >= deviation and leg_volume >= expected_vol
                    add_pivot(bar_index - depth, high[depth], 1)
                    leg_volume := 0.0
            else if p_low and low[depth] < last_val // Обновляем текущий минимум, если цена ушла ниже
                array.set(pivot_bars, array.size(pivot_bars) - 1, bar_index - depth)
                array.set(pivot_vals, array.size(pivot_vals) - 1, low[depth])
                if array.size(zz_lines) > 0
                    line.set_x2(array.get(zz_lines, array.size(zz_lines) - 1), bar_index - depth)
                    line.set_y2(array.get(zz_lines, array.size(zz_lines) - 1), low[depth])

Разбор параметров

  • depth: Минимальное количество баров между локальными экстремумами. Задает базовый шаг для поиска потенциальных разворотов.
  • deviation: Минимальное процентное изменение цены, необходимое для фиксации нового колена ZigZag. Защищает от мелкого флета.
  • vol_mult: Коэффициент фильтрации по объему. Суммарный объем за время формирования колена должен превысить средний объем за этот же период, умноженный на данный коэффициент.
  • vol_len: Период скользящей средней (ta.sma) объема для расчета базовой рыночной активности.

Как запустить

Чтобы запустить данный индикатор на платформе TradingView, выполните следующие шаги:

1. Откройте график любого финансового инструмента на TradingView.

2. В нижней части экрана перейдите во вкладку Pine Editor.

3. Полностью удалите стандартный шаблон кода и вставьте скопированный выше скрипт.

4. Нажмите кнопку Add to Chart (Добавить на график) в правом верхнем углу редактора.

После того как кастомный ZigZag определил истинный разворот тренда, вы можете автоматизировать вход в позицию и настроить Частичный Take Profit в Pine Script v5: Пошаговое руководство для фиксации прибыли частями.

Фильтрация по объему — это классический подход VSA (Volume Spread Analysis). Если вам интересны другие методы взвешивания рыночных данных по объему, рекомендуем изучить построение VWMA с кастомными весами через матрицы в Pine Script v5.

Для мониторинга сигналов и ведения логов пробития экстремумов ZigZag в реальном времени отлично подойдет Интеграция Pine Script v5 с Google Sheets: Webhook для логов сделок.

Оцените статью
FinFluct