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

SMC Order Block Scorer

indicator smc order block scorer for tradingview.pine
Вы автор или правообладатель?

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

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

О программе

Индикатор «SMC Order Block Scorer» анализирует рыночную структуру на основе свинг-пивотов, определяя сигналы Break of Structure (BOS) и Change of Character (CHoCH). Он автоматически находит Order Blocks — последние свечи противоположного направления перед структурным пробоем — и оценивает каждый из них по шкале от 0 до 100 на основе профилей объёма (POC, Value Area, HVN), всплесков объёма и величины смещения. Order Blocks получают буквенную оценку от A+ до C и отображаются на графике в виде цветных блоков.

Встроенный профиль объёма отображает зоны POC, Value Area и High Volume Node с возможностью выделения HVN по всей шкале графика. Система митигации отслеживает пересечение ценой ранее созданных Order Blocks и позволяет скрыть или «затушить» их в зависимости от выбранного триггера. Индикатор также содержит таблицу статуса с ранжированием активных Order Blocks по оценке и набор условных оповещений для CHoCH, BOS, новых Order Blocks и событий митигации.

Примечание: оценка Order Blocks представляет собой правила-based рейтинг конфлюэнса, а не результат бэктеста или вероятностную модель. Индикатор работает поверх графика и не выполняет симуляцию торговых операций.

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

НастройкаОписание
swingLen Длина отступа (количество баров) для поиска основных свинг-пивотов, определяющих структуру BOS/CHoCH и триггер появления Order Blocks.
showStructure Главный переключатель: включает или отключает отображение всей рыночной структуры (BOS, CHoCH, линии).
showBOS Включает или отключает отображение меток Break of Structure (BOS) на графике.
showCHoCH Включает или отключает отображение меток Change of Character (CHoCH) на графике.
showLines Включает или отключает отрисовку линий разрыва структуры (продолжение уровня пивота при BOS/CHoCH).
bullColor Цвет отрисовки элементов и меток бычьего направления (ростящий тренд).
bearColor Цвет отрисовки элементов и меток медвежьего направления (нисходящий тренд).
showInt Включает или отключает отображение внутренней структуры (мелких пивотов) — косметическая функция.
intLen Длина отступа (количество баров) для поиска внутренних свинг-пивотов, используемых только в косметических целях.
intColor Цвет меток внутренней структуры (мелких пивотов), если соответствующая настройка включена.
showOB Включает или отключает автоматическое обнаружение и отображение Order Blocks.
obMax Максимальное количество одновременно отображаемых Order Blocks на одну сторону (бычью или медвежью).
obLookback Количество баров назад, в пределах которых ищется последняя противоположная свеча для формирования Order Block.
mitigateBy Тип триггера митигации: Touch — цена касается зоны, 50% — цена достигает середины зоны, Wick — свеча проходит через дальнюю сторону, Close — свеча закрывается за дальней стороной.
showMitigated Если включено, митигированные (затушённые) Order Block остаются на графике в сером цвете вместо удаления.
hideOverlap Если включено, новые Order Blocks не создаются при перекрытии зоной другого Order Blocks того же направления.
obShowMid Если включено, для каждого Order Block отображается пунктирная линия на уровне 50% (середина зоны).
minScore Минимальная оценка Order Block: блоки с оценкой ниже этого значения не отображаются на графике.
showLabels Включает или отключает текстовые метки с оценкой и классом на Order Blocks.
labelSizeIn Размер меток Order Blocks на графике: tiny, small или normal.
showProfile Включает или отключает отображение профиля объёма на графике.
showHvnZones Если включено, зоны High Volume Node (HVN) выделяются заливкой на всём графике, а не только в профиле.
profLookback Количество баров назад, используемых для построения профиля объёма.
profRows Количество строк (уровней), на которые разбивается диапазон цен профиля объёма.
vaPct Процент объёма, определяющий границы Value Area (например, 70 означает, что Value Area охватывает 70% объёма).
hvnMult Множитель для определения HVN: строка профиля считается зоной высокого объёма, если её объём превышает средний объём строки, умноженный на это значение.
profWidth Ширина столбцов профиля объёма в барах.
profOffset Смещение столбцов профиля объёма от последнего бара графика (вправо).
volLen Период скользящей средней для расчёта среднего объёма, используемый при определении всплесков объёма.
volMult Множитель для определения всплеска объёма: текущий объём считается всплеском, если превышает среднее, умноженное на это значение.
wPOC Вес (бонусные баллы), добавляемый к оценке Order Block при наличии POC внутри зоны.
wVA Вес (бонусные баллы), добавляемый к оценке Order Block при пересечении зоны Value Area.
wHVN Вес (бонусные баллы), добавляемый к оценке Order Block при пересечении зоны HVN.
pocCol Цвет отрисовки и маркировки зоны Point of Control (POC) в профиле объёма.
vaCol Цвет отрисовки и заливки зоны Value Area в профиле объёма.
hvnCol Цвет заливки и маркировки зон High Volume Node (зон с высоким объёмом).
nvCol Цвет для строк профиля объёма, не являющихся POC, Value Area или HVN.
showTable Включает или отключает таблицу статуса с ранжированием активных Order Blocks по оценке.
tablePos Позиция таблицы статуса на графике: верхний правый, верхний левый, нижний правый или нижний левый угол.
Получить полный код

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

indicator("SMC Order Block Scorer", shorttitle="SMC OB Scorer", overlay=true, max_boxes_count=500, max_lines_count=500, max_labels_count=500, max_bars_back=1000)

grpSwing   = "Swing Structure (drives CHoCH / BOS / OB)"
swingLen      = input.int(50, "Swing Lookback (pivot strength)", minval=2, group=grpSwing)
showStructure = input.bool(true, "Show market structure (master toggle)", group=grpSwing)
showBOS       = input.bool(true, "Show BOS labels", group=grpSwing)
showCHoCH     = input.bool(true, "Show CHoCH labels", group=grpSwing)
showLines     = input.bool(true, "Draw structure break lines", group=grpSwing)
bullColor     = input.color(color.new(color.teal, 0), "Bullish color", group=grpSwing)
bearColor     = input.color(color.new(color.red, 0), "Bearish color", group=grpSwing)

grpInt     = "Internal Structure (optional, cosmetic only)"
showInt    = input.bool(false, "Show internal structure (minor pivots)", group=grpInt)
intLen     = input.int(5, "Internal Lookback (pivot strength)", minval=1, group=grpInt)
intColor   = input.color(color.new(color.gray, 55), "Internal label color", group=grpInt)

grpOB      = "Order Blocks"
showOB     = input.bool(true, "Show Order Blocks", group=grpOB)
obMax      = input.int(10, "Max active OBs per side", minval=1, maxval=50, group=grpOB)
obLookback = input.int(50, "OB search lookback (bars)", minval=5, maxval=200, group=grpOB)
mitigateBy = input.string("Touch", "Mitigation trigger", options=["Touch", "50%", "Wick", "Close"], group=grpOB, tooltip="Touch = price revisits the zone (any wick inside)\n50% = price reaches the middle of the zone\nWick = wick trades through the far side\nClose = candle closes beyond the far side")
showMitigated = input.bool(false, "Keep mitigated OBs (faded)", group=grpOB)
hideOverlap   = input.bool(true, "Skip OBs overlapping a same-side OB", group=grpOB)
obShowMid  = input.bool(true, "Show OB 50% equilibrium line", group=grpOB)
minScore   = input.float(0, "Hide OBs below score", minval=0, maxval=100, group=grpOB)
showLabels = input.bool(true, "Show OB labels", group=grpOB)
labelSizeIn = input.string("small", "Label size", options=["tiny", "small", "normal"], group=grpOB)

grpVP      = "Volume Profile / Zones"
showProfile  = input.bool(true, "Show volume profile", group=grpVP)
showHvnZones = input.bool(true, "Shade HVN zones across chart", group=grpVP)
profLookback = input.int(150, "Profile lookback (bars)", minval=30, maxval=500, group=grpVP)
profRows     = input.int(30, "Profile rows", minval=10, maxval=80, group=grpVP)
vaPct        = input.float(70, "Value area %", minval=50, maxval=95, group=grpVP) / 100.0
hvnMult      = input.float(1.3, "HVN threshold (x avg row volume)", minval=1.0, step=0.1, group=grpVP)
profWidth    = input.int(25, "Profile width (bars)", minval=5, maxval=100, group=grpVP)
profOffset   = input.int(6, "Profile offset from last bar", minval=1, maxval=100, group=grpVP)

grpVol     = "Volume Confirmation"
volLen     = input.int(20, "Volume average length", minval=1, group=grpVol)
volMult    = input.float(1.5, "Spike threshold (x average)", minval=0.1, step=0.1, group=grpVol)

grpW       = "Scoring weights"
wPOC       = input.float(25, "OB contains POC", minval=0, group=grpW)
wVA        = input.float(15, "OB overlaps Value Area", minval=0, group=grpW)
wHVN       = input.float(20, "OB overlaps HVN (extra credit)", minval=0, group=grpW)

grpSty     = "Profile colors"
pocCol     = input.color(#ff3d71, "POC", group=grpSty, inline="p1")
vaCol      = input.color(#4c8dff, "Value area", group=grpSty, inline="p1")
hvnCol     = input.color(#ffb300, "HVN", group=grpSty, inline="p2")
nvCol      = input.color(#7b8494, "Other rows", group=grpSty, inline="p2")

grpInfo    = "Info Table"
showTable  = input.bool(true, "Show status table", group=grpInfo)
tablePos   = input.string("Top Right", "Table position", options=["Top Right", "Top Left", "Bottom Right", "Bottom Left"], group=grpInfo)

var string txtSz = labelSizeIn == "tiny" ? size.tiny : labelSizeIn == "normal" ? size.normal : size.small
var string posMap = tablePos == "Top Right" ? position.top_right : tablePos == "Top Left" ? position.top_left : tablePos == "Bottom Right" ? position.bottom_right : position.bottom_left

type Profile
    array<float> vols
    array<bool>  hvn
    float lo
    float step
    int   pocIdx
    int   vahIdx
    int   valIdx
    float total

type OB
    box    bx
    line   ml
    label  lb
    bool   bull
    float  top
    float  bot
    float  score
    string txt

float atrVal = ta.atr(14)
float volAvg = ta.sma(volume, volLen)
bool  volSpike = volume > volAvg * volMult

var array<OB>    obs        = array.new<OB>()
var array<box>   profBoxes  = array.new<box>()
var array<line>  profLines  = array.new<line>()
var array<label> profLabels = array.new<label>()

f_buildProfile(int lookback, int rows, float vaFrac, float hvnMul) =>
    int n = math.min(lookback, bar_index + 1)
    float hiP = high
    float loP = low
    for i = 0 to n - 1
        hiP := math.max(hiP, high[i])
        loP := math.min(loP, low[i])
    float stp = math.max((hiP - loP) / rows, syminfo.mintick)
    array<float> vols = array.new<float>(rows, 0.0)
    for i = 0 to n - 1
        float bl  = low[i]
        float bh  = high[i]
        float v   = nz(volume[i])
        float rng = math.max(bh - bl, syminfo.mintick)
        int i0 = math.max(0, math.min(rows - 1, int(math.floor((bl - loP) / stp))))
        int i1 = math.max(0, math.min(rows - 1, int(math.floor((bh - loP) / stp))))
        for r = i0 to i1
            float rl = loP + r * stp
            float rh = rl + stp
            float sh = i0 == i1 ? 1.0 : math.max(0.0, math.min(bh, rh) - math.max(bl, rl)) / rng
            vols.set(r, vols.get(r) + v * sh)

    float total = vols.sum()
    int poc = vols.indexof(vols.max())

    int up = poc
    int dn = poc
    float acc = vols.get(poc)
    while acc < total * vaFrac and (up < rows - 1 or dn > 0)
        float vu = up < rows - 1 ? vols.get(up + 1) : -1.0
        float vd = dn > 0 ? vols.get(dn - 1) : -1.0
        if vu >= vd
            up += 1
            acc += vu
        else
            dn -= 1
            acc += vd

    array<bool> hvn = array.new<bool>(rows, false)
    float avg = total / rows
    for r = 0 to rows - 1
        float v  = vols.get(r)
        float pv = r > 0 ? vols.get(r - 1) : 0.0
        float nx = r < rows - 1 ? vols.get(r + 1) : 0.0
        if total > 0 and v >= avg * hvnMul and v >= pv and v >= nx
            hvn.set(r, true)

    Profile.new(vols, hvn, loP, stp, poc, up, dn, total)

f_confluence(Profile p, float zTop, float zBot) =>
    bool hasPoc = false
    bool hasHvn = false
    float share = 0.0
    float tot = p.total
    if tot > 0
        for r = 0 to p.vols.size() - 1
            float rl = p.lo + r * p.step
            float rh = rl + p.step
            if rl < zTop and rh > zBot
                share += p.vols.get(r) * (math.min(zTop, rh) - math.max(zBot, rl)) / p.step
                if r == p.pocIdx
                    hasPoc := true
                if p.hvn.get(r)
                    hasHvn := true
    float vaLo = p.lo + p.valIdx * p.step
    float vaHi = p.lo + (p.vahIdx + 1) * p.step
    bool inVa = tot > 0 and zBot < vaHi and zTop > vaLo
    float shr = tot > 0 ? share / tot : 0.0
    [hasPoc, inVa, hasHvn, shr]

f_overlap(bool bull, float t, float b) =>
    bool res = false
    if obs.size() > 0
        for i = 0 to obs.size() - 1
            OB o = obs.get(i)
            if o.bull == bull and t > o.bot and b < o.top
                res := true
    res

f_kill(OB o) =>
    box.delete(o.bx)
    line.delete(o.ml)
    label.delete(o.lb)
    true

f_findOB(bool bull) =>
    float obH = na
    float obL = na
    int   obB = na
    for i = 1 to obLookback
        bool opp = bull ? close[i] < open[i] : close[i] > open[i]
        if opp
            obH := high[i]
            obL := low[i]
            obB := bar_index - i
            break
    [obH, obL, obB]

f_createOB(bool bull, float zTop, float zBot, int zBar, bool isChoch, bool spike) =>
    float atrv = nz(atrVal, syminfo.mintick)
    bool made = false
    bool ovl = hideOverlap and f_overlap(bull, zTop, zBot)
    if not ovl
        Profile p = f_buildProfile(profLookback, profRows, vaPct, hvnMult)
        [hasPoc, inVa, hasHvn, share] = f_confluence(p, zTop, zBot)

        int off = bar_index - zBar
        float vRatio  = nz(volume[off]) / math.max(nz(volAvg[off]), 1e-10)
        float ptsVol  = math.min(vRatio / 2.0, 1.0) * 5.0 + (spike ? 5.0 : 0.0)
        float dispAtr = bull ? (close - zBot) / atrv : (zTop - close) / atrv
        float ptsDisp = math.min(math.max(dispAtr / 4.0, 0.0), 1.0) * 10.0
        float ptsStr  = isChoch ? 6.0 : 10.0
        float ptsShr  = math.min(share / 0.15, 1.0) * 10.0
        float raw     = ptsStr + ptsVol + ptsDisp + ptsShr + (hasPoc ? wPOC : 0.0) + (inVa ? wVA : 0.0) + (hasHvn ? wHVN : 0.0)
        float maxRaw  = 40.0 + wPOC + wVA + wHVN
        float score   = math.min(100.0, raw / maxRaw * 100.0)

        if score >= minScore
            color base = bull ? bullColor : bearColor
            int bgT = score >= 75 ? 66 : score >= 60 ? 76 : score >= 45 ? 85 : 92
            int brT = score >= 75 ? 10 : score >= 60 ? 30 : score >= 45 ? 50 : 70
            string grade = score >= 75 ? "A+" : score >= 60 ? "A" : score >= 45 ? "B" : "C"
            array<string> tg = array.new<string>()
            if hasPoc
                tg.push("POC")
            if inVa
                tg.push("VA")
            if hasHvn
                tg.push("HVN")
            string tags = tg.join(" · ")
            string txt = (bull ? "▲ " : "▼ ") + grade + " " + str.tostring(math.round(score)) + "%" + (tags == "" ? "" : "\n" + tags)
            float midY = (zTop + zBot) / 2

            box bx = box.new(zBar, zTop, bar_index + 20, zBot, border_color=color.new(base, brT), border_width=1, bgcolor=color.new(base, bgT))
            line ml = obShowMid ? line.new(zBar, midY, bar_index + 20, midY, color=color.new(base, 30), style=line.style_dotted) : na
            label lb = showLabels ? label.new(bar_index + 20, midY, txt, style=label.style_label_left, color=color.new(base, 35), textcolor=color.white, size=txtSz) : na

            obs.push(OB.new(bx, ml, lb, bull, zTop, zBot, score, txt))

            int cnt = 0
            for q in obs
                if q.bull == bull
                    cnt += 1
            while cnt > obMax
                for i = 0 to obs.size() - 1
                    OB old = obs.get(i)
                    if old.bull == bull
                        f_kill(old)
                        obs.remove(i)
                        cnt -= 1
                        break
            made := true
    made
var table wm = table.new(position.bottom_right, 1, 1)
if barstate.isfirst
    table.cell(wm, 0, 0, "Telegram @SimpleForexTools", text_color = color.new(color.gray, 70), text_size = size.large)

float inPH = ta.pivothigh(high, intLen, intLen)
float inPL = ta.pivotlow(low, 

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

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

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

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

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

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

Стоимость полного кода
1 614,20₽ ≈ $19.73