← К каталогу
Исходный код · ID 4666

Smart Volume Tactician

smart volume-based tactician (1).pine
Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

Индикатор TradingView на Pine Script v6, отображаемый поверх графика. Он рассчитывает технические показатели и выводит линии и графические отметки, а также задаёт условия для оповещений TradingView.

В коде реализованы сессионные боксы и профиль объёма с уровнями POC, VAH и VAL, зоны LVN/HVN и Single Prints, а также ордер-блоки на основе пивотов. Пользователь может выбирать тип сессии и метод её расчёта, настраивать разрешение профиля, процент объёма Value Area, режим отображения баров и сглаживание объёма.

Отдельные группы настроек управляют уровнями Фибоначчи, внешним видом линий и боксов, а также порогами и цветами зон LVN/HVN. Предусмотрены условия оповещений для пересечения уровней профиля объёма, входа в зоны LVN/HVN/NPOC, касания ордер-блоков и пользовательского уровня Фибоначчи, а также для сигналов разворота у ключевых уровней.

Индикатор не является автоматическим советником и не выполняет симуляцию сделок в тестере.

Настройки программы

НастройкаОписание
maxLookbackBars Максимальное количество баров для анализа; уменьшение повышает производительность на младших таймфреймах.
enableComplexCalculations Включает сложные расчёты зон LVN/HVN; отключение повышает производительность.
sessionType Выбор типа сессии для расчёта и отображения.
sessionCalcMethod Метод расчёта границ сессии: начинать с чистого листа или учитывать предыдущую сессию.
showDisclaimer Показывает предупреждение об ограничениях сессий на младших таймфреймах.
showLvnHvn Закрашивает зоны на основе объёмных узлов LVN/HVN.
showSinglePrints Показывает небольшие разрывы объёма внутри Value Area.
lvnThreshold Порог объёма для определения зон LVN.
hvnThreshold Порог объёма для определения зон HVN.
singlePrintThreshold Порог для обнаружения Single Prints внутри Value Area.
lvnColor Цвет фона зон LVN ниже VAL.
hvnColor Цвет фона зон HVN выше VAH.
singlePrintColor Цвет фона Single Prints внутри Value Area.
showLvnHvnLabels Показывает текстовые метки для зон LVN и HVN.
lvnHvnTransparency Базовая прозрачность фона зон LVN/HVN.
lvnHvnWidth Ширина зон LVN/HVN.
source Источник для расчёта ордер-блоков: фитили или тела свечей.
leftLenH Количество баров слева для поиска пивота High.
rightLenH Количество баров справа для поиска пивота High.
leftLenL Количество баров слева для поиска пивота Low.
rightLenL Количество баров справа для поиска пивота Low.
bullBoxColor Цвет бычьих ордер-блоков.
bearBoxColor Цвет медвежьих ордер-блоков.
closedBoxColor Цвет закрытых ордер-блоков.
extendBox Продлевает ордер-блоки до момента касания ценой.
boxLength Длина ордер-блока, если расширение отключено.
enableVPAlerts Включает оповещения при пересечении POC, VAH или VAL.
enableOBAlerts Включает оповещения при входе в зоны ордер-блоков.
enableFibAlerts Включает оповещения при пересечении пользовательского уровня Фибоначчи.
enableLvnHvnAlerts Включает оповещения при входе в зоны LVN, HVN или NPOC.
enableSignalAlerts Включает оповещения при срабатывании сигналов покупки и продажи.
customFibLevel Пользовательский уровень Фибоначчи для оповещений в диапазоне от 0.0 до 1.0.
alertFrequency Частота срабатывания оповещений: на закрытии бара или на каждом баре.
enableSignals Включает отображение сигналов на ключевых уровнях.
signalMinCandleSize Минимальный размер свечи установки относительно ATR.
signalReversalThreshold Процент свечи установки, который должен быть отыгран для подтверждения разворота.
signalLevelTolerance Допуск близости цены к ключевому уровню для срабатывания сигнала, в процентах от цены.
showProf Показывает профиль объёма.
showSbox Показывает сессионный бокс.
showPoc Показывает линию POC.
showVA Показывает линии VAH и VAL.
showVAb Показывает бокс Value Area.
showCur Показывает текущую зону.
showLabels Показывает метки сессий.
showFx Показывает боксы сессий Форекс без профиля объёма.
extendLines Продлевает линии VAL, VAH и POC.
showFib Показывает уровни Фибоначчи.
extendFibLines Продлевает линии уровней Фибоначчи.
resolution Разрешение расчёта профиля объёма; меньшее значение повышает производительность.
VAwid Процент объёма, используемый для расчёта Value Area.
dispMode Режим отображения баров профиля объёма: Mode 1 или Mode 2.
smoothVol Сглаживает данные объёма для построения профиля.
showMode12Percentages Показывает процентное соотношение быков и медведей на объёмных узлах в режимах Mode 1 и Mode 2.
mode12TextDistance Расстояние процентного текста от объёмных узлов в режимах Mode 1 и Mode 2.
showFibPrices Показывает цены на уровнях Фибоначчи.
showFibLevels Показывает линии уровней Фибоначчи.
fibLevelsFormat Формат отображения уровней Фибоначчи: значения или проценты.
fibLabelsPosition Позиция меток уровней Фибоначчи: слева или справа.
fibColor Цвет линий и меток уровней Фибоначчи.
autoFibDirection Автоматически определяет направление построения уровней Фибоначчи.
show_fib_0 Включает отображение уровня Фибоначчи 0%.
color_fib_0 Цвет линии уровня Фибоначчи 0%.
show_fib_236 Включает отображение уровня Фибоначчи 23.6%.
color_fib_236 Цвет линии уровня Фибоначчи 23.6%.
show_fib_382 Включает отображение уровня Фибоначчи 38.2%.
color_fib_382 Цвет линии уровня Фибоначчи 38.2%.
show_fib_50 Включает отображение уровня Фибоначчи 50%.
color_fib_50 Цвет линии уровня Фибоначчи 50%.
show_fib_618 Включает отображение уровня Фибоначчи 61.8%.
color_fib_618 Цвет линии уровня Фибоначчи 61.8%.
show_fib_650 Включает отображение уровня Фибоначчи 65%.
color_fib_650 Цвет линии уровня Фибоначчи 65%.
show_fib_786 Включает отображение уровня Фибоначчи 78.6%.
color_fib_786 Цвет линии уровня Фибоначчи 78.6%.
show_fib_886 Включает отображение уровня Фибоначчи 88.6%.
color_fib_886 Цвет линии уровня Фибоначчи 88.6%.
show_fib_100 Включает отображение уровня Фибоначчи 100%.
color_fib_100 Цвет линии уровня Фибоначчи 100%.
bullCol Цвет отображения объёма вверх.
bearCol Цвет отображения объёма вниз.
VAbCol Цвет фона бокса Value Area.
pocCol Цвет линии POC.
pocWid Толщина линии POC.
vahCol Цвет линии VAH.
vahWid Толщина линии VAH.
valCol Цвет линии VAL.
valWid Толщина линии VAL.
boxBg Цвет фона сессионного бокса.
boxWid Толщина границы сессионного бокса.
Получить полный код

Поиск по коду файла

indicator('<[$/Умный тактик на основе объемов/$]>', shorttitle = '<[$/Smart Volume Tactician/$]>', overlay = true, max_bars_back = 1000, max_boxes_count = 500, max_lines_count = 200)

performanceGroup = '=== Настройки производительности ==='
maxLookbackBars = input.int(1000, 'Макс. баров для анализа', minval = 10, maxval = 2000, step = 100, group = performanceGroup, tooltip = 'Уменьшите для лучшей производительности на младших ТФ')
enableComplexCalculations = input.bool(true, 'Включить сложные расчеты LVN/HVN', group = performanceGroup, tooltip = 'Отключите для лучшей производительности при необходимости')

sessionType = input.string('Daily', 'Тип сессии', options = ['Sydney', 'Tokyo', 'Asian', 'Frankfurt', 'London', 'European', 'New York', 'US Extended', 'Asia-London Overlap', 'London-NY Overlap', 'Daily', 'Weekly', 'Monthly', 'Quarterly', 'Yearly'])
sessionCalcMethod = input.string('Include Previous Session', 'Метод расчета сессии', options = ['Start Fresh', 'Include Previous Session'], tooltip = 'Start Fresh: Начинать расчеты с начала сессии | Include Previous Session: Учитывать предыдущую сессию для лучшего распределения (предотвращает скопление в начале сессии)')
showDisclaimer = input.bool(true, 'Показывать предупреждение', tooltip = 'Отображать важные предупреждения об ограничениях сессий на младших ТФ')

lvnHvnGroup = '=== Настройки зон LVN/HVN ==='
showLvnHvn = input.bool(true, 'Показывать зоны LVN/HVN', group = lvnHvnGroup, tooltip = 'Закрашивать зоны на основе объемных узлов')
showSinglePrints = input.bool(true, 'Показывать Single Prints (разрывы внутри VA)', group = lvnHvnGroup, tooltip = 'Показывать небольшие разрывы объема внутри Value Area - зоны заполнения')
lvnThreshold = input.float(0.5, 'Порог LVN', minval = 0.1, maxval = 0.9, step = 0.1, group = lvnHvnGroup, tooltip = 'Порог объема для Low Volume Nodes - зоны НИЖЕ VAL, где цена может провалиться')
hvnThreshold = input.float(0.2, 'Порог HVN', minval = 0.1, maxval = 1.5, step = 0.1, group = lvnHvnGroup, tooltip = 'Порог объема для High Volume Nodes - зоны ВЫШЕ VAH (зоны сопротивления) - меньше = чувствительнее')
singlePrintThreshold = input.float(0.3, 'Порог Single Print', minval = 0.1, maxval = 0.8, step = 0.1, group = lvnHvnGroup, tooltip = 'Порог для обнаружения Single Prints внутри Value Area')
lvnColor = input.color(color.new(#00FF00, 70), 'Цвет LVN', group = lvnHvnGroup, tooltip = 'Цвет фона для Low Volume зон ниже VAL - "GO" зоны для импульса')
hvnColor = input.color(color.new(#FF0000, 85), 'Цвет HVN', group = lvnHvnGroup, tooltip = 'Цвет фона для High Volume зон выше VAH - "STOP" зоны с сопротивлением')
singlePrintColor = input.color(color.new(color.blue, 80), 'Цвет Single Print', group = lvnHvnGroup, tooltip = 'Цвет фона для Single Prints внутри Value Area - зоны заполнения')
showLvnHvnLabels = input.bool(true, 'Показывать метки LVN/HVN', group = lvnHvnGroup, tooltip = 'Отображать текстовые метки для зон LVN и HVN')
lvnHvnTransparency = input.int(70, 'Прозрачность фона', minval = 0, maxval = 95, step = 5, group = lvnHvnGroup, tooltip = 'Базовая прозрачность - градиенты показывают уровни объема внутри каждой зоны')
lvnHvnWidth = input.float(1.5, 'Ширина зон LVN/HVN', minval = 0.5, maxval = 3.0, step = 0.1, group = lvnHvnGroup, tooltip = 'Контролирует ширину зон LVN/HVN. Меньше = уже зоны')

orderBlocksGroup = '=== Ордер Блоки ==='
source = input.string('Wicks', options = ['Wicks', 'Bodys'], title = 'Источник', group = orderBlocksGroup)

leftLenH = input.int(title = 'Pivot High', defval = 25, minval = 1, inline = 'Pivot High', group = orderBlocksGroup)
rightLenH = input.int(title = '/', defval = 25, minval = 1, inline = 'Pivot High', group = orderBlocksGroup)

leftLenL = input.int(title = 'Pivot Low', defval = 25, minval = 1, inline = 'Pivot Low', group = orderBlocksGroup)
rightLenL = input.int(title = '/', defval = 25, minval = 1, inline = 'Pivot Low', group = orderBlocksGroup)

bullBoxColor = input.color(color.new(#00FF00, 50), title = 'Цвет бычьих', group = orderBlocksGroup, inline = '1')
bearBoxColor = input.color(color.new(#FF0000, 50), title = 'Цвет медвежьих', group = orderBlocksGroup, inline = '1')
closedBoxColor = input.color(color.new(color.gray, 90), title = 'Закрытые', group = orderBlocksGroup, inline = '1')

extendBox = input.bool(true, title = 'Расширять блоки', group = orderBlocksGroup, tooltip = 'Расширять блоки до момента касания ценой')
boxLength = input.int(30, title = 'Размер блока', tooltip = 'Если расширение отключено, блоки будут отрисованы этой длины', group = orderBlocksGroup)

alertGroup = '=== Настройки алертов ==='
enableVPAlerts = input.bool(true, 'Алерты Volume Profile', group = alertGroup, tooltip = 'Алерты при пересечении POC, VAH или VAL (включает комплексные данные рынка)')
enableOBAlerts = input.bool(true, 'Алерты Ордер Блоков', group = alertGroup, tooltip = 'Алерты при входе в зоны ордер блоков (включает комплексные данные рынка)')
enableFibAlerts = input.bool(true, 'Алерты Fib уровней', group = alertGroup, tooltip = 'Алерты при пересечении пользовательского уровня Фибоначчи (включает комплексные данные рынка)')
enableLvnHvnAlerts = input.bool(true, 'Алерты LVN/HVN/NPOC', group = alertGroup, tooltip = 'Алерты при входе в зоны LVN, HVN или NPOC')
enableSignalAlerts = input.bool(true, 'Алерты сигналов', group = alertGroup, tooltip = 'Алерты при срабатывании сигналов покупки/продажи')

var bool buySignalAtLevel = false
var bool sellSignalAtLevel = false
customFibLevel = input.float(0.618, 'Пользовательский уровень Fib для алертов', minval = 0.0, maxval = 1.0, step = 0.001, group = alertGroup, tooltip = 'Установите пользовательский уровень Фибоначчи между 0.0 и 1.0')
alertFrequency = input.string('Once Per Bar Close', 'Частота алертов', options = ['Once Per Bar Close', 'Once Per Bar'], group = alertGroup)

signalGroup = '=== Настройки сигналов покупки/продажи ==='
enableSignals = input.bool(true, 'Включить сигналы', group = signalGroup, tooltip = 'Показывать сигналы на ключевых уровнях (зеленые/красные треугольники)')

signalMinCandleSize = input.float(1.5, 'Минимальный размер свечи (умножение ATR)', minval = 0.5, maxval = 5.0, step = 0.1, group = signalGroup, tooltip = 'Минимальный размер свечи установки относительно ATR')
signalReversalThreshold = input.float(50.0, '% разворота свечи', minval = 10.0, maxval = 80.0, step = 5.0, group = signalGroup, tooltip = 'Какой процент свечи установки должен быть отыгран (50% = половина свечи)')
signalLevelTolerance = input.float(0.005, 'Допуск к уровню %', minval = 0.001, maxval = 0.01, step = 0.001, group = signalGroup, tooltip = 'Насколько близко цена должна быть к ключевому уровню для срабатывания сигнала (в процентах от цены)')

showProf = input.bool(true, 'Показывать Volume Profile', group = 'Отображение')
showSbox = input.bool(true, 'Показывать сессионный бокс', group = 'Отображение')
showPoc = input.bool(true, 'Показывать POC', group = 'Отображение')
showVA = input.bool(true, 'Показывать VAH и VAL', group = 'Отображение')
showVAb = input.bool(false, 'Показывать бокс Value Area', group = 'Отображение')
showCur = input.bool(true, 'Показывать текущую зону', group = 'Отображение')
showLabels = input.bool(true, 'Показывать метки сессий', group = 'Отображение')
showFx = input.bool(false, 'Показывать Форекс сессии (без профиля)', group = 'Отображение')
extendLines = input.bool(true, 'Продлевать линии VAL/VAH/POC', group = 'Отображение')
showFib = input.bool(true, 'Показывать уровни Фибоначчи', group = 'Отображение')
extendFibLines = input.bool(false, 'Продлевать линии Фибоначчи', group = 'Отображение')

resolution = input.int(20, 'Разрешение', minval = 5, maxval = 50, tooltip = 'Меньше = лучше производительность. Больше = детальнее профили, но медленнее расчет', group = 'Настройки Volume Profile')
VAwid = input.int(70, '% объема Value Area', minval = 1, maxval = 100, group = 'Настройки Volume Profile')
dispMode = input.string('Mode 2', 'Режим баров', ['Mode 1', 'Mode 2'], group = 'Настройки Volume Profile', tooltip = 'Mode 1: Быки + Медведи рядом с процентами | Mode 2: Быки + Медведи с наложением и процентами (РЕКОМЕНДУЕТСЯ)')
smoothVol = input.bool(false, 'Сглаживать данные объема', tooltip = 'Полезно для активов с большими скачками объема - помогает создавать лучшие профили', group = 'Настройки Volume Profile')

showMode12Percentages = input.bool(true, 'Показывать проценты в Mode 1/2', group = 'Настройки Volume Profile', tooltip = 'Показывать процентное соотношение быков/медведей на объемных узлах в Mode 1 и Mode 2')
mode12TextDistance = input.int(2, 'Расстояние текста от узлов', minval = 1, maxval = 10, step = 1, group = 'Настройки Volume Profile', tooltip = 'Расстояние процентного текста от объемных узлов (меньше = ближе)')

showFibPrices = input.bool(true, 'Показывать цены', group = 'Фибоначчи')
showFibLevels = input.bool(true, 'Показывать уровни', group = 'Фибоначчи')
fibLevelsFormat = input.string('Percent', 'Формат', options = ['Values', 'Percent'], group = 'Фибоначчи')
fibLabelsPosition = input.string('Right', 'Позиция меток', options = ['Left', 'Right'], group = 'Фибоначчи')
fibColor = input.color(color.white, 'Цвет Фибоначчи', group = 'Фибоначчи')
autoFibDirection = input.bool(true, 'Автоопределение направления Фибо', tooltip = 'При включении автоматически определяет, является ли сессия бычьей (откат от минимума) или медвежьей (откат от максимума)', group = 'Фибоначчи')

show_fib_0 = input(true, '0%', inline = 'fib_level_0', group = 'Уровни Фибоначчи')
color_fib_0 = input(color.white, '', inline = 'fib_level_0', group = 'Уровни Фибоначчи')

show_fib_236 = input(true, '23.6%', inline = 'fib_level_1', group = 'Уровни Фибоначчи')
color_fib_236 = input(color.white, '', inline = 'fib_level_1', group = 'Уровни Фибоначчи')

show_fib_382 = input(true, '38.2%', inline = 'fib_level_2', group = 'Уровни Фибоначчи')
color_fib_382 = input(color.white, '', inline = 'fib_level_2', group = 'Уровни Фибоначчи')

show_fib_50 = input(true, '50%', inline = 'fib_level_3', group = 'Уровни Фибоначчи')
color_fib_50 = input(color.white, '', inline = 'fib_level_3', group = 'Уровни Фибоначчи')

show_fib_618 = input(true, '61.8%', inline = 'fib_level_4', group = 'Уровни Фибоначчи')
color_fib_618 = input(color.white, '', inline = 'fib_level_4', group = 'Уровни Фибоначчи')

show_fib_650 = input(true, '65%', inline = 'fib_level_5', group = 'Уровни Фибоначчи')
color_fib_650 = input(color.white, '', inline = 'fib_level_5', group = 'Уровни Фибоначчи')

show_fib_786 = input(true, '78.6%', inline = 'fib_level_6', group = 'Уровни Фибоначчи')
color_fib_786 = input(color.white, '', inline = 'fib_level_6', group = 'Уровни Фибоначчи')

show_fib_886 = input(true, '88.6%', inline = 'fib_level_7', group = 'Уровни Фибоначчи')
color_fib_886 = input(color.white, '', inline = 'fib_level_7', group = 'Уровни Фибоначчи')

show_fib_100 = input(true, '100%', inline = 'fib_level_8', group = 'Уровни Фибоначчи')
color_fib_100 = input(color.white, '', inline = 'fib_level_8', group = 'Уровни Фибоначчи')

dataTf = ''

bullCol = input.color(color.rgb(0, 255, 0, 50), 'Объем вверх', group = 'Внешний вид')
bearCol = input.color(color.rgb(255, 0, 0, 50), 'Объем вниз', group = 'Внешний вид')
VAbCol = input.color(color.rgb(107, 159, 255, 90), 'Бокс Value Area', group = 'Внешний вид')
pocCol = input.color(color.white, 'POC', inline = 'p', group = 'Внешний вид')
pocWid = input.int(3, 'Толщина', inline = 'p', group = 'Внешний вид')
vahCol = input.color(color.rgb(255, 0, 0), 'VAH', inline = 'h', group = 'Внешний вид')
vahWid = input.int(3, 'Толщина', inline = 'h', group = 'Внешний вид')
valCol = input.color(color.rgb(0, 255, 0), 'VAL', inline = 'l', group = 'Внешний вид')
valWid = input.int(3, 'Толщина', inline = 'l', group = 'Внешний вид')
boxBg = input.color(color.rgb(255, 153, 0, 100), 'Сессионный бокс', inline = 'm', group = 'Внешний вид')
boxWid = input.int(1, 'Толщина', inline = 'm', group = 'Внешний вид')

phOption = source == 'Wicks' ? high : close
plOption = source == 'Wicks' ? low : close

ph = ta.pivothigh(phOption, leftLenH, rightLenH)
pl = ta.pivotlow(plOption, leftLenL, rightLenL)

var leftBull = bar_index
var rightBull = bar_index
var topBull = close
var bottomBull = close

var leftBear = bar_index
var rightBear = bar_index
var topBear = close
var bottomBear = close

var array<box> _bearBoxes = array.new_box()
var array<box> _bullBoxes = array.new_box()

if not na(ph)
    leftBear := bar_index - leftLenH
    rightBear := bar_index - (leftLenH - boxLength)
    topBear := source == 'Bodys' ? close[leftLenL] > open[leftLenL] ? close[leftLenH] : open[leftLenH] : high[leftLenL]
    bottomBear := source == 'Bodys' ? close[leftLenL] > open[leftLenL] ? open[leftLenH] : close[leftLenH] : close[leftLenL] > open[leftLenL] ? close[leftLenL] : open[leftLenL]
    bottomBear

if not na(pl)
    leftBull := bar_index - leftLenL
    rightBull := bar_index - (leftLenL - boxLength)
    topBull := source == 'Bodys' ? close[leftLenL] > open[leftLenL] ? close[leftLenL] : open[leftLenL] : close[leftLenL] > open[leftLenL] ? open[leftLenL] : close[leftLenL]
    bottomBull := source == 'Bodys' ? close[leftLenL] > open[leftLenL] ? open[leftLenL] : close[leftLenL] : low[leftLenL]
    bottomBull

if not na(pl)
    array.push(_bullBoxes, box.new(left = leftBull, right = rightBull, top = topBull, bottom = bottomBull, bgcolor = color.new(bullBoxColor, 80), border_color = bullBoxColor))

if not na(ph)
    array.push(_bearBoxes, box.new(left = leftBear, right = rightBear, top = topBear, bottom = bottomBear, bgcolor = color.new(bearBoxColor, 80), border_color = bearBoxColor))

extend_boxes(_array, _type) =>
    if array.size(_array) > 0
        for i = 0 to array.size(_array) - 1 by 1
            _box = array.get(_array, i)
            _boxLow = box.get_bottom(_box)
            _boxHigh = box.get_top(_box)
            _boxLeft = box.get_left(_box)
            _boxRight = box.get_right(_box)

            if _type == 'bull' and _boxRight == bar_index
                if low > _boxHigh
                    box.set_right(_box, bar_index + 1)
                else
                    box.set_bgcolor(_box, closedBoxColor)
                    box.set_border_color(_box, closedBoxColor)
                    box.set_text_color(_box, closedBoxColor)
                    box.set_right(_box, bar_index)

            if _type == 'bear' and _boxRight == bar_index
                if high < _boxLow
                    box.set_right(_box, bar_index + 1)
                else
                    box.set_bgcolor(_box, closedBoxColor)
                    box.set_border_color(_box, closedBoxColor)
                    box.set_text_color(_box, closedBoxColor)
                    box.set_right(_box, bar_index)

if extendBox == true
    extend_boxes(_bullBoxes, 'bull')
    extend_boxes(_bearBoxes, 'bear')

var int zoneStart = 0
var int sydneyStart = 0
var int tokyoStart = 0
var int asianStart = 0
var int frankfurtStart = 0
var int londonStart = 0
var int europeanStart = 0
var int nyStart = 0
var int usExtendedStart = 0
var int asiaLondonStart = 0
var int londonNYStart = 0

getSessionPeriodBars() =>
    switch sessionType
        'Daily' => int(1440 / timeframe.in_seconds(timeframe.period) * 60) // ~1 день в барах
        'Weekly' => int(7 * 1440 / timeframe.in_seconds(timeframe.period) * 60) // ~7 дней в барах  
        'Monthly' => int(30 * 1440 / timeframe.in_seconds(timeframe.period) * 60) // ~30 дней в барах
        'Quarterly' => int(90 * 1440 / timeframe.in_seconds(timeframe.period) * 60) // ~90 дней в барах
        'Yearly' => int(365 * 1440 / timeframe.in_seconds(timeframe.period) * 60) // ~365 дней в барах
        'Sydney' => int(9 * 60 / timeframe.in_seconds(timeframe.period) * 60) // ~9 часов
        'Tokyo' => int(9 * 60 / timeframe.in_seconds(timeframe.period) * 60) // ~9 часов
        'Asian' => int(12 * 60 / timeframe.in_seconds(timeframe.period) * 60) // ~12 часов
        'Frankfurt' => int(9 * 60 / timeframe.in_seconds(timeframe.period) * 60) // ~9 часов
        'London' => int(9 * 60 / timeframe.in_seconds(timeframe.period) * 60) // ~9 часов
        'European' => int(10 * 60 / timeframe.in_seconds(timeframe.period) * 60) // ~10 часов
        'New York' => int(9 * 60 / timeframe.in_seconds(timeframe.period) * 60) // ~9 часов
        'US Extended' => int(16 * 60 / timeframe.in_seconds(timeframe.period) * 60) // ~16 часов
        'Asia-London Overlap' => int(2 * 60 / timeframe.in_seconds(timeframe.period) * 60) // ~2 часа
        'London-NY Overlap' => int(3 * 60 / timeframe.in_seconds(timeframe.period) * 60) // ~3 часа
        => int(1440 / timeframe.in_seconds(timeframe.period) * 60) // По умолчанию ~1 день

sessionPeriodBars = math.min(getSessionPeriodBars(), maxLookbackBars)

int safeLookback = zoneStart > 0 and bar_index >= zoneStart ? math.min(math.min(bar_index - zoneStart, maxLookbackBars), 4999) : math.min(bar_index, maxLookbackBars)
int lookback = math.max(safeLookback, 1)
var activeZone = false

var vpGreen = array.new_float(resolution, 0) // Сумма объема на бычьих барах
var vpRed = array.new_float(resolution, 0) // То же самое для медвежьих баров
var zoneBounds = array.new_float(resolution, 0) // Массив для хранения максимальных значений в зоне

var lvnHvnBoxes = array.new_box()
var lvnHvnLabels = array.new_label()

var array<float> ltfOpen = array.new_float(0)
var array<float> ltfClose = array.new_float(0)
var array<float> ltfHigh = array.new_float(0)
var array<float> ltfLow = array.new_float(0)
var array<float> ltfVolume = array.new_float(0)

type FibLevel
	line fibLine
	label fibLabel
	float level
	color levelColor
	bool show

var array<FibLevel> currentFibLines = array.new<FibLevel>()

vol() =>
    smoothVol ? ta.ema(volume, 5) : volume

[dO, dC, dH, dL, dV] = request.security_lower_tf(syminfo.tickerid, dataTf, [open, close, high, low, vol()])

resetProfile(enable) =>
    if enable
        array.fill(vpGreen, 0)
        array.fill(vpRed, 0)
        array.clear(ltfOpen)
        array.clear(ltfHigh)
        array.clear(ltfLow)
        array.clear(ltfClose)
        array.clear(ltfVolume)

safeHigh(offset) =>
    if bar_index >= offset and offset >= 0 and offset <= 4999
        high[offset]
    else
        high

safeLow(offset) =>
    if bar_index >= offset and offset >= 0 and offset <= 4999
        low[offset]
    else
        low

_maxSafeBars = math.min(bar_index, maxLookbackBars)
_profLength = zoneStart > 0 and bar_index >= zoneStart ? math.min(math.min(lookback + 1, _maxSafeBars), 5000) : math.min(bar_index + 1, maxLookbackBars)
_profLengthCurrent = math.min(bar_index + 1, 1000)

_profHighSession = ta.highest(high, _profLength)[1]
_profLowSession = ta.lowest(low, _profLength)[1]
_profHighCurrent = ta.highest(high, _profLengthCurrent)
_profLowCurrent = ta.lowest(low, _profLengthCurrent)

lookbackForBounds = math.min(sessionPeriodBars, maxLookbackBars)
smartHigh = ta.highest(high, lookbackForBounds)
smartLow = ta.lowest(low, lookbackForBounds)
smartATR = ta.atr(14) // Переименовано, чтобы избежать дублирования

if sessionCalcMethod == 'Include Previous Session' and zoneStart > 0 and bar_index <= zoneStart + 5

    currentRange = _profHighSession - _profLowSession
    if currentRange < smartATR * 3 // Если текущий диапазон меньше 3 ATR
        smartRange = smartHigh - smartLow

        if smartRange > currentRange * 1.5
            _profHighSession := smartHigh
            _profLowSession := smartLow
            _profLowSession

profHigh = zoneStart > 0 and bar_index >= zoneStart and _profLength > 1 ? _profHighSession : _profHighCurrent
profLow = zoneStart > 0 and bar_index >= zoneStart and _profLength > 1 ? _profLowSession : _profLowCurrent

tr = ta.atr(1)
atr = ta.atr(14)

get_vol(y11, y12, y21, y22, height, vol) =>
    nz(math.max(math.min(math.max(y11, y12), math.max(y21, y22)) - math.max(math.min(y11, y12), math.min(y21, y22)), 0) * vol / height)

profileAdd(o, h, l, c, v, g, w) =>

    zoneDist = array.new_float(resolution, 0)
    distSum = 0.0

    for i = 0 to array.size(vpGreen) - 1 by 1

        zoneTop = array.get(zoneBounds, i)
        zoneBot = zoneTop - g

        body_top = math.max(c, o)
        body_bot = math.min(c, o)
        itsgreen = c >= o

        topwick = h - body_top
        bottomwick = body_bot - l
        body = body_top - body_bot

        bodyvol = body * v / (2 * topwick + 2 * bottomwick + body)
        topwickvol = 2 * topwick * v / (2 * topwick + 2 * bottomwick + body)
        bottomwickvol = 2 * bottomwick * v / (2 * topwick + 2 * bottomwick + body)

        array.set(vpGreen, i, array.get(vpGreen, i) + (itsgreen ? get_vol(zoneBot, zoneTop, body_bot, body_top, body, bodyvol) : 0) + get_vol(zoneBot, zoneTop, body_top, h, topwick, topwickvol) / 2 + get_vol(zoneBot, zoneTop, body_bot, l, bottomwick, bottomwickvol) / 2)
        array.set(vpRed, i, array.get(vpRed, i) + (itsgreen ? 0 : get_vol(zoneBot, zoneTop, body_bot, body_top, body, bodyvol)) + get_vol(zoneBot, zoneTop, body_top, h, topwick, topwickvol) / 2 + get_vol(zoneBot, zoneTop, body_bot, l, bottomwick, bottomwickvol) / 2)

calcSession(update) =>
    array.fill(vpGreen, 0)
    array.fill(vpRed, 0)
    if bar_index > lookback and update and zoneStart > 0
        gap = (profHigh - profLow) / resolution

        for i = 0 to resolution - 1 by 1
            array.set(zoneBounds, i, profHigh - gap * i)

        if array.size(ltfOpen) > 0
            for j = 0 to array.size(ltfOpen) - 1 by 1
                profileAdd(array.get(ltfOpen, j), array.get(ltfHigh, j), array.get(ltfLow, j), array.get(ltfClose, j), array.get(ltfVolume, j), gap, 1)

pocLevel() =>
    float maxVol = 0
    int levelInd = 0
    for i = 0 to array.size(vpRed) - 1 by 1
        if array.get(vpRed, i) + array.get(vpGreen, i) > maxVol
            maxVol := array.get(vpRed, i) + array.get(vpGreen, i)
            levelInd := i
            levelInd

    float outLevel = na
    if levelInd != array.size(vpRed) - 1
        outLevel := array.get(zoneBounds, levelInd) - (array.get(zoneBounds, levelInd) - array.get(zoneBounds, levelInd + 1)) / 2
        outLevel
    outLevel

valueLevels(poc) =>
    float gap = (profHigh - profLow) / resolution
    float volSum = array.sum(vpRed) + array.sum(vpGreen)
    float volCnt = 0

    float vah = profHigh
    float val = profLow

    int pocInd = 0
    for i = 0 to array.size(zoneBounds) - 2 by 1
        if array.get(zoneBounds, i) >= poc and array.get(zoneBounds, i + 1) < poc
            pocInd := i
            pocInd

    volCnt := volCnt + array.get(vpRed, pocInd) + array.get(vpGreen, pocInd)
    for i = 1 to array.size(vpRed) by 1
        if pocInd + i >= 0 and pocInd + i < array.size(vpRed)
            volCnt := volCnt + array.get(vpRed, pocInd + i) + array.get(vpGreen, pocInd + i)
            if volCnt >= volSum * (VAwid / 100)
                break
            else
                val := array.get(zoneBounds, pocInd + i) - gap
                val
        if pocInd - i >= 0 and pocInd - i < array.size(vpRed)
            volCnt := volCnt + array.get(vpRed, pocInd - i) + array.get(vpGreen, pocInd - i)
            if volCnt >= volSum * (VAwid / 100)
                break
            else
                vah := array.get(zoneBounds, pocInd - i)
                vah

    [val, vah]

detectLvnHvn() =>
    if enableComplexCalculations and array.sum(vpGreen) + array.sum(vpRed) > 0

        poc = pocLevel()
        [val, vah] = valueLevels(poc)
        gap = (profHigh - profLow) / resolution

        int vahIndex = 0
        int valIndex = resolution - 1
        int pocIndex = 0

        float maxVol = 0
        for i = 0 to array.size(vpRed) - 1 by 1
            zoneTop = array.get(zoneBounds, i)
            zoneBottom = zoneTop - gap
            zoneMid = (zoneTop + zoneBottom) / 2
            totalVol = array.get(vpRed, i) + array.get(vpGreen, i)

            if totalVol > maxVol
                maxVol := totalVol
                pocIndex := i
                pocIndex

            if math.abs(zoneMid - vah) < math.abs(array.get(zoneBounds, vahIndex) - gap / 2 - vah)
                vahIndex := i
                vahIndex

            if math.abs(zoneMid - val) < math.abs(array.get(zoneBounds, valIndex) - gap / 2 - val)
                valIndex := i
                valIndex

        float avgVol = (array.sum(vpRed) + array.sum(vpGreen)) / resolution
        float totalVol = array.sum(vpRed) + array.sum(vpGreen)
        float lvnThresholdVol = avgVol * lvnThreshold // Порог низкого объема
        float hvnThresholdVol = avgVol * hvnThreshold // Сделать HVN относительно среднего, не усиленным
        float singlePrintThresholdVol = avgVol * singlePrintThreshold // Порог Single Print

        float medianVol = avgVol * 0.8 // Еще более низкий порог для обнаружения HVN

        var lvnZones = array.new_int()
        var hvnZones = array.new_int()
        var singlePrintZones = array.new_int()
        array.clear(lvnZones)
        array.clear(hvnZones)
        array.clear(singlePrintZones)

        for i = 0 to array.size(vpRed) - 1 by 1
            totalVol := array.get(vpRed, i) + array.get(vpGreen, i)

            isPocArea = i == pocIndex // Исключить только точный POC, не окружающие области

            if not isPocArea and totalVol > 0

                isAboveVAH = i < vahIndex

                isHighVolume = totalVol >= hvnThresholdVol or totalVol >= medianVol and isAboveVAH

                if isAboveVAH and isHighVolume
                    array.push(hvnZones, i)

                isBelowVAL = i > valIndex
                isLowVolume = totalVol <= lvnThresholdVol

                if isBelowVAL and isLowVolume
                    array.push(lvnZones, i)

                isWithinVA = i >= vahIndex and i <= valIndex
                isNPOC = totalVol <= singlePrintThresholdVol

                if isWithinVA and isNPOC and showSinglePrints
                    array.push(singlePrintZones, i)

        [lvnZones, hvnZones, singlePrintZones]

clearLvnHvnAreas() =>
    if array.size(lvnHvnBoxes) > 0
        for i = 0 to array.size(lvnHvnBoxes) - 1 by 1
            box.delete(array.get(lvnHvnBoxes, i))
        array.clear(lvnHvnBoxes)

    if array.size(lvnHvnLabels) > 0
        for i = 0 to array.size(lvnHvnLabels) - 1 by 1
            label.delete(array.get(lvnHvnLabels, i))
        array.clear(lvnHvnLabels)

drawLvnHvnAreas(leftMax, rightMax) =>
    if showLvnHvn and enableComplexCalculations and array.sum(vpGreen) + array.sum(vpRed) > 0
        [lvnZones, hvnZones, singlePrintZones] = detectLvnHvn()
        gap = (profHigh - profLow) / resolution

        profileWidth = rightMax - leftMax

        baseWidth = math.min(profileWidth * 0.3, 20) // Намного меньшая базовая ширина
        userWidth = baseWidth * lvnHvnWidth

        maxWidth = switch 
            timeframe.ismonthly => math.min(userWidth, 15)
            timeframe.isweekly => math.min(userWidth, 25)
            timeframe.isdaily => math.min(userWidth, 40)
            => userWidth

        if showSinglePrints and array.size(singlePrintZones) > 0
            var currentNPOCStart = -1
            var currentNPOCEnd = -1

            for i = 0 to array.size(singlePrintZones) - 1 by 1
                zoneIndex = array.get(singlePrintZones, i)

                if currentNPOCStart == -1
                    currentNPOCStart := zoneIndex
                    currentNPOCEnd := zoneIndex
                    currentNPOCEnd
                else if zoneIndex == currentNPOCEnd + 1
                    currentNPOCEnd := zoneIndex
                    currentNPOCEnd
                else // Отрисовка текущей NPOC зоны с белым градиентом - ВЫСОКАЯ ПРОЗРАЧНОСТЬ
                    topPrice = array.get(zoneBounds, currentNPOCStart)
                    bottomPrice = array.get(zoneBounds, currentNPOCEnd) - gap

                    float minVolInArea = 999999
                    float maxVolInArea = 0

                    for areaIdx = currentNPOCStart to currentNPOCEnd by 1
                        areaVol = array.get(vpRed, areaIdx) + array.get(vpGreen, areaIdx)
                        if areaVol < minVolInArea and areaVol > 0
                            minVolInArea := areaVol
                            minVolInArea
                        if areaVol > maxVolInArea
                            maxVolInArea := areaVol
                            maxVolInArea

                    areaSize = currentNPOCEnd - currentNPOCStart + 1
                    if areaSize > 1

                        for zoneIdx = currentNPOCStart to currentNPOCEnd by 1
                            zoneTop = array.get(zoneBounds, zoneIdx)
                            zoneBottom = zoneTop - gap
                            zoneVol = array.get(vpRed, zoneIdx) + array.get(vpGreen, zoneIdx)

                            volumeRatio = maxVolInArea > minVolInArea ? (zoneVol - minVolInArea) / (maxVolInArea - minVolInArea) : 0
                            zoneTransparency = int(85 + volumeRatio * 10) // Диапазон 85-95% прозрачности
                            zoneTransparency := math.max(math.min(zoneTransparency, 95), 85)

                            npocBox = box.new(int(rightMax), zoneTop, int(rightMax + maxWidth), zoneBottom, bgcolor = color.new(singlePrintColor, zoneTransparency), border_color = color.new(singlePrintColor, 90), border_width = 1)
                            array.push(lvnHvnBoxes, npocBox)
                    else // Одиночная зона NPOC - ВЫСОКАЯ ПРОЗРАЧНОСТЬ
                        npocBox = box.new(int(rightMax), topPrice, int(rightMax + maxWidth), bottomPrice, bgcolor = color.new(singlePrintColor, 90), border_color = color.new(singlePrintColor, 90), border_width = 1)
                        array.push(lvnHvnBoxes, npocBox)

                    if showLvnHvnLabels
                        midPrice = (topPrice + bottomPrice) / 2
                        npocLabel = label.new(int(rightMax) + int(maxWidth * 0.15), midPrice, 'NPOC', color = color.new(color.black, 100), textcolor = color.new(color.white, 20), size = size.small, style = label.style_label_left)
                        array.push(lvnHvnLabels, npocLabel)

                    currentNPOCStart := zoneIndex
                    currentNPOCEnd := zoneIndex
                    currentNPOCEnd

            if currentNPOCStart != -1
                topPrice = array.get(zoneBounds, currentNPOCStart)
                bottomPrice = array.get(zoneBounds, currentNPOCEnd) - gap

                float minVolInArea = 999999
                float maxVolInArea = 0

                for areaIdx = currentNPOCStart to currentNPOCEnd by 1
                    areaVol = array.get(vpRed, areaIdx) + array.get(vpGreen, areaIdx)
                    if areaVol < minVolInArea and areaVol > 0
                        minVolInArea := areaVol
                        minVolInArea
                    if areaVol > maxVolInArea
                        maxVolInArea := areaVol
                        maxVolInArea

                areaSize = currentNPOCEnd - currentNPOCStart + 1
                if areaSize > 1

                    for zoneIdx = currentNPOCStart to currentNPOCEnd by 1
                        zoneTop = array.get(zoneBounds, zoneIdx)
                        zoneBottom = zoneTop - gap
                        zoneVol = array.get(vpRed, zoneIdx) + array.get(vpGreen, zoneIdx)

                        volumeRatio = maxVolInArea > minVolInArea ? (zoneVol - minVolInArea) / (maxVolInArea - minVolInArea) : 0
                        zoneTransparency = int(85 + volumeRatio * 10) // Диапазон 85-95% прозрачности
                        zoneTransparency := math.max(math.min(zoneTransparency, 95), 85)

                        npocBox = box.new(int(rightMax), zoneTop, int(rightMax + maxWidth), zoneBottom, bgcolor = color.new(singlePrintColor, zoneTransparency), border_color = color.new(singlePrintColor, 90), border_width = 1)
                        array.push(lvnHvnBoxes, npocBox)
                else // Одиночная зона NPOC - ВЫСОКАЯ ПРОЗРАЧНОСТЬ
                    npocBox = box.new(int(rightMax), topPrice, int(rightMax + maxWidth), bottomPrice, bgcolor = color.new(singlePrintColor, 90), border_color = color.new(singlePrintColor, 90), border_width = 1)
                    array.push(lvnHvnBoxes, npocBox)

                if showLvnHvnLabels
                    midPrice = (topPrice + bottomPrice) / 2
                    npocLabel = label.new(int(rightMax) + int(maxWidth * 0.15), midPrice, 'NPOC', color = color.new(color.black, 100), textcolor = color.new(color.white, 20), size = size.small, style = label.style_label_left)
                    array.push(lvnHvnLabels, npocLabel)

        areaRightEdge = int(rightMax + maxWidth)

        if array.size(lvnZones) > 0
            var currentLvnStart = -1
            var currentLvnEnd = -1

            for i = 0 to array.size(lvnZones) - 1 by 1
                zoneIndex = array.get(lvnZones, i)

                if currentLvnStart == -1
                    currentLvnStart := zoneIndex
                    currentLvnEnd := zoneIndex
                    currentLvnEnd
                else if zoneIndex == currentLvnEnd + 1
                    currentLvnEnd := zoneIndex
                    currentLvnEnd
                else // Отрисовка текущей LVN зоны с градиентом на основе объема - ВЫСОКАЯ ПРОЗРАЧНОСТЬ
                    topPrice = array.get(zoneBounds, currentLvnStart)
                    bottomPrice = array.get(zoneBounds, currentLvnEnd) - gap

                    float minVolInArea = 999999
                    float maxVolInArea = 0

                    for areaIdx = currentLvnStart to currentLvnEnd by 1
                        areaVol = array.get(vpRed, areaIdx) + array.get(vpGreen, areaIdx)
                        if areaVol < minVolInArea
                            minVolInArea := areaVol
                            minVolInArea
                        if areaVol > maxVolInArea and areaVol > 0
                            maxVolInArea := areaVol
                            maxVolInArea

                    areaSize = currentLvnEnd - currentLvnStart + 1
                    if areaSize > 1

                        for zoneIdx = currentLvnStart to currentLvnEnd by 1
                            zoneTop = array.get(zoneBounds, zoneIdx)
                            zoneBottom = zoneTop - gap
                            zoneVol = array.get(vpRed, zoneIdx) + array.get(vpGreen, zoneIdx)

                            volumeRatio = maxVolInArea > minVolInArea ? (zoneVol - minVolInArea) / (maxVolInArea - minVolInArea) : 0
                            zoneTransparency = int(80 + volumeRatio * 15) // Диапазон 80-95% прозрачности
                            zoneTransparency := math.max(math.min(zoneTransparency, 95), 80)

                            lvnBox = box.new(int(rightMax), zoneTop, int(rightMax + maxWidth), zoneBottom, bgcolor = color.new(lvnColor, zoneTransparency), border_color = color.new(lvnColor, 90), border_width = 1)
                            array.push(lvnHvnBoxes, lvnBox)
                    else // Одиночная зона LVN - ВЫСОКАЯ ПРОЗРАЧНОСТЬ
                        lvnBox = box.new(int(rightMax), topPrice, int(rightMax + maxWidth), bottomPrice, bgcolor = color.new(lvnColor, 88), border_color = color.new(lvnColor, 90), border_width = 1)
                        array.push(lvnHvnBoxes, lvnBox)

                    if showLvnHvnLabels
                        midPrice = (topPrice + bottomPrice) / 2
                        labelText = areaSize > 2 ? 'LVN⚡' : 'LVN'
                        lvnLabel = label.new(int(rightMax) + int(maxWidth * 0.15), midPrice, labelText, color = color.new(color.black, 100), textcolor = color.new(color.white, 10), size = size.small, style = label.style_label_left)
                        array.push(lvnHvnLabels, lvnLabel)

                    currentLvnStart := zoneIndex
                    currentLvnEnd := zoneIndex
                    currentLvnEnd

            if currentLvnStart != -1
                topPrice = array.get(zoneBounds, currentLvnStart)
                bottomPrice = array.get(zoneBounds, currentLvnEnd) - gap

                float minVolInArea = 999999
                float maxVolInArea = 0

                for areaIdx = currentLvnStart to currentLvnEnd by 1
                    areaVol = array.get(vpRed, areaIdx) + array.get(vpGreen, areaIdx)
                    if areaVol < minVolInArea
                        minVolInArea := areaVol
                        minVolInArea
                    if areaVol > maxVolInArea and areaVol > 0
                        maxVolInArea := areaVol
                        maxVolInArea

                areaSize = currentLvnEnd - currentLvnStart + 1
                if areaSize > 1

                    for zoneIdx = currentLvnStart to currentLvnEnd by 1
                        zoneTop = array.get(zoneBounds, zoneIdx)
                        zoneBottom = zoneTop - gap
                        zoneVol = array.get(vpRed, zoneIdx) + array.get(vpGreen, zoneIdx)

                        volumeRatio = maxVolInArea > minVolInArea ? (zoneVol - minVolInArea) / (maxVolInArea - minVolInArea) : 0
                        zoneTransparency = int(80 + volumeRatio * 15) // Диапазон 80-95% прозрачности
                        zoneTransparency := math.max(math.min(zoneTransparency, 95), 80)

                        lvnBox = box.new(int(rightMax), zoneTop, int(rightMax + maxWidth), zoneBottom, bgcolor = color.new(lvnColor, zoneTransparency), border_color = color.new(lvnColor, 90), border_width = 1)
                        array.push(lvnHvnBoxes, lvnBox)
                else // Одиночная зона LVN - ВЫСОКАЯ ПРОЗРАЧНОСТЬ
                    lvnBox = box.new(int(rightMax), topPrice, int(rightMax + maxWidth), bottomPrice, bgcolor = color.new(lvnColor, 88), border_color = color.new(lvnColor, 90), border_width = 1)
                    array.push(lvnHvnBoxes, lvnBox)

                if showLvnHvnLabels
                    midPrice = (topPrice + bottomPrice) / 2
                    labelText = areaSize > 2 ? 'LVN⚡' : 'LVN'
                    lvnLabel = label.new(int(rightMax) + int(maxWidth * 0.15), midPrice, labelText, color = color.new(color.black, 100), textcolor = color.new(color.white, 10), size = size.small, style = label.style_label_left)
                    array.push(lvnHvnLabels, lvnLabel)

        if array.size(hvnZones) > 0
            var currentHvnStart = -1
            var currentHvnEnd = -1

            for i = 0 to array.size(hvnZones) - 1 by 1
                zoneIndex = array.get(hvnZones, i)

                if currentHvnStart == -1
                    currentHvnStart := zoneIndex
                    currentHvnEnd := zoneIndex
                    currentHvnEnd
                else if zoneIndex == currentHvnEnd + 1
                    currentHvnEnd := zoneIndex
                    currentHvnEnd
                else // Отрисовка текущей HVN зоны с градиентом на основе объема - ВЫСОКАЯ ПРОЗРАЧНОСТЬ
                    topPrice = array.get(zoneBounds, currentHvnStart)
                    bottomPrice = array.get(zoneBounds, currentHvnEnd) - gap

                    float minVolInArea = 999999
                    float maxVolInArea = 0

                    for areaIdx = currentHvnStart to currentHvnEnd by 1
                        areaVol = array.get(vpRed, areaIdx) + array.get(vpGreen, areaIdx)
                        if areaVol < minVolInArea and areaVol > 0
                            minVolInArea := areaVol
                            minVolInArea
                        if areaVol > maxVolInArea
                            maxVolInArea := areaVol
                            maxVolInArea

                    areaSize = currentHvnEnd - currentHvnStart + 1
                    if areaSize > 1

                        for zoneIdx = currentHvnStart to currentHvnEnd by 1
                            zoneTop = array.get(zoneBounds, zoneIdx)
                            zoneBottom = zoneTop - gap
                            zoneVol = array.get(vpRed, zoneIdx) + array.get(vpGreen, zoneIdx)

                            volumeRatio = maxVolInArea > minVolInArea ? (zoneVol - minVolInArea) / (maxVolInArea - minVolInArea) : 0
                            zoneTransparency = int(82 + volumeRatio * 13) // Диапазон 82-95% прозрачности
                            zoneTransparency := math.max(math.min(zoneTransparency, 95), 82)

                            hvnBox = box.new(int(rightMax), zoneTop, int(rightMax + maxWidth), zoneBottom, bgcolor = color.new(hvnColor, zoneTransparency), border_color = color.new(hvnColor, 90), border_width = 1)
                            array.push(lvnHvnBoxes, hvnBox)
                    else // Одиночная зона HVN - ВЫСОКАЯ ПРОЗРАЧНОСТЬ
                        hvnBox = box.new(int(rightMax), topPrice, int(rightMax + maxWidth), bottomPrice, bgcolor = color.new(hvnColor, 90), border_color = color.new(hvnColor, 90), border_width = 1)
                        array.push(lvnHvnBoxes, hvnBox)

                    if showLvnHvnLabels
                        midPrice = (topPrice + bottomPrice) / 2
                        hvnLabel = label.new(int(rightMax) + int(maxWidth * 0.15), midPrice, 'HVN', color = color.new(color.black, 100), textcolor = color.new(color.white, 10), size = size.small, style = label.style_label_left)
                        array.push(lvnHvnLabels, hvnLabel)

                    currentHvnStart := zoneIndex
                    currentHvnEnd := zoneIndex
                    currentHvnEnd

            if currentHvnStart != -1
                topPrice = array.get(zoneBounds, currentHvnStart)
                bottomPrice = array.get(zoneBounds, currentHvnEnd) - gap

                float minVolInArea = 999999
                float maxVolInArea = 0

                for areaIdx = currentHvnStart to currentHvnEnd by 1
                    areaVol = array.get(vpRed, areaIdx) + array.get(vpGreen, areaIdx)
                    if areaVol < minVolInArea and areaVol > 0
                        minVolInArea := areaVol
                        minVolInArea
                    if areaVol > maxVolInArea
                        maxVolInArea := areaVol
                        maxVolInArea

                areaSize = currentHvnEnd - currentHvnStart + 1
                if areaSize > 1

                    for zoneIdx = currentHvnStart to currentHvnEnd by 1
                        zoneTop = array.get(zoneBounds, zoneIdx)
                        zoneBottom = zoneTop - gap
                        zoneVol = array.get(vpRed, zoneIdx) + array.get(vpGreen, zoneIdx)

                        volumeRatio = maxVolInArea > minVolInArea ? (zoneVol - minVolInArea) / (maxVolInArea - minVolInArea) : 0
                        zoneTransparency = int(82 + volumeRatio * 13) // Диапазон 82-95% прозрачности
                        zoneTransparency := math.max(math.min(zoneTransparency, 95), 82)

                        hvnBox = box.new(int(rightMax), zoneTop, int(rightMax + maxWidth), zoneBottom, bgcolor = color.new(hvnColor, zoneTransparency), border_color = color.new(hvnColor, 90), border_width = 1)
                        array.push(lvnHvnBoxes, hvnBox)
                else // Одиночная зона HVN - ВЫСОКАЯ ПРОЗРАЧНОСТЬ
                    hvnBox = box.new(int(rightMax), topPrice, int(rightMax + maxWidth), bottomPrice, bgcolor = color.new(hvnColor, 90), border_color = color.new(hvnColor, 90), border_width = 1)
                    array.push(lvnHvnBoxes, hvnBox)

                if showLvnHvnLabels
                    midPrice = (topPrice + bottomPrice) / 2
                    hvnLabel = label.new(int(rightMax) + int(maxWidth * 0.15), midPrice, 'HVN', color = color.new(color.black, 100), textcolor = color.new(color.white, 10), size = size.small, style = label.style_label_left)
                    array.push(lvnHvnLabels, hvnLabel)

_wrap(txt) =>
    '(' + str.tostring(txt, format.mintick) + ')'

_label_txt(level, price) =>
    l = fibLevelsFormat == 'Percent' ? str.tostring(level * 100) + '%' : str.tostring(level)
    (showFibLevels ? l : '') + (showFibPrices ? _wrap(price) : '')

_draw_fib_label(price, txt, txtColor, leftMax) =>
    x = fibLabelsPosition == 'Left' ? leftMax : bar_index - 1
    labelStyle = fibLabelsPosition == 'Left' ? label.style_label_right : label.style_label_left
    align = fibLabelsPosition == 'Left' ? text.align_right : text.align_left
    labelsAlignStr = fibLabelsPosition == 'Left' ? txt + '\n' : '       ' + txt + '\n'
    label.new(x = x, y = price, text = labelsAlignStr, textcolor = txtColor, style = labelStyle, textalign = align, color = color.new(color.black, 100))

clearFibLines() =>
    if array.size(currentFibLines) > 0
        for i = 0 to array.size(currentFibLines) - 1 by 1
            fibLevel = array.get(currentFibLines, i)
            if not na(fibLevel.fibLine)
                line.delete(fibLevel.fibLine)
            if not na(fibLevel.fibLabel)
                label.delete(fibLevel.fibLabel)
        array.clear(currentFibLines)

getTrendDirection(sessionHigh, sessionLow, sessionStart) =>
    if not autoFibDirection
        true // По умолчанию бычий/восходящий тренд, если автоопределение отключено
    else //

Показано первые 50% кода (символов: 67479)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
6 747,90₽ ≈ $83.29