Volume Nodes & Value Migration [MQLSoftware]
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «volume nodes.pine» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
Это индикатор TradingView на Pine Script v6, который строит профили объёма по цене и отслеживает, как цена ведёт себя вокруг структуры этих профилей. Профили привязываются к якорным окнам (дневным, недельным, месячным, квартальным или годовым) и пересчитываются только по подтверждённым свечам. Индикатор отрисовывает гистограмму профилей, зоны ценности, линию точки контроля (POC), миграционные связи между окнами и состояние горизонтальных уровней-узлов. В нижней части графика выводится панель со статусом окна, текущими значениями и измеренными базовыми частотами повторных обращений к POC и разрешения узлов. Все события и расчёты привязаны к подтверждённым барам — живой профиль и панель обновляются как визуальный контекст, а не как сигналы.
Настройки программы
| Настройка | Описание |
|---|---|
| anchorMode | Якорный период — Выбор якорного окна для построения профилей: автоматический выбор по таймфрейму графика или фиксированный период (день, неделя, месяц, квартал). |
| keepProfiles | Количество сохраняемых профилей — Сколько завершённых окон остаются нарисованными на графике; статистика и базовые частоты используют всю загруженную историю. |
| detail | Детализация профиля — Задаёт целевую гранулярность построения профиля — грубую, сбалансированную или тонкую. |
| atrLen | Длина ATR — Период расчёта ATR, используемый для определения высоты бинов и выражения расстояния миграции POC. |
| vaPct | Процент зоны ценности — Доля объёма окна, которую охватывает зона ценности, строимая путём жадного расширения от бина POC. |
| trackNodes | Отслеживание POC и HVN как узлов — Включает отслеживание возвратов цены к уровням POC и HVN с определением принятия или отклонения узла. |
| acceptN | Количество подтверждённых закрытий для принятия — Сколько подтверждённых закрытий внутри зоны узла требуется для признания возврата принятым. |
| hvnMax | Максимум HVN-узлов на окно — Сколько высоковолюмных узлов (кроме POC) активируется при фиксации окна. |
| showLvn | Тонкие зоны (LVN) — Включает отображение тонких зон — участков бинов с низким объёмом относительно среднего. |
| marksKeep | Количество сохраняемых меток — Сколько разрешённых меток узлов (принятых/отклонённых) остаются на графике. |
| showProf | Зафиксированные профили — Отрисовка итоговой гистограммы каждого зафиксированного окна с затенённой зоной ценности. |
| showLive | Живой формирующийся профиль — Отображение гистограммы текущего ещё не завершённого окна, перерисовываемого по мере роста. |
| profWidth | Ширина профиля (% от окна) — Горизонтальная ширина гистограммы как доля от количества баров в окне. |
| showDev | Формирующиеся POC и зона ценности — Отрисовка траектории развивающегося POC и полосы зоны ценности для активного окна. |
| showMig | Связи миграции POC — Пунктирные линии и подписи расстояний между финальными POC последовательных окон. |
| glowOn | Эффекты свечения — Включает мягкое свечение под линиями POC и узлов — чисто декоративная настройка. |
| colBody | Цвет профиля — Основной цвет тела бинов профиля. |
| colPoc | Цвет POC — Цвет линии точки контроля и её траектории миграции. |
| colAcc | Цвет принятых — Цвет для узлов, чей возврат признан принятым. |
| colRej | Цвет отклонённых — Цвет для узлов, чей возврат признан отклонённым. |
| showPanel | Панель статистики — Включает отображение информационной панели со статусом окна, состоянием узлов и измеренными базовыми частотами. |
| panelPos | Позиция панели — Угол графика, к которому привязана панель статистики. |
| panelSize | Размер текста панели — Размер текста в информационной панели. |
Поиск по коду файла
indicator("Volume Nodes & Value Migration [MQLSoftware]", shorttitle="MQLSoftware - Volume Nodes & Value Migration", overlay=true, max_boxes_count=500, max_lines_count=500, max_labels_count=500, max_polylines_count=10)
color NS_WHITE = color.rgb(225, 230, 240)
color NS_LBL = color.rgb(170, 178, 195)
color NS_SEC = color.rgb( 90, 98, 115)
color NS_BG = color.new(color.rgb( 8, 11, 18), 4)
color NS_ROW = color.new(color.rgb( 16, 20, 30), 6)
color NS_INK = color.rgb( 10, 14, 22)
color VN_BODY_DEF = #A78BFA // profile body — amethyst
color VN_POC_DEF = #E8DEFF // POC — near-white violet
color VN_ACC_DEF = #FFAF14 // accepted — house amber token
color VN_REJ_DEF = #FF4669 // rejected — house rose token
int BIN_CAP = 96
var string GRP_W = "◆ Profile Window"
var string GRP_D = "◆ Resolution & Distribution"
var string GRP_N = "◆ Volume Nodes"
var string GRP_R = "◆ Rendering"
var string GRP_ST = "◆ Statistics & Panel"
string anchorMode = input.string("Auto", "Anchor Period", group = GRP_W, options = ["Auto", "Day", "Week", "Month", "Quarter"], tooltip = "Each profile covers one anchor window. Auto picks Day for charts up to 30 minutes, Week for slower intraday charts, Month for Daily charts and Year above that. A manual pick at or below the chart timeframe escalates to the next valid period automatically.")
int keepProfiles = input.int(3, "Committed Profiles to Keep", group = GRP_W, minval = 1, maxval = 4, tooltip = "How many completed windows keep their histogram drawn on the chart. Statistics and base rates always use the full loaded history.")
string detail = input.string("Balanced", "Profile Detail", group = GRP_D, options = ["Coarse", "Balanced", "Fine"], tooltip = "Sets the TARGET resolution, not a bin count. Bin height is derived from ATR at the window anchor — Coarse 0.50 ATR, Balanced 0.25 ATR, Fine 0.125 ATR per bin — so the number of bins follows the window's range-to-ATR ratio and adapts per symbol and timeframe. If a window's range outgrows the internal cap, bins merge 2:1 and the height doubles.")
int atrLen = input.int(14, "ATR Length", group = GRP_D, minval = 5, maxval = 50, tooltip = "ATR lookback used to derive the bin height at each window anchor and to express POC migration distance.")
int vaPct = input.int(70, "Value Area %", group = GRP_D, minval = 50, maxval = 90, tooltip = "Share of the window's volume the Value Area encloses. Built by greedy expansion from the POC bin, one bin at a time toward the heavier side.")
bool trackNodes = input.bool(true, "Track POC / HVN as Nodes", group = GRP_N, tooltip = "When a window commits, its POC and the strongest HVNs arm as horizontal levels. Every return is then tracked on confirmed bars: armed → accepted / rejected. Unresolved nodes expire when the next window commits.")
int acceptN = input.int(2, "Acceptance Closes", group = GRP_N, minval = 1, maxval = 6, tooltip = "Confirmed closes inside the node zone (node center ± half an ATR, never thinner than one bin) required to call a retest ACCEPTED. A probe through the node center that closes outside the zone, or an entry that leaves before the required closes, is REJECTED. Edge grazes resolve nothing.")
int hvnMax = input.int(2, "HVN Nodes per Window", group = GRP_N, minval = 0, maxval = 3, tooltip = "How many High Volume Nodes arm per committed window, besides the POC. An HVN is a local peak of the profile holding at least half of the POC volume.")
bool showLvn = input.bool(true, "Thin Zones (LVN)", group = GRP_N, tooltip = "Shades the committed window's Thin Zones (LVN) — contiguous runs of bins holding 20% or less of the average bin volume. Context only: no state machine, no alerts.")
int marksKeep = input.int(12, "Resolved Marks to Keep", group = GRP_N, minval = 4, maxval = 24, tooltip = "How many resolved ✓ / ✕ node marks (and their recolored level lines) stay on the chart. Older marks are removed to keep dense stretches readable; base-rate statistics are not affected.")
bool showProf = input.bool(true, "Committed Profiles", group = GRP_R, tooltip = "Draws the final histogram of each committed window, with the Value Area shaded behind it.")
bool showLive = input.bool(true, "Live Developing Profile", group = GRP_R, tooltip = "Histogram of the current, still-forming window. Redraws as the window grows — visual context, not a signal.")
int profWidth = input.int(30, "Profile Width (% of window)", group = GRP_R, minval = 10, maxval = 60, tooltip = "Horizontal footprint of the histogram as a share of its window's bar count.")
bool showDev = input.bool(true, "Developing POC / Value Area", group = GRP_R, tooltip = "Draws the developing POC step-trail and the developing Value Area band for the ACTIVE window, recomputed on every confirmed bar. Committed windows keep their final POC / VAH / VAL lines instead, so history stays clean.")
bool showMig = input.bool(true, "POC Migration Links", group = GRP_R, tooltip = "Dotted link and distance label between the final POCs of consecutive windows.")
bool glowOn = input.bool(true, "Glow Effects", group = GRP_R, tooltip = "Soft underglow beneath POC and node lines. Purely cosmetic.")
color colBody = input.color(VN_BODY_DEF, "Profile", group = GRP_R, inline = "c1", tooltip = "Profile body — bin brightness follows volume share.")
color colPoc = input.color(VN_POC_DEF, "POC", group = GRP_R, inline = "c1", tooltip = "Point of Control and its migration trail.")
color colAcc = input.color(VN_ACC_DEF, "Accepted", group = GRP_R, inline = "c2", tooltip = "Node retest resolved as accepted.")
color colRej = input.color(VN_REJ_DEF, "Rejected", group = GRP_R, inline = "c2", tooltip = "Node retest resolved as rejected.")
bool showPanel = input.bool(true, "Statistics Panel", group = GRP_ST, tooltip = "Window status, developing value, node states and the measured base rates.")
string panelPos = input.string("Top Right", "Position", group = GRP_ST, options = ["Top Right", "Top Left", "Bottom Right", "Bottom Left"], tooltip = "Corner of the chart the panel is pinned to.")
string panelSize = input.string("Small", "Text Size", group = GRP_ST, options = ["Tiny", "Small", "Normal"], tooltip = "Panel text size.")
int CHART_SEC = timeframe.in_seconds()
string anchorPick = anchorMode == "Auto" ? (timeframe.isintraday ? (CHART_SEC <= 1800 ? "D" : "W") : timeframe.isdaily ? "M" : "12M") : anchorMode == "Day" ? "D" : anchorMode == "Week" ? "W" : anchorMode == "Month" ? "M" : "3M"
string ANCHOR = anchorPick
if ANCHOR == "D" and timeframe.in_seconds("D") <= CHART_SEC
ANCHOR := "W"
if ANCHOR == "W" and timeframe.in_seconds("W") <= CHART_SEC
ANCHOR := "M"
if ANCHOR == "M" and timeframe.in_seconds("M") <= CHART_SEC
ANCHOR := "3M"
if ANCHOR == "3M" and timeframe.in_seconds("3M") <= CHART_SEC
ANCHOR := "12M"
string anchName = ANCHOR == "D" ? "Daily" : ANCHOR == "W" ? "Weekly" : ANCHOR == "M" ? "Monthly" : ANCHOR == "3M" ? "Quarterly" : "Yearly"
bool newWindow = timeframe.change(ANCHOR)
f_px(float v) =>
na(v) ? "—" : str.tostring(v, format.mintick)
f_rate(int c, int n, int minN) =>
n >= minN ? str.tostring(100.0 * c / n, "#") + "%" : "collecting"
f_trimBoxes(array<box> a, int maxN) =>
while a.size() > maxN
box.delete(a.shift())
f_trimLines(array<line> a, int maxN) =>
while a.size() > maxN
line.delete(a.shift())
f_trimLabels(array<label> a, int maxN) =>
while a.size() > maxN
label.delete(a.shift())
f_triCdf(float L, float H, float C, float x) =>
float r = H - L
float out = na
if r <= 0
out := x > H ? 1.0 : 0.0
else if x <= L
out := 0.0
else if x >= H
out := 1.0
else if x <= C
out := (x - L) * (x - L) / (r * (C - L))
else
out := 1.0 - (H - x) * (H - x) / (r * (H - C))
out
f_stateTxt(int st) =>
st == 2 ? "testing" : st == 3 ? "accepted" : st == 4 ? "rejected" : "armed"
type VNode
string kind
float lvl
float zLo
float zHi
int state
int streak
line ln
line glow
label tag
var array<float> binVol = array.new<float>()
var float gridLo = na
var float binH = na
var int wStart = na
var float devPoc = na
var float devVah = na
var float devVal = na
var float priorPoc = na // final POC of the previous committed window
var bool fRevisit = false
var int cRevisit = 0
var int nRevisit = 0
var float lastPocPrice = na // for migration links
var int lastPocBar = na
var bool sawVol = false
var bool everCommitted = false
var int cPocT = 0
var int cPocA = 0
var int cHvnT = 0
var int cHvnR = 0
var array<VNode> liveNodes = array.new<VNode>()
var array<box> profBoxes = array.new<box>()
var array<int> profCounts = array.new<int>()
var array<box> lvnBoxes = array.new<box>()
var array<box> liveBoxes = array.new<box>()
var array<line> winLines = array.new<line>()
var array<label> winLabels = array.new<label>()
var array<line> nodeLines = array.new<line>()
var array<label> nodeLabels = array.new<label>()
var label tagVah = label(na)
var label tagVal = label(na)
var label tagPoc = label(na)
var array<chart.point> trailPts = array.new<chart.point>()
var float lastTrailPoc = na
var polyline trailPl = na
var box devVaBx = box(na)
var string TT_NODE = "Armed when its window committed. Returns are tracked on confirmed bars only: " + str.tostring(acceptN) + " confirmed close(s) inside the zone (center ± half an ATR, never thinner than one bin) = accepted · a probe through the node CENTER that closes outside the zone, or an entry that leaves before that, = rejected. A graze of the zone edge that neither trades the center nor closes inside resolves nothing. Unresolved nodes expire when the next window commits."
float atr = ta.atr(atrLen)
float detailK = detail == "Coarse" ? 0.5 : detail == "Balanced" ? 0.25 : 0.125
bool committedNow = false
bool accNow = false
bool rejNow = false
bool revisitNow = false
string accTxt = ""
string rejTxt = ""
if newWindow and not na(wStart) and binVol.size() > 0 and not na(devPoc)
committedNow := true
everCommitted := true
int nB = binVol.size()
int wEnd = bar_index - 1
int pocI = 0
float vMax = 0.0
float vSum = 0.0
int nnz = 0
int i0 = 0
while i0 < nB
float v = binVol.get(i0)
vSum += v
if v > 0
nnz += 1
if v > vMax
vMax := v
pocI := i0
i0 += 1
if not na(priorPoc)
nRevisit += 1
if fRevisit
cRevisit += 1
float aRef = nz(atr, binH * 4)
if showMig and not na(lastPocPrice) and aRef > 0
string mGl = devPoc > lastPocPrice ? "▲" : devPoc < lastPocPrice ? "▼" : "◆"
string mTxt = "POC " + mGl + " " + str.tostring(math.abs(devPoc - lastPocPrice) / aRef, "#.##") + " ATR · " + str.tostring(100.0 * math.abs(devPoc - lastPocPrice) / lastPocPrice, "#.##") + "% vs prior"
winLines.push(line.new(lastPocBar, lastPocPrice, wEnd, devPoc, color = color.new(colPoc, 50), style = line.style_dotted))
winLabels.push(label.new(wEnd, (devPoc + lastPocPrice) / 2, mTxt, style = label.style_none, color = color.new(colPoc, 100), textcolor = color.new(colPoc, 30), size = size.small, tooltip = "How far the Point of Control migrated between the previous committed window and this one, in ATR units. Value building higher or lower is the window-to-window read of this profile."))
int winBars = wEnd - wStart
int rowSpan = math.max(4, int(math.round(winBars * profWidth / 100.0)))
if showProf and vMax > 0
int rows = 0
profBoxes.push(box.new(wStart, devVah, wEnd, devVal, border_color = color.new(colBody, 100), bgcolor = color.new(colBody, 95)))
rows += 1
int i1 = 0
while i1 < nB
float v = binVol.get(i1)
if v > 0
int rowLen = math.max(1, int(math.round(rowSpan * v / vMax)))
float yLo = gridLo + i1 * binH
bool isPoc = i1 == pocI
int rowTr = int(math.round(86.0 - 62.0 * v / vMax))
profBoxes.push(box.new(wStart, yLo + binH, wStart + rowLen, yLo, border_color = color.new(colBody, 100), bgcolor = color.new(isPoc ? colPoc : colBody, isPoc ? 20 : rowTr)))
rows += 1
i1 += 1
profCounts.push(rows)
while profCounts.size() > keepProfiles
int k0 = profCounts.shift()
int j0 = 0
while j0 < k0
box.delete(profBoxes.shift())
j0 += 1
label.delete(tagVah)
label.delete(tagVal)
label.delete(tagPoc)
winLines.push(line.new(wStart, devPoc, wEnd, devPoc, color = color.new(colPoc, 15), width = 2))
if glowOn
winLines.push(line.new(wStart, devPoc, wEnd, devPoc, color = color.new(colPoc, 86), width = 6))
winLines.push(line.new(wStart, devVah, wEnd, devVah, color = color.new(colBody, 45), style = line.style_dashed))
winLines.push(line.new(wStart, devVal, wEnd, devVal, color = color.new(colBody, 45), style = line.style_dashed))
tagVah := label.new(wEnd, devVah, "VAH · Value Area High", style = label.style_label_right, color = color.new(colBody, 100), textcolor = color.new(colBody, 35), size = size.tiny, tooltip = "Upper edge of the price band holding " + str.tostring(vaPct) + "% of the committed window's volume.")
tagVal := label.new(wEnd, devVal, "VAL · Value Area Low", style = label.style_label_right, color = color.new(colBody, 100), textcolor = color.new(colBody, 35), size = size.tiny, tooltip = "Lower edge of the price band holding " + str.tostring(vaPct) + "% of the committed window's volume.")
if not trackNodes
tagPoc := label.new(wEnd, devPoc, "POC · High Volume Node", style = label.style_label_right, color = color.new(colPoc, 100), textcolor = color.new(colPoc, 25), size = size.tiny, tooltip = "Point of Control — the single price bin that traded the most volume in the committed window.")
if showLvn and nnz > 0
float thrLvn = 0.2 * vSum / nnz
int runS = -1
int bestS1 = -1
int bestL1 = 0
int bestS2 = -1
int bestL2 = 0
int i2 = 1
while i2 < nB - 1
bool thin = binVol.get(i2) <= thrLvn
if thin and runS < 0
runS := i2
if runS >= 0 and (not thin or i2 == nB - 2)
int runE = thin ? i2 : i2 - 1
int rl = runE - runS + 1
if rl > bestL1
bestS2 := bestS1
bestL2 := bestL1
bestS1 := runS
bestL1 := rl
else if rl > bestL2
bestS2 := runS
bestL2 := rl
runS := -1
i2 += 1
if bestL1 > 1
lvnBoxes.push(box.new(wStart, gridLo + (bestS1 + bestL1) * binH, wEnd, gridLo + bestS1 * binH, border_color = color.new(colBody, 88), border_style = line.style_dashed, bgcolor = color.new(colBody, 96), text = "LVN · Thin Zone", text_size = size.tiny, text_color = color.new(colBody, 55), text_halign = text.align_left))
if bestL2 > 1
lvnBoxes.push(box.new(wStart, gridLo + (bestS2 + bestL2) * binH, wEnd, gridLo + bestS2 * binH, border_color = color.new(colBody, 88), border_style = line.style_dashed, bgcolor = color.new(colBody, 96), text = "LVN · Thin Zone", text_size = size.tiny, text_color = color.new(colBody, 55), text_halign = text.align_left))
f_trimBoxes(lvnBoxes, keepProfiles * 2)
while liveNodes.size() > 0
VNode nd0 = liveNodes.pop()
line l0 = nd0.ln
line g0 = nd0.glow
if not na(l0)
l0.set_style(line.style_dotted)
l0.set_color(color.new(colBody, 80))
nodeLines.push(l0)
if not na(g0)
g0.set_color(color.new(colBody, 96))
nodeLines.push(g0)
label.delete(nd0.tag)
if trackNodes
float zHalf = math.max(binH, 0.5 * aRef)
line pLn = line.new(bar_index, devPoc, bar_index + 1, devPoc, color = color.new(colPoc, 20), width = 2)
line pGl = glowOn ? line.new(bar_index, devPoc, bar_index + 1, devPoc, color = color.new(colPoc, 84Показано первые 50% кода (символов: 23409)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.