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

CTZ Swing Exhaustion Levels

indicator ctz swing exhaustion levels for tradingview.pine
Поделиться этим товаромОтправьте ссылку на карточку
VK Telegram MAX WhatsApp
Вы автор или правообладатель?

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

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

О программе

CTZ Swing Exhaustion Levels — индикатор анализа и отображения для TradingView (Pine Script v6), который отслеживает свечные swing-структуры (свинг-хаи и свинг-лоу) и рассчитывает уровни истощения с вероятностными прогнозами. Свинг завершается, когда цена возвращается на расстояние k ATR(14) от экстремума, а вероятности достижения уровней и разворота рассчитываются на основе истории свингов текущего графика. Индикатор отображает линии уровней (50%, 75%, 90%), временное окно, зигзаг, теги структуры и информационную панель с показателями. Встроен ядерный регрессионный тренд на основе метода Надарая—Уотсона (рационально-квадратичное + гауссово ядро), а также сигналы совпадения свинг- и тренд-анализа с поддержкой оповещений.

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

НастройкаОписание
mktSel Выбор рынка: Auto (автоматическое определение крипто), Crypto или Other markets. Влияет на параметры k для свингов.
presetSel Размер свинга: Micro, Standard, Major или Custom. Определяет коэффициент k ATR для завершения свинга (Micro k=1.5/2.0, Standard k=2.5/3.5, Major k=4.0/5.5 — для обычных/крипто рынков).
warmIn Количество сохранённых свингов в каждом направлении, необходимое перед тем, как прогнозы считаются готовыми (ready). Больше — стабильнее прогнозы, дольше прогрев.
kCustom Коэффициент k в кратных ATR для режима «Custom» — расстояние от экстремума свинга, при котором свинг считается завершённым.
nCustom Длина ATR в барах для режима «Custom» (по умолчанию 14).
srcSel Источник для определения экстремумов свинга: Wicks (максимумы/минимумы свечей) или Closes (только закрытия). ATR всегда рассчитывается по true range.
showLv Включение/отключение отображения линий уровней истощения (50%, 75%, 90% за пределами экстремума свинга) с вероятностями.
lvLen Количество баров вправо, на которое отображаются линии уровней истощения.
showWin Включение/отключение отображения временного окна (полосы, в которой половина свингов данного размера завершилась).
cardSel Положение информационной панели с показателями (odds panel) на графике.
showTags Отображение меток структуры (HH/LH/HL/LL) и размера свинга в ATR при каждом подтверждённом пивоте.
themeSel Цветовая тема индикатора: Neon, Classic или Custom. При Neon и Classic цвета задаются встроенными, при Custom — параметрами ниже.
upIn Цвет восходящих (up) свингов и маркеров в режиме «Neon» и «Classic».
dnIn Цвет нисходящих (down) свингов и маркеров в режиме «Neon» и «Classic».
accIn Цвет индикатора часов (временного окна) в режиме «Neon» и «Classic».
showZig Включение/отключение отображения зигзага — линий, соединяющих подтверждённые пивоты.
zigT Прозрачность линий зигзага в процентах (0–90).
glowOn Включение/отключение свечения (glow) линий зигзага — широкая полупрозрачная линия под каждой ногой зигзага.
tintSel Режим окраски свечей: Swing (по текущему свингу — бледные при рождении, насыщенные при достижении 50%), Kernel trend (по ядерному тренду) или Off.
showLive Отображение тега текущего (живого) свинга рядом с последним баром с информацией о размере и возрасте.
showKr Включение/отключение отображения линий ядерной регрессионной оценки и сигнала на графике.
krFillOn Включение/отключение заливки области между ядерной оценкой и ядерным сигналом.
krSrc Источник данных для расчёта ядерной регрессионного тренда.
krH Длина окна обратного отсчёта (lookback) для ядерной регрессии, в барах. Рекомендуется 3–50. Больше — медленнее и плавнее тренд.
krR Относительный весовой коэффициент для рационально-квадратичного ядра. Рекомендуется 0.25–25. Меньше — больше веса долгосрочным движениям.
krX Количество баров, используемых в оценке регрессии (regression level), в барах. Рекомендуется 2–25.
krLag Задержка сигнала для гауссова компонента ядерного тренда, в барах.
showSig Отображение маркеров совпадения свинг- и тренд-сигналов: стрелки при совпадении зоны разворота с изменением ядерного тренда и метки при подтверждении свинга.
alKr Оповещение при совпадении свинг- и тренд-сигналов (совпадение зоны разворота с изменением ядерного тренда).
alKrTr Оповещение при каждом изменении направления ядерного тренда.
alLevel Оповещение при достижении свингом одного из уровней (50%, 75% или 90%).
alOdds Оповещение при пересечении пороговой вероятности разворота или подтверждения (Turn/Conf odds cross).
alThr Процентный порог для оповещений пересечения вероятности (Turn/Conf odds cross), в процентах.
alLikely Оповещение при высокой вероятности разворота (Top/Bottom likely in, когда p_in >= 1 - alpha).
alConf Оповещение при подтверждении свинга (подтверждённый свинг высокого или низкого уровня).
alOverdue Оповещение при просрочке свинга (свинг вышел за пределы временного окна).
startTime Время начала расчётов: все данные (движок, таблицы) начинаются с первого бара на или после указанного времени.

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

indicator("CTZ Swing Exhaustion Levels", "CTZ Swing Exhaustion", overlay = true, max_lines_count = 500, max_boxes_count = 100, max_labels_count = 250)

grpE = "Swing"
mktSel    = input.string("Auto", "Market", options = ["Auto", "Crypto", "Other markets"], group = grpE,
     tooltip = "Auto uses the crypto presets on crypto charts. Crypto swings run further and wick harder, so a bigger pullback is needed before a swing counts as over.")
presetSel = input.string("Standard", "Swing size", options = ["Micro", "Standard", "Major", "Custom"], group = grpE,
     tooltip = "A swing ends when price comes back k ATR(14) from its extreme.\nCrypto: Micro k = 2.0, Standard k = 3.5, Major k = 5.5.\nOther markets: Micro k = 1.5, Standard k = 2.5, Major k = 4.0.")
warmIn    = input.int(20, "Swings needed before odds show", minval = 10, maxval = 60, group = grpE,
     tooltip = "Per direction. Bigger crypto swings mean fewer swings in the chart's history, so this is lower than the original 30. Higher = steadier odds, longer warm-up.")
kCustom   = input.float(2.5, "Custom k (ATR multiples)", minval = 0.5, step = 0.1, group = grpE)
nCustom   = input.int(14, "Custom ATR length", minval = 2, group = grpE)
srcSel    = input.string("Wicks", "Pivot source", options = ["Wicks", "Closes"], group = grpE,
     tooltip = "Closes: extremes and retraces use the close only. The ATR always uses the true range.")

grpD = "Display"
showLv    = input.bool(true, "Extension levels", group = grpD, inline = "lv",
     tooltip = "Three levels beyond the swing's extreme: of past swings on this chart that got as far as this one and kept going, 50%, 75% and 90% ended before them. Each label shows the chance that price tags the level from here, which also counts the chance that the swing is already over (Top in). The lines move only when the swing makes a new extreme; the odds update every bar. Red over an up swing, green under a down swing.")
lvLen     = input.int(30, "bars", minval = 5, maxval = 200, group = grpD, inline = "lv")
showWin   = input.bool(true, "Time window", group = grpD,
     tooltip = "Faint band over the bars in which half of such swings ended, set at the swing's birth. Dashed once the swing is past it.")
cardSel   = input.string("Bottom right", "Odds panel", options = ["Bottom right", "Top right", "Bottom left", "Top left", "Off"], group = grpD,
     tooltip = "Swing size and age, the time window, and the odds as bars, all from this chart's own history.")
showTags  = input.bool(true, "Structure labels", group = grpD,
     tooltip = "At each confirmed pivot: HH / LH / HL / LL and the swing size in ATR. Hover for the length in bars.")

grpS = "Style"
themeSel = input.string("Neon", "Theme", options = ["Neon", "Classic", "Custom"], group = grpS,
     tooltip = "Neon and Classic set the colours; Custom uses the three below.")
upIn  = input.color(#00e5b4, "Up", group = grpS, inline = "cu")
dnIn  = input.color(#ff4d6d, "Down", group = grpS, inline = "cu")
accIn = input.color(#ffb21e, "Clock", group = grpS, inline = "cu")
showZig = input.bool(true, "Zigzag", group = grpS, inline = "zig")
zigT    = input.int(10, "transparency", minval = 0, maxval = 90, group = grpS, inline = "zig")
glowOn  = input.bool(true, "Glow", group = grpS, inline = "zig")
tintSel = input.string("Swing", "Candle tint", options = ["Swing", "Kernel trend", "Off"], group = grpS,
     tooltip = "Swing: bars take the live swing's colour, faint at its birth and full strength as it reaches its 50% level. Kernel trend: bars take the kernel trend colour.")
showLive = input.bool(true, "Live swing tag", group = grpS)
color upCol  = themeSel == "Neon" ? #00e5b4 : themeSel == "Classic" ? #26a69a : upIn
color dnCol  = themeSel == "Neon" ? #ff4d6d : themeSel == "Classic" ? #ef5350 : dnIn
color accCol = themeSel == "Neon" ? #ffb21e : themeSel == "Classic" ? #f5b041 : accIn

grpK = "Kernel trend"
showKr   = input.bool(true, "Show kernel lines", group = grpK, inline = "kr")
krFillOn = input.bool(true, "Fill", group = grpK, inline = "kr")
krSrc    = input.source(close, "Source", group = grpK)
krH      = input.int(8, "Lookback window", minval = 3, group = grpK, tooltip = "Recommended 3-50. Higher = slower, smoother trend.")
krR      = input.float(8.0, "Relative weighting", minval = 0.25, step = 0.25, group = grpK, tooltip = "Recommended 0.25-25. Lower = more weight on longer-term moves.")
krX      = input.int(25, "Regression level", minval = 2, maxval = 200, group = grpK, tooltip = "Bars used in the estimate. Recommended 2-25.")
krLag    = input.int(2, "Signal lag", minval = 1, maxval = 10, group = grpK)
showSig  = input.bool(true, "Confluence signals (swing + trend)", group = grpK,
     tooltip = "KR ▲: a down swing is in its turn zone (or bottom likely in) and the kernel trend turns up. ✓ ▲: a swing low is confirmed while the kernel trend is up. Mirrored for tops.")
alKr     = input.bool(true, "Alert on confluence signals", group = grpK)
alKrTr   = input.bool(false, "Alert on every kernel trend change", group = grpK)

grpA = "Alerts (on bar close; create one alert with 'Any alert() function call')"
alLevel   = input.bool(true, "Swing tagged a level", group = grpA)
alOdds    = input.bool(false, "Turn / Conf odds cross", group = grpA, inline = "odds")
alThr     = input.float(65.0, "%", minval = 1, maxval = 99, group = grpA, inline = "odds")
alLikely  = input.bool(true, "Top / bottom likely in", group = grpA)
alConf    = input.bool(true, "Swing confirmed", group = grpA)
alOverdue = input.bool(false, "Overdue", group = grpA)

grpP = "Parity check"
startTime = input.time(timestamp("01 Jan 2000 00:00 +0000"), "Start at", group = grpP,
     tooltip = "Everything (engine, tables) starts on the first bar at or after this time. For parity exports: set it inside the exported range. Otherwise leave the default, which is the chart's first bar.")

bool  IS_CRYPTO = mktSel == "Crypto" or (mktSel == "Auto" and syminfo.type == "crypto")
float K      = presetSel == "Custom" ? kCustom : IS_CRYPTO ? (presetSel == "Micro" ? 2.0 : presetSel == "Major" ? 5.5 : 3.5) : (presetSel == "Micro" ? 1.5 : presetSel == "Major" ? 4.0 : 2.5)
int   NATR   = presetSel == "Custom" ? nCustom : 14
bool  CLOSES = srcSel == "Closes"
int   DISCARD  = 2                 // v0.2 2.3: the first two confirmed swings are not kept
float ALPHA    = 0.5               // coverage 50%
float M_HAZ    = 80.0              // bars; tuned in the study with the twin as the prior, not re-tuned for this build
float M_BAND   = 25.0
int   N_POOL   = 10
int   WARM     = warmIn            // kept swings per direction before forecasts count as ready (original: 30)
int   N_MAX    = 500
int   FULL_STEPS = 30
int   WARM_STEPS = 12
float DELTA    = 0.5
int   TF_SEC   = timeframe.in_seconds()
int   HZN      = TF_SEC <= 60 ? 5 : TF_SEC <= 900 ? 3 : 2     // Turn horizon N (v0.3.1 R2): 1m 5, 5m/15m 3, 30m/1h 2
int   N_LOW    = 25                // band sample below this: "low sample"

float CMP = 1e20
gtE(float a, float b) => (a - b) * CMP > 0
geE(float a, float b) => (a - b) * CMP >= 0
ltE(float a, float b) => (b - a) * CMP > 0
leE(float a, float b) => (b - a) * CMP >= 0
eqE(float a, float b) => (a - b) * CMP == 0
maxE(float a, float b) => ltE(a, b) ? b : a
minE(float a, float b) => gtE(a, b) ? b : a
absE(float a) => ltE(a, 0.0) ? -a : a

type Engine
    float k
    int   n
    bool  closes  = false
    int   nTr     = 0
    float trSum   = 0.0
    float rma     = na        // RMA(TR, n) before the floor
    float atr     = na        // after the floor
    float cPrev   = na
    bool  started = false
    int   sid     = 0
    float dir     = 1.0
    int   b0      = na
    float p0      = na
    float atr0    = na
    float pe      = na
    int   be      = na
    float atre    = na
    float deep    = na
    int   birth   = na
    bool  conf    = false     // a swing was confirmed on this bar
    int   cB0     = na        // the confirmed swing: pivots, direction, A, D
    int   cB1     = na
    float cP0     = na
    float cP1     = na
    float cDir    = na
    float cA      = na
    int   cD      = na

method step(Engine e, int t, float h, float l, float c, float floorV) =>

    float tr = na(e.cPrev) ? h - l : maxE(maxE(h - l, absE(h - e.cPrev)), absE(l - e.cPrev))
    e.nTr := e.nTr + 1
    if e.nTr < e.n
        e.trSum := e.trSum + tr
    else if e.nTr == e.n
        e.rma := (e.trSum + tr) / e.n
    else
        e.rma := (e.rma * (e.n - 1) + tr) / e.n
    e.atr := e.nTr >= e.n ? maxE(e.rma, floorV) : na
    e.cPrev := c
    float hh = e.closes ? c : h
    float ll = e.closes ? c : l
    e.conf := false
    if not e.started

        if not na(e.atr)
            e.started := true
            e.dir   := 1.0
            e.b0    := t
            e.p0    := ll
            e.atr0  := e.atr
            e.pe    := hh
            e.be    := t
            e.atre  := e.atr
            e.deep  := c
            e.birth := t
    else

        float d     = e.dir
        float hi    = d > 0 ? hh : -ll
        float lo    = d > 0 ? ll : -hh
        float cl    = d > 0 ? c : -c
        float peU   = e.pe * d
        float deepU = e.deep * d
        if gtE(hi, peU)                   // step 1, extension
            peU    := hi
            e.be   := t
            e.atre := e.atr
            deepU  := cl
        else                              // step 2
            deepU := minE(deepU, lo)
        e.pe   := peU * d
        e.deep := deepU * d
        if geE(peU - deepU, e.k * e.atre) // step 3, at most one confirmation per bar
            e.conf  := true
            e.cB0   := e.b0
            e.cB1   := e.be
            e.cP0   := e.p0
            e.cP1   := e.pe
            e.cDir  := d
            e.cA    := d * (e.pe - e.p0) / e.atr0
            e.cD    := e.be - e.b0
            e.sid   := e.sid + 1
            e.dir   := -d
            e.p0    := e.pe
            e.b0    := e.be
            e.atr0  := e.atre
            e.pe    := e.deep
            e.be    := t
            e.atre  := e.atr
            e.deep  := c
            e.birth := t
    e

method rhoC(Engine e, float c) =>
    e.dir * (e.pe - c) / (e.k * e.atre)
method extent(Engine e) =>
    e.dir * (e.pe - e.p0) / e.atr0

cellOf(float d, float rhoC, int g, float r) =>
    float rc = minE(maxE(rhoC, 0.0), 1.0)
    int ri = math.min(int(rc / 0.2), 4)
    int gi = g <= 0 ? 0 : g <= 2 ? 1 : g <= 5 ? 2 : 3
    int xi = ltE(r, 1.5) ? 0 : ltE(r, 2.5) ? 1 : ltE(r, 4.0) ? 2 : 3
    int di = d > 0 ? 0 : 1
    [di * 80 + ri * 16 + gi * 4 + xi, rc, ri]

type Book
    array<float> hz          // 160 cells x 5: n, sum Y_in, sum Y_N, sum Y_C, sum (Y_in - rho_c)
    array<float> srt0        // sorted A of kept swings, up / down
    array<float> srt1
    array<float> ringA0      // ring buffers of A and D, N_MAX per direction
    array<float> ringA1
    array<int>   ringD0
    array<int>   ringD1
    array<int>   liveT       // the live swing's bars so far: bar, cell, clipped rho_c
    array<int>   liveC
    array<float> liveR
    int pos0  = 0
    int pos1  = 0
    int kept0 = 0
    int kept1 = 0

newBook() =>
    Book.new(array.new<float>(800, 0.0), array.new<float>(), array.new<float>(), array.new<float>(), array.new<float>(),
         array.new<int>(), array.new<int>(), array.new<int>(), array.new<int>(), array.new<float>())

addAt(array<float> a, int i, float v) =>
    array.set(a, i, array.get(a, i) + v)

countLE(array<float> s, float x) =>
    int lo = 0
    int hi = array.size(s)
    while lo < hi
        int mid = int((lo + hi) / 2)
        if leE(array.get(s, mid), x)
            lo := mid + 1
        else
            hi := mid
    lo
countLT(array<float> s, float x) =>
    int lo = 0
    int hi = array.size(s)
    while lo < hi
        int mid = int((lo + hi) / 2)
        if ltE(array.get(s, mid), x)
            lo := mid + 1
        else
            hi := mid
    lo
countX(array<float> s, float x, bool left) =>
    int n = 0
    if left
        n := countLT(s, x)
    else
        n := countLE(s, x)
    n

method insertRec(Book bk, int di, float A, int D) =>
    array<float> srt = di == 0 ? bk.srt0 : bk.srt1
    array<float> ra  = di == 0 ? bk.ringA0 : bk.ringA1
    array<int>   rd  = di == 0 ? bk.ringD0 : bk.ringD1
    int pos = di == 0 ? bk.pos0 : bk.pos1
    if array.size(ra) == N_MAX
        float old = array.get(ra, pos)
        array.remove(srt, countLT(srt, old))
        array.set(ra, pos, A)
        array.set(rd, pos, D)
    else
        array.push(ra, A)
        array.push(rd, D)
    if di == 0
        bk.pos0 := (pos + 1) % N_MAX
    else
        bk.pos1 := (pos + 1) % N_MAX
    array.insert(srt, countLE(srt, A), A)

var array<float> margR = array.new<float>(40, 0.0)     // rho_c margin [dir, rho bin]: n, sum Y_N, sum Y_C, sum (Y_in - rho_c)
var array<float> baseR = array.new<float>(6, 0.0)      // direction base rate [dir]: n, sum Y_N, sum Y_C

method absorb(Book bk, Engine e, int t, float c) =>
    if e.started
        if e.conf
            int n = array.size(bk.liveT)
            if e.sid - 1 >= DISCARD and n > 0
                int di = e.cDir > 0 ? 0 : 1
                if di == 0
                    bk.kept0 := bk.kept0 + 1
                else
                    bk.kept1 := bk.kept1 + 1
                for i = 0 to n - 1
                    int tt   = array.get(bk.liveT, i)
                    int cc   = array.get(bk.liveC, i)
                    float rv = array.get(bk.liveR, i)
                    float yin = e.cB1 <= tt ? 1.0 : 0.0
                    float yn  = e.cB1 <= tt + HZN ? 1.0 : 0.0
                    float yc  = t <= tt + HZN ? 1.0 : 0.0
                    addAt(bk.hz, cc * 5, 1.0)
                    addAt(bk.hz, cc * 5 + 1, yin)
                    addAt(bk.hz, cc * 5 + 2, yn)
                    addAt(bk.hz, cc * 5 + 3, yc)
                    addAt(bk.hz, cc * 5 + 4, yin - rv)
                    int rb = math.min(int(rv / 0.2), 4)
                    int mi = (di * 5 + rb) * 4
                    addAt(margR, mi, 1.0)
                    addAt(margR, mi + 1, yn)
                    addAt(margR, mi + 2, yc)
                    addAt(margR, mi + 3, yin - rv)
                    addAt(baseR, di * 3, 1.0)
                    addAt(baseR, di * 3 + 1, yn)
                    addAt(baseR, di * 3 + 2, yc)
                bk.insertRec(di, e.cA, e.cD)
            array.clear(bk.liveT)
            array.clear(bk.liveC)
            array.clear(bk.liveR)
        [cell, rc, ri] = cellOf(e.dir, e.rhoC(c), t - e.be, e.extent() / e.k)
        array.push(bk.liveT, t)
        array.push(bk.liveC, cell)
        array.push(bk.liveR, rc)
    bk

subset(Book bk, int di, float a) =>
    array<float> own = di == 0 ? bk.srt0 : bk.srt1
    array<float> oth = di == 0 ? bk.srt1 : bk.srt0
    int le    = countLE(own, a)
    int nOwn  = array.size(own) - le
    bool pooled = nOwn < N_POOL
    int base  = le
    int n     = nOwn
    if pooled
        int le2 = countLE(oth, a)
        base := le + le2
        n    := nOwn + array.size(oth) - le2
    [pooled, base, n]

gExcess(float x, float a, float mu, int di, Book bk, bool pr, int br, int nr, bool left) =>
    float g0 = 1.0 - math.exp(-x / mu)
    float g = g0
    if nr > 0
        float ax = a + x
        int cnt = countX(di == 0 ? bk.srt0 : bk.srt1, ax, left) - br
        if pr
            cnt := cnt + countX(di == 0 ? bk.srt1 : bk.srt0, ax, left)
        float w = nr / (nr + M_BAND)
        g := w * (float(cnt) / nr) + (1.0 - w) * g0
    g

gMix(float x, float p, float a, float mu, int di, Book bk, bool pr, int br, int nr) =>
    p + (1.0 - p) * gExcess(x, a, mu, di, bk, pr, br, nr, false)

tagOdds(float lv, float a, float p, float mu, int di, Book bk, bool pr, int br, int nr) =>
    float out = na
    if not na(lv)
        out := leE(lv, a) ? 1.0 : (1.0 - p) * (1.0 - gExcess(lv - a, a, mu, di, bk, pr, br, nr, true))
    out

solveX(float u, float p, float a, float mu, int di, Book bk, bool pr, int br, int nr, bool warm, float xPrev) =>
    float x = 0.0
    if gtE(u, p)
        float lo = 0.0
        float hi = 1.0
        int steps = FULL_STEPS
        if warm
            float d = DELTA
            bool found = false
            while not found
                lo := maxE(0.0, xPrev - d)
                hi := xPrev + d
                if leE(gMix(lo, p, a, mu, di, bk, pr, br, nr), u) and leE(u, gMix(hi, p, a, mu, di, bk, pr, br, nr))
                    found := true
                else
                    d := d * 2.0
            steps := WARM_STEPS
        else
            while ltE(gMix(hi, p, a, mu, di, bk, pr, br, nr), u)
                hi := hi * 2.0
        for i = 1 to steps
            float mid = 0.5 * (lo + hi)
            if geE(gMix(mid, p, a, mu, di, bk, pr, br, nr), u)
                hi := mid
            else
                lo := mid
        x := 0.5 * (lo + hi)
    x

windowVals(Book bk, int di, float a, int d) =>
    array<float> v = array.new<float>()
    for side = 0 to 1
        int dd = side == 0 ? di : 1 - di
        if side == 1 and array.size(v) >= N_POOL
            break
        array<float> ra = dd == 0 ? bk.ringA0 : bk.ringA1
        array<int>   rd = dd == 0 ? bk.ringD0 : bk.ringD1
        int n = array.size(ra)
        if n > 0
            for i = 0 to n - 1
                if gtE(array.get(ra, i), a) and array.get(rd, i) > d
                    array.push(v, float(array.get(rd, i)))
    array.sort(v, order.ascending)
    v

windowQ(float u, float p, float dExt, array<float> s) =>
    float out = na
    if leE(u, p)
        out := dExt
    else
        int n = array.size(s)
        if n > 0
            float v = (u - p) / (1.0 - p)
            int i = 0
            while i < n and na(out)
                float xq = array.get(s, i)
                if geE(float(countLE(s, xq)) / n, v - 1e-12)
                    out := xq
                i := i + 1
    out

var Engine real = Engine.new(k = K, n = NATR, closes = CLOSES)
var Book bkR = newBook()
var int   startBar = na
var line  liveLeg = na
var line  liveGlow = na

var float fCell = na
var float fPin = na
var float fPn = na
var float fPc = na
var float fLo = na
var float fHi = na
var float fDlo = na
var float fDhi = na
var float fMass = na
var float fNband = na
var float fReady = na
var int   lastSid = -1
var float lastA = na
var array<float> xp = array.new<float>(3, 0.0)   // warm-start chains: lo, hi, 1 - alpha

var float wLo = na
var float wHi = na

var float bDlo = na
var float bDhi = na

var float prevPn = na
var float prevPc = na
var bool  stInZone = false
var bool  stLikely = false
var bool  stOverdue = false
var float zA = na                 // display band in price
var float zB = na

var float fL50 = na
var float fL75 = na
var float fL90 = na
var float fT50 = na              // chance of a tag from here, per level
var float fT75 = na
var float fT90 = na
var array<float> lvPrev = array.new<float>(3, na)
var array<line>  legs   = array.new<line>()
var array<label> tags   = array.new<label>()
var array<line>  glows  = array.new<line>()
var float lastHiP = na
var float lastLoP = na
var color tintCol = na

if barstate.isconfirmed and na(startBar) and time >= startTime
    startBar := bar_index

if barstate.isconfirmed and not na(startBar)
    int t = bar_index - startBar
    real.step(t, high, low, close, 2.0 * syminfo.mintick)
    bkR.absorb(real, t, close)

    if real.conf
        float A = real.cA
        bool zoneHitBirth = not na(bDlo) and leE(bDlo, A) and leE(A, bDhi)
        bool winOk = not na(wLo) and not na(wHi)
        bool winHit = winOk ? leE(wLo, real.cD) and leE(real.cD, wHi) : false
        if alConf and real.sid - 1 >= DISCARD
            alert((real.cDir > 0 ? "Swing Exhaustion: up swing confirmed, " : "Swing Exhaustion: down swing confirmed, ") + str.tostring(A, "0.00") + " ATR. Zone at birth " + (zoneHitBirth ? "hit" : "missed") + ", window " + (winOk ? (winHit ? "hit" : "missed") : "n/a") + ".", alert.freq_once_per_bar_close)
        bool isHi = real.cDir > 0
        string sTag = isHi ? (na(lastHiP) or gtE(real.cP1, lastHiP) ? "HH" : "LH") : (na(lastLoP) or ltE(real.cP1, lastLoP) ? "LL" : "HL")
        if isHi
            lastHiP := real.cP1
        else
            lastLoP := real.cP1
        if showTags and real.sid - 1 >= DISCARD
            color tagC = sTag == "HH" or sTag == "HL" ? upCol : dnCol
            array.push(tags, label.new(startBar + real.cB1, real.cP1, sTag + " · " + str.tostring(A, "0.0") + "×",
                 style = isHi ? label.style_label_down : label.style_label_up, color = color.new(tagC, 10), textcolor = color.black, size = size.tiny,
                 tooltip = (isHi ? "Up" : "Down") + " swing: " + str.tostring(A, "0.00") + " ATR in " + str.tostring(real.cD) + " bars"))
            if array.size(tags) > 120
                label.delete(array.shift(tags))

    if real.started
        float d = real.dir
        int di = d > 0 ? 0 : 1
        [c, rc, ri] = cellOf(d, real.rhoC(close), t - real.be, real.extent() / K)
        float nb  = array.get(baseR, di * 3)
        float pbN = nb > 0 ? array.get(baseR, di * 3 + 1) / nb : 0.5
        float pbC = nb > 0 ? array.get(baseR, di * 3 + 2) / nb : 0.5
        int mi = (di * 5 + ri) * 4
        float nm   = array.get(margR, mi)
        float pmN  = (array.get(margR, mi + 1) + M_HAZ * pbN) / (nm + M_HAZ)
        float pmC  = (array.get(margR, mi + 2) + M_HAZ * pbC) / (nm + M_HAZ)
        float resM = array.get(margR, mi + 3) / (nm + M_HAZ)
        float n0 = array.get(bkR.hz, c * 5)
        float pIn = minE(maxE(rc + (array.get(bkR.hz, c * 5 + 4) + M_HAZ * resM) / (n0 + M_HAZ), 0.0), 1.0)
        fCell := c
        fPin  := pIn
        fPn   := (array.get(bkR.hz, c * 5 + 2) + M_HAZ * pmN) / (n0 + M_HAZ)
        fPc   := (array.get(bkR.hz, c * 5 + 3) + M_HAZ * pmC) / (n0 + M_HAZ)
        bool ready = bkR.kept0 >= WARM and bkR.kept1 >= WARM
        fReady := ready ? 1.0 : 0.0
        bool birth = real.sid != lastSid

        float a  = real.extent()
      

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

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

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

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

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

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

Стоимость полного кода
3 124₽ ≈ $38