Исходный код
Ниже представлен оптимизированный скрипт на языке Pine Script v5. Он собирает ценовые уровни внутри заданной сессии, распределяет их по 30-минутным интервалам (каждому интервалу соответствует своя буква) и строит наглядный профиль TPO прямо на графике, выделяя линию POC.
//@version=5
indicator('Market Profile TPO - Finfluct', overlay=true, max_labels_limit=500, max_lines_limit=500)
// Входные параметры
tpo_step = input.float(1.0, title='Шаг цены TPO (в пунктах)', minval=0.0001)
session_spec = input.session('0900-1800:23456', title='Торговая сессия')
text_color = input.color(color.white, title='Цвет текста TPO')
bg_color = input.color(color.new(color.blue, 90), title='Цвет фона профиля')
poc_color = input.color(color.orange, title='Цвет линии POC')
// Определение сессии
in_session = not na(time(timeframe.period, session_spec))
new_session = in_session and not in_session[1]
// Массив букв TPO для 30-минутных интервалов
var string[] tpo_letters = array.from(
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
)
// Хранилище данных профиля
var float[] price_levels = array.new_float(0)
var string[] tpo_strings = array.new_string(0)
var int session_start_idx = na
var label profile_lbl = na
var line poc_ln = na
// Функция поиска или создания ценового уровня
get_level_index(float price) =>
int idx = array.indexof(price_levels, price)
if idx == -1
array.push(price_levels, price)
array.push(tpo_strings, '')
idx := array.size(price_levels) - 1
idx
// Сброс данных при старте новой сессии
if new_session
array.clear(price_levels)
array.clear(tpo_strings)
session_start_idx := bar_index
profile_lbl := label.new(
x=bar_index,
y=close,
text='',
style=label.style_label_left,
textcolor=text_color,
color=bg_color,
textalign=text.align_left
)
if not na(poc_ln)
line.delete(poc_ln)
poc_ln := line.new(x1=bar_index, y1=close, x2=bar_index, y2=close, color=poc_color, width=2)
// Наполнение профиля внутри сессии
if in_session and not na(session_start_idx)
// Вычисление индекса 30-минутного интервала
int elapsed_ms = int(time - time[bar_index - session_start_idx])
int interval_index = math.min(math.floor(elapsed_ms / 1800000), array.size(tpo_letters) - 1)
string current_letter = array.get(tpo_letters, interval_index)
// Округление границ текущего бара под шаг TPO
float low_bound = math.floor(low / tpo_step) * tpo_step
float high_bound = math.ceil(high / tpo_step) * tpo_step
// Заполнение ценовых уровней буквами
for price = low_bound to high_bound by tpo_step
float rounded_price = math.round(price / tpo_step) * tpo_step
int idx = get_level_index(rounded_price)
string current_str = array.get(tpo_strings, idx)
// Добавляем букву, если её еще нет для этого уровня в текущем интервале
if str.pos(current_str, current_letter) == -1
array.set(tpo_strings, idx, current_str + current_letter)
// Отрисовка профиля на каждом баре для интерактивности
if array.size(price_levels) > 0
// Сортировка уровней по убыванию цены
int[] sorted_indices = array.sort_indices(price_levels, order.descending)
string display_text = ''
float poc_price = 0.0
int max_tpo_len = 0
for i = 0 to array.size(sorted_indices) - 1
int orig_idx = array.get(sorted_indices, i)
float price = array.get(price_levels, orig_idx)
string tpos = array.get(tpo_strings, orig_idx)
int tpo_len = str.length(tpos)
if tpo_len > max_tpo_len
max_tpo_len := tpo_len
poc_price := price
display_text := display_text + str.tostring(price, '#.##') + ' | ' + tpos + '\n'
// Обновление метки профиля
label.set_xy(profile_lbl, session_start_idx, poc_price)
label.set_text(profile_lbl, display_text)
// Обновление линии POC (Point of Control)
line.set_xy1(poc_ln, session_start_idx, poc_price)
line.set_xy2(poc_ln, bar_index, poc_price) Разбор параметров
Для гибкой настройки индикатора под разные таймфреймы и инструменты мы вынесли ключевые переменные в панель настроек:
tpo_step: Шаг цены (размер строки TPO). Определяет чувствительность профиля. Для волатильных активов (например, BTCUSD) шаг следует увеличить, для акций или форекс-пар — уменьшить.session_spec: Временные границы торговой сессии, внутри которой рассчитывается профиль. По умолчанию настроена дневная сессия.text_color: Цвет букв TPO для кастомизации визуального стиля под темную или светлую тему графика.bg_color: Цвет фона текстовой метки профиля с поддержкой прозрачности.poc_color: Цвет горизонтальной линии Point of Control (уровня с максимальным скоплением TPO).
Как запустить
Чтобы запустить скрипт на платформе TradingView, выполните следующие шаги:
1. Откройте график нужного вам актива на TradingView (рекомендуется использовать таймфреймы от 1m до 5m для точного расчета внутри 30-минутных блоков).
2. В нижней панели выберите вкладку Pine Editor.
3. Скопируйте исходный код, представленный выше, и вставьте его в редактор, предварительно удалив стандартный шаблон.
4. Нажмите кнопку Add to Chart (Добавить на график).
5. При необходимости откройте настройки индикатора, чтобы скорректировать параметр tpo_step под текущую волатильность инструмента.
При разработке сложных торговых систем, использующих горизонтальные объемы и профили рынка, критически важно уметь вовремя фиксировать прибыль и ограничивать убытки. В этом вам поможет наш материал про динамический трейлинг-стоп по ATR в Pine Script v5: Инструкция.
Для институционального исполнения крупных ордеров внутри зон высокой ликвидности (POC), определенных профилем рынка, рекомендуется использовать скрипт TWAP на Pine Script v5: Алгоритмическое исполнение, который позволяет минимизировать рыночное проскальзывание.
Если вы хотите отслеживать трендовые развороты на множестве активов параллельно с анализом горизонтальных уровней TPO, изучите наш Pine Script v5: Скринер MACD кроссоверов для 40 тикеров для автоматизации рутинного сканирования рынка.




