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

Range Breakout Verdict Engine

range breakout verdict engine.pine
Вы автор или правообладатель?

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

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

О программе

Индикатор «Range Breakout Verdict Engine» (RBVE) автоматически обнаруживает ценовые диапазоны на графике и запускает последовательный статистический тест при пробитии границ диапазона закрытием бара. В основе теста лежит метод последовательного отношения правдоподобия (SPRT), параметры которого обучаются на реальных breakout-событиях текущего графика. Индикатор выносит вердикты ACCEPTED (продолжение) или DEVIATION (отклонение) при достижении достаточной доказательной базы.

Пользователь может задать допустимые уровни ошибок (с conservative, balanced и aggressive вариантами), количество баров для тестирования и параметры обучения. Если данных для обучения недостаточно, система переходит в режим LEARNING и не выдаёт окончательных вердиктов. Все решения фиксируются на закрытых барах и не пересматриваются.

Визуализация включает рамки диапазонов, метки вердиктов на графике и информационную панель с текущим состоянием теста, счётчиком доказательств и историей вердиктов. Индикатор поддерживает три условия оповещений: бычий вердикт, медвежий вердикт и начало тестирования пробития.

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

НастройкаОписание
rngLen Количество баров в окне для определения диапазона. Диапазон формируется по максимуму и минимуму предыдущих N закрытых баров.
cmpMax Максимальное сжатие: отношение высоты диапазона к высоте контекстного окна в 4 раза длиннее. Чем ниже значение, тем только более плотные консолидации принимаются как диапазон.
errIn Уровень допустимых ошибок: conservative (α = β = 5%), balanced (α = β = 10%) или aggressive (α = β = 20%). Определяет допустимую частоту ложных вердиктов. Более низкие значения требуют больше доказательств.
maxK Максимальное количество закрытых баров после бара пробития, которые тест может использовать для накопления доказательств. Если граница не достигнута, тест завершается как SKIP.
advOn Включает расширенные правила обучения. При выключении используются значения по умолчанию: 1.0× для yardstick, 0.25× для глубины отказа, 30-барный горизонт и 5 проб на класс.
yardIn Порог принятия (в кратных значениях от высоты диапазона): пробитие считается подтверждённым для обучения, если закрытие достигает этого расстояния за границей диапазона.
failIn Глубина отказа (в кратных значениях от высоты диапазона): цена закрытия на этом расстоянии внутри диапазона классифицирует пробитие как неудачное для обучения.
horIn Горизонт результата в барах: пробития, не разрешённые ни в одну сторону в пределах этого количества баров, отбрасываются из обучения.
nMinIn Минимальное количество разрешённых пробитий каждого класса (ACCEPTED и FAILED), необходимое для выдачи вердиктов. До достижения этого порога панель показывает режим LEARNING.
showBox Отображать ли рамки диапазонов на графике. Рамки рисуются пунктирной линией при формировании и сплошной при активном тесте.
bullCol Цвет отрисовки для бычьих (восходящих) вердиктов и отметок на графике.
bearCol Цвет отрисовки для медвежьих (нисходящих) вердиктов и отметок на графике.
showDash Отображать ли информационную панель в правом верхнем углу графика с текущим состоянием, доказательствами и историей вердиктов.
tsIn Размер таблицы информационной панели: Tiny, Small или Normal.
Получить полный код

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

indicator("Range Breakout Verdict Engine", shorttitle = "RBVE", overlay = true, max_boxes_count = 12, max_lines_count = 6, max_labels_count = 40)

enum ErrRate
    conservative = "Conservative (α = β = 5%)"
    balanced     = "Balanced (α = β = 10%)"
    aggressive   = "Aggressive (α = β = 20%)"

enum TSize
    tiny   = "Tiny"
    small  = "Small"
    normal = "Normal"

const string G_R = "Range Detection"
const string G_T = "Sequential Test"
const string G_L = "Learning Rules"
const string G_V = "Visuals"

int   rngLen  = input.int(20, "Range Length", minval = 8, maxval = 100, group = G_R, tooltip = "Bars in the candidate range window. The range is the high/low of the previous N closed bars.")
float cmpMax  = input.float(0.50, "Max Compression", minval = 0.20, maxval = 0.90, step = 0.05, group = G_R, tooltip = "Range height ÷ height of the 4× longer context window. Lower values accept only tighter consolidations.")
ErrRate errIn = input.enum(ErrRate.balanced, "Error Rates", group = G_T, tooltip = "α = tolerated rate of ACCEPTED verdicts on breakouts that fail. β = tolerated rate of DEVIATION verdicts on breakouts that hold. Lower rates need more evidence, so verdicts arrive later and more tests end in SKIP.")
int   maxK    = input.int(8, "Max Test Bars", minval = 2, maxval = 30, group = G_T, tooltip = "Closed bars after the breakout bar that the test may use. If the evidence never crosses a bound, the test ends as SKIP.")
bool  advOn   = input.bool(false, "Custom Learning Rules", group = G_L, tooltip = "Off = defaults (1.0× yardstick, 0.25× failure depth, 30-bar horizon, 5 trials per class).")
float yardIn  = input.float(1.0, "Acceptance Yardstick (× range height)", minval = 0.3, maxval = 3.0, step = 0.1, group = G_L, active = advOn, tooltip = "A breakout is labelled ACCEPTED for learning when a close reaches this distance beyond the broken boundary.")
float failIn  = input.float(0.25, "Failure Depth (× range height)", minval = 0.05, maxval = 1.0, step = 0.05, group = G_L, active = advOn, tooltip = "A breakout is labelled FAILED for learning when a close returns this far back inside the range.")
int   horIn   = input.int(30, "Outcome Horizon (bars)", minval = 5, maxval = 200, group = G_L, active = advOn, tooltip = "Breakouts that resolve neither way within this many bars are discarded from learning.")
int   nMinIn  = input.int(5, "Min Trials per Class", minval = 2, maxval = 50, group = G_L, active = advOn, tooltip = "Resolved ACCEPTED and FAILED breakouts required before verdicts are issued. Until then the dashboard shows LEARNING.")
bool  showBox = input.bool(true, "Show Range Boxes", group = G_V)
color bullCol = input.color(#22C3A6, "Bullish", group = G_V, inline = "pal")
color bearCol = input.color(#F0506E, "Bearish", group = G_V, inline = "pal")
bool  showDash = input.bool(true, "Show Dashboard", group = G_V)
TSize tsIn    = input.enum(TSize.small, "Table Size", group = G_V, active = showDash)

float yardE   = advOn ? yardIn : 1.0
float failE   = advOn ? failIn : 0.25
int   nMinE   = advOn ? nMinIn : 5
int   horE    = math.max(advOn ? horIn : 30, maxK + 1)
float alphaE  = errIn == ErrRate.conservative ? 0.05 : errIn == ErrRate.balanced ? 0.10 : 0.20
float betaE   = alphaE
float upperA  = math.log((1.0 - betaE) / alphaE)
float lowerB  = math.log(betaE / (1.0 - alphaE))
string tblSz  = tsIn == TSize.tiny ? size.tiny : tsIn == TSize.small ? size.small : size.normal
color neutral = color.new(chart.fg_color, 55)
const int NB  = 6

f_bin(float x) =>
    x < -0.25 ? 0 : x < 0.0 ? 1 : x < 0.15 ? 2 : x < 0.35 ? 3 : x < 0.70 ? 4 : 5

f_lr(int b, array<int> ca, array<int> cf, int nA, int nF) =>
    float pa = (ca.get(b) + 1.0) / (nA + NB)
    float pf = (cf.get(b) + 1.0) / (nF + NB)
    math.log(pa / pf)

f_pct(int num, int den) =>
    den > 0 ? str.tostring(math.round(100.0 * num / den)) + "%" : "—"

float hiW = ta.highest(high, rngLen)
float loW = ta.lowest(low, rngLen)
float hiC = ta.highest(high, rngLen * 4)
float loC = ta.lowest(low, rngLen * 4)

var int   state   = 0
var float rTop    = na
var float rBot    = na
var int   rFormed = na
var box   curBox  = na
var array<box> boxHist = array.new<box>()

var int   tDir    = 0
var float tBound  = na
var float tH      = na
var int   tBar    = na
var int   tK      = -1
var float llr     = 0.0
var int   vK      = -1     // test bar on which the verdict was issued
var int   verdict = 0      // 0 pending, 1 ACCEPTED, -1 DEVIATION, 2 SKIP, 3 LEARNING (no verdict)
var array<int> obs = array.new<int>()

var array<int> cntA = array.new<int>(NB, 0)
var array<int> cntF = array.new<int>(NB, 0)
var int nObsA = 0
var int nObsF = 0
var int nTrA  = 0
var int nTrF  = 0
var int nUnres = 0

var int accV   = 0
var int accHit = 0
var int devV   = 0
var int devHit = 0

var int   lastV     = 0
var int   lastVDir  = 0
var int   lastVBar  = na
var line  yLine     = na
var array<label> labs = array.new<label>()

bool bullSig   = false
bool bearSig   = false
bool testStart = false
var table wm = table.new(position.bottom_right, 1, 1)
if barstate.isfirst
    table.cell(wm, 0, 0, "Telegram @free_fx_pro", text_color = color.new(color.gray, 70), text_size = size.large)

if barstate.isconfirmed

    if state == 0
        float wH = hiW[1] - loW[1]
        float cH = hiC[1] - loC[1]
        if not na(wH) and not na(cH) and cH > 0 and wH > syminfo.mintick * 2 and wH <= cmpMax * cH and close <= hiW[1] and close >= loW[1]
            rTop    := hiW[1]
            rBot    := loW[1]
            rFormed := bar_index
            state   := 1
            if showBox
                curBox := box.new(bar_index - rngLen, rTop, bar_index, rBot, border_color = neutral, border_width = 1, border_style = line.style_dashed, bgcolor = color.new(chart.fg_color, 94))
                boxHist.push(curBox)
                if boxHist.size() > 4
                    box.delete(boxHist.shift())

    else if state == 1
        if close > rTop or close < rBot
            tDir    := close > rTop ? 1 : -1
            tBound  := tDir == 1 ? rTop : rBot
            tH      := rTop - rBot
            tBar    := bar_index
            tK      := -1
            llr     := 0.0
            vK      := -1
            obs.clear()
            verdict := nTrA >= nMinE and nTrF >= nMinE ? 0 : 3
            state   := 2
            testStart := true
            if showBox and not na(curBox)
                box.set_right(curBox, bar_index)
                if not na(yLine)
                    line.delete(yLine)
                float yLvl = tBound + tDir * yardE * tH
                yLine := line.new(bar_index, yLvl, bar_index + maxK, yLvl, color = neutral, style = line.style_dotted, width = 1)
        else if bar_index - rFormed > 2 * rngLen
            state := 0
            if not na(curBox)
                box.delete(curBox)
                if boxHist.size() > 0
                    boxHist.pop()
                curBox := na
        else if showBox and not na(curBox)
            box.set_right(curBox, bar_index)

    if state == 2
        tK += 1
        float x = tDir * (close - tBound) / tH
        int   b = f_bin(x)
        if tK <= maxK
            obs.push(b)
            if verdict == 0
                llr += f_lr(b, cntA, cntF, nObsA, nObsF)
                if llr >= upperA
                    verdict := 1
                else if llr <= lowerB
                    verdict := -1
                else if tK == maxK
                    verdict := 2
                if verdict == 1 or verdict =

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

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

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

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

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

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

Стоимость полного кода
1 079,60₽ ≈ $13.20