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

Eye Rejection Profile

indicator eye rejection profile for tradingview.pine

Похожие материалы по тегам

#3 news panel (black) bgp.mq5MQL5 / MetaTrader 5 · 1 общих теговea robofibo source v.11.2.mq4MQL4 / MetaTrader 4 · 1 общих теговindicator marketmind for tradingview.pineTradingView · 1 общих теговmarket crusher ea guidlines.txtMQL · 1 общих теговsovetnikov_v5.mq4MQL4 / MetaTrader 4 · 1 общих теговunlocker manual.mq4MQL4 / MetaTrader 4 · 1 общих тегов
Вы автор или правообладатель?

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

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

О программе

«Eye Rejection Profile» — индикатор для TradingView (Pine Script v6), отображающий на графике профиль отторжений цен в виде «бабочки». Объём отторжений рассчитывается только по фитилям свечей, а не по общему объёму: левая крыло показывает отторжение покупателями, правое — продавцом. Зоны отторжений пересчитываются один раз за сессию из баров до начала сессии и затем замораживаются, что исключает их перерисовку.

Индикатор отслеживает «голые POC» (точки контроля) каждой сессии и строит карту магнитов с вероятностью возврата цены к каждому из них, рассчитанной на основе истории данного символа и расстояния в средних диапазонах сессии. Также выделяются свечи отторжений с необычно большим фитилём и объёмом, которые подсвечиваются на графике.

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

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

НастройкаОписание
lookN Количество баров, используемых для построения профиля и зон на начало каждой сессии. На интрадей charts сессия = день, на дневных — неделя, на недельных — месяц.
rows Количество ценовых строк (строк профиля), на которые делится диапазон цены при построении профиля отторжений и зон.
widB Ширина профиля «бабочки» в барах — горизонтальный диапазон, на котором отображаются блоки объёма покупателей и продавцов.
offB Отступ в барах от последней свечи, до которого продлеваются линии и блоки текущих зон и сценариев.
showP При включении отображается профиль отторжений в виде «бабочки» на последнем баре: левая крыло — покупатели, правая — продавцы.
showZ При включении отображаются зоны отторжений — ценовые диапазоны с наибольшим объёмом отторжений, пересчитанные один раз за сессию и замороженные.
zoneTh Минимальная доля силы отторжения (от силы наиболее заполненной строки), необходимая для того, чтобы строка входила в зону. Более высокое значение — меньше, но более сильных зон.
zPer Максимальное количество зон отторжения, отображаемых на каждую сторону (покупателей и продавцов).
showSig При включении на графике отображаются сигналы сценариев отторжений с отметками входа, стопа и цели.
wickMin Минимальный размер отторжённого фитиля в процентах от полного диапазона свечи. Фитиль, направленный в зону отторжения, должен составлять не менее этого значения для формирования сигнала.
slBuf Дополнительный буст в единицах ATR, добавляемый к стопу сценария отторжения для увеличения зазора от цены входа.
minRR Минимальное соотношение награда к риску (R). Naked POC или зона используются как цель только если расстояние до них составляет не менее этого значения; иначе цель устанавливается на 2R.
maxRR Максимальное допустимое соотношение награда к риску (R). Цели дальше этого порога не используются, что ограничивает реалистичность сценариев.
maxBars Количество баров, по истечении которых сценарий отторжения принудительно закрывается по цене закрытия бара, если не сработал ни стоп, ни цель.
magMin Минимальная вероятность (в % от 100), при которой naked POC считается высоковероятной магнитной целью для сценария отторжения и получает отметку звезды.
showBox При включении отображаются блоки TP (цели) и SL (стопа) для каждого нового сценария отторжения.
keepT Максимальное количество сценариев отторжений, отображаемых одновременно на графике (блоки TP/SL и labels).
showN При включении на графике отображаются магниты — голые POC (точки контроля) каждой завершённой сессии, с линиями и подписями.
maxN Максимальное количество ближайших магнитов (голых POC), отображаемых на графике.
revWin Количество сессий, в течение которых измеряется вероятность возврата цены к магниту. Каждый магнит показывает шанс торговли обратно к нему в этом окне, рассчитанный на основе истории данного символа.
maxDist Максимальное расстояние до магнита в средних диапазонах сессии. Магниты дальше этого порога не отображаются на графике, но учитываются в статистике.
minSamp Минимальное количество наблюдений в дистанционном диапазоне, необходимое для расчёта вероятности возврата к магниту. При меньшем количестве вероятность не вычисляется.
showRC При включении подсвечиваются фитили свечей, у которых размер фитиля и объём одновременно превышают установленный порог силы отторжения.
rcStr Пороговая сила отторжения для подсветки фитиля. Сила рассчитывается как длина фитиля в ATR, умноженная на отношение объёма к его 50-барному среднему. Фитиль также должен составлять не менее значения «Отторжённый фитиль (%)».
rcKeep Максимальное количество свечей отторжений с подсветкой, отображаемых одновременно на графике.
buyC Цвет отображения покупателей (зоны отторжения, профиль, labels).
selC Цвет отображения продавцов (зоны отторжения, профиль, labels).
pocC Цвет отображения голых POC (точек контроля) и магнитов.
hdrC Цвет заголовка сводной таблицы.
showTb При включении отображается сводная таблица с информацией о зонах, магнитах, статистике сценариев и текущим состоянием.
tbPos Позиция сводной таблицы на графике: верхний правый, верхний левый, нижний правый или нижний левый угол.
detailAlerts При включении формирует подробные сообщения alert() с информацией о входе, стопе и цели для каждого нового сценария отторжения.
Получить полный код

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

indicator("Eye Rejection Profile", overlay = true, max_boxes_count = 500, max_lines_count = 500, max_labels_count = 500, max_bars_back = 5000)

GP = "📊 Rejection Profile"
lookN = input.int(300, "Bars used per session", minval = 50, maxval = 2000, group = GP, display = display.none,
     tooltip = "At the start of every session the profile and zones are rebuilt from this many bars before it. Session = day on intraday charts, week on daily, month on weekly.")
rows  = input.int(40, "Rows", minval = 10, maxval = 100, group = GP, display = display.none)
widB  = input.int(50, "Profile width (bars)", minval = 10, maxval = 200, group = GP, display = display.none)
offB  = input.int(10, "Gap from last candle (bars)", minval = 2, maxval = 100, group = GP, display = display.none)
showP = input.bool(true, "Show rejection profile", group = GP, display = display.none)

GZ = "🧱 Rejection Zones"
showZ  = input.bool(true, "Show rejection zones", group = GZ, display = display.none)
zoneTh = input.int(60, "Zone strength (% of strongest row)", minval = 30, maxval = 95, group = GZ, display = display.none,
     tooltip = "Rows with at least this share of the strongest row form a zone. Higher = fewer, stronger zones.")
zPer   = input.int(2, "Zones per side", minval = 1, maxval = 4, group = GZ, display = display.none)

GS = "🎯 Rejection Setups"
showSig = input.bool(true, "Show rejection setups", group = GS, display = display.none)
wickMin = input.float(40, "Rejection wick (% of candle)", minval = 10, maxval = 90, group = GS, display = display.none,
     tooltip = "The wick pointing into the zone must be at least this share of the candle's range.")
slBuf   = input.float(0.2, "Stop buffer (× ATR)", minval = 0.0, step = 0.05, group = GS, display = display.none)
minRR   = input.float(1.0, "Minimum reward : risk", minval = 0.5, step = 0.25, group = GS, display = display.none,
     tooltip = "A naked POC or zone is only used as target if it is at least this many R away; otherwise the target is 2R.")
maxRR   = input.float(3.0, "Maximum reward : risk", minval = 1.0, step = 0.5, group = GS, display = display.none,
     tooltip = "Targets further than this many R are ignored, so trades stay realistic.")
maxBars = input.int(48, "Time exit after (bars)", minval = 5, maxval = 500, group = GS, display = display.none,
     tooltip = "If neither target nor stop is hit within this many bars, the setup is closed at the bar's close.")
magMin  = input.int(60, "⭐ Magnet target needs (%)", minval = 30, maxval = 95, group = GS, display = display.none,
     tooltip = "A setup earns the magnet star when its target is a naked POC whose probability is at least this.")
showBox = input.bool(true, "Show TP / SL boxes", group = GS, display = display.none)
keepT   = input.int(100, "Setups kept on chart", minval = 1, maxval = 150, group = GS, display = display.none)

GN = "🧲 Magnet Map"
showN   = input.bool(true, "Show magnets (naked POCs)", group = GN, display = display.none)
maxN    = input.int(5, "Nearest magnets shown", minval = 1, maxval = 30, group = GN, display = display.none)
revWin  = input.int(5, "Probability window (sessions)", minval = 1, maxval = 20, group = GN, display = display.none,
     tooltip = "Each magnet shows the chance that price trades back to it within this many sessions, measured on this symbol.")
maxDist = input.float(3.0, "Hide magnets further than (session ranges)", minval = 0.5, step = 0.5, group = GN, display = display.none,
     tooltip = "Magnets further away than this many average session ranges are not drawn, so the price scale is not squeezed. They still count in the statistics.")
minSamp = input.int(15, "Min samples per distance bucket", minval = 5, maxval = 200, group = GN, display = display.none)

GR = "🕯️ Rejection Candles"
showRC = input.bool(true, "Glow strong rejection wicks", group = GR, display = display.none)
rcStr  = input.float(2.5, "Rejection strength needed", minval = 0.5, step = 0.25, group = GR, display = display.none,
     tooltip = "Strength = wick length in ATR × volume versus its 50-bar average. The wick must also be at least the 'Rejection wick %' of the candle.")
rcKeep = input.int(100, "Rejection candles kept", minval = 5, maxval = 150, group = GR, display = display.none)

GC = "🎨 Colours"
buyC = input.color(#26A69A, "Buyers", inline = "c1", group = GC)
selC = input.color(#EF5350, "Sellers", inline = "c1", group = GC)
pocC = input.color(#FFB300, "Naked POC", inline = "c2", group = GC)
hdrC = input.color(#2962FF, "Header", inline = "c2", group = GC)

GT = "📋 Table & Alerts"
showTb = input.bool(true, "Show summary table", group = GT, display = display.none)
tbPos  = input.string("Top right", "Table position", options = ["Top right", "Top left", "Bottom right", "Bottom left"], group = GT, display = display.none)
detailAlerts = input.bool(true, "Detailed alert() messages", group = GT, display = display.none,
     tooltip = "Create the alert with 'Any alert() function call' to get entry, stop and target in the message.")

atr  = ta.atr(14)
atrL = ta.atr(50)
avgVol = ta.sma(nz(volume) > 0 ? volume : 1.0, 50)
sessTf = timeframe.isintraday ? "D" : timeframe.isdaily ? "W" : timeframe.isweekly ? "M" : "12M"
sessName = timeframe.isintraday ? "days" : timeframe.isdaily ? "weeks" : timeframe.isweekly ? "months" : "years"
sessUnit = timeframe.isintraday ? "day" : timeframe.isdaily ? "week" : timeframe.isweekly ? "month" : "year"
f_bk(float d) => d < 0.5 ? 0 : d < 1.0 ? 1 : d < 2.0 ? 2 : 3
newS = timeframe.change(sessTf)
px(float p) => str.tostring(p, format.mintick)
bgLum  = 0.299 * color.r(chart.bg_color) + 0.587 * color.g(chart.bg_color) + 0.114 * color.b(chart.bg_color)
isDark = bgLum < 128
pocT   = isDark ? pocC : #B7791F          // darker gold for text on light charts

f_str(array<float> arr, float top, float bot, float loR, float step, int nRows) =>
    float sm = 0.0
    for k = 0 to nRows - 1
        float mid = loR + (k + 0.5) * step
        if mid <= top and mid >= bot
            sm += arr.get(k)
    sm

f_spread(array<float> arr, float lo, float hi, float amt, float loR, float step, int nRows) =>
    if hi > lo and amt > 0
        int k1 = math.max(0, math.min(nRows - 1, int(math.floor((lo - loR) / step))))
        int k2 = math.max(0, math.min(nRows - 1, int(math.floor((hi - loR) / step))))
        for k = k1 to k2
            float rLo = loR + k * step
            float ov  = math.max(0.0, math.min(hi, rLo + step) - math.max(lo, rLo))
            arr.set(k, arr.get(k) + amt * ov / (hi - lo))

f_zones(array<float> arr, float loR, float step, int nRows, int keep) =>
    float mx = arr.max()
    array<float> zT = array.new<float>()
    array<float> zB = array.new<float>()
    array<float> zS = array.new<float>()
    if mx > 0
        int   s   = -1
        float acc = 0.0
        for k = 0 to nRows
            bool on = k < nRows and arr.get(k) >= mx * zoneTh / 100.0
            if on
                if s < 0
                    s := k
                    acc := 0.0
                acc += arr.get(k)
            else if s >= 0
                zB.push(loR + s * step)
                zT.push(loR + k * step)
                zS.push(acc)
                s := -1
    array<float> oT = array.new<float>()
    array<float> oB = array.new<float>()
    while oT.size() < keep and zS.size() > 0
        int j = zS.indexof(zS.max())
        oT.push(zT.get(j))
        oB.push(zB.get(j))
        zT.remove(j)
        zB.remove(j)
        zS.remove(j)
    [oT, oB]

var map<int, float> sVol   = map.new<int, float>()
var float           bSize  = na
var array<float>    nPrice = array.new<float>()
var array<int>      nBorn  = array.new<int>()
var array<int>      nBar   = array.new<int>()
var array<int>      nTm    = array.new<int>()     // time of the POC's session (for the label)
var int             sStartT = na
var array<label>    hitLb  = array.new<label>()
var array<bool>     nDone  = array.new<bool>()
var int   sessCount = 0
var int   revisited = 0
var int   expired   = 0
var float sumAge    = 0.0
var int          pocId  = 0
var array<int>   nId    = array.new<int>()
var array<int>   smB    = array.new<int>()       // pending probability samples: distance bucket
var array<int>   smS    = array.new<int>()       //   session the sample started
var array<int>   smId   = array.new<int>()       //   naked POC id
var array<bool>  smHit  = array.new<bool>()      //   reached inside its window?
var array<int>   bHit   = array.new<int>(4, 0)
var array<int>   bTot   = array.new<int>(4, 0)
var float sHi   = na
var float sLo   = na
var float avgSR = na

if newS
    if not na(sHi)
        float sr = sHi - sLo
        avgSR := na(avgSR) ? sr : avgSR * 0.9 + sr * 0.1
    sHi := high
    sLo := low
    if sVol.size() > 0 and not na(bSize)
        float bestV = -1.0
        int   bestK = 0
        for [k, v] in sVol
            if v > bestV
                bestV := v
                bestK := k
        nPrice.push((bestK + 0.5) * bSize)
        nBorn.push(sessCount)
        nBar.push(bar_index - 1)
        nTm.push(nz(sStartT, time))
        nDone.push(false)
        pocId += 1
        nId.push(pocId)
    sVol.clear()
    sStartT := time
    sessCount += 1
    bSize := na(atrL) ? na : math.max(syminfo.mintick, atrL * 0.25)

    if smB.size() > 0
        for i = smB.size() - 1 to 0
            if sessCount - smS.get(i) >= revWin
                bTot.set(smB.get(i), bTot.get(smB.get(i)) + 1)
                if smHit.get(i)
                    bHit.set(smB.get(i), bHit.get(smB.get(i)) + 1)
                smB.remove(i)
                smS.remove(i)
                smId.remove(i)
                smHit.remove(i)

    if not na(avgSR) and avgSR > 0 and nPrice.size() > 0 and smB.size() < 4000
        for i = 0 to nPrice.size() - 1
            smB.push(f_bk(math.abs(open - nPrice.get(i)) / avgSR))
            smS.push(sessCount)
            smId.push(nId.get(i))
            smHit.push(false)
else
    sHi := math.max(nz(sHi, high), high)
    sLo := math.min(nz(sLo, low), low)

if not na(bSize)
    float vv = nz(volume) > 0 ? volume : 1.0
    int kLo = int(math.floor(low / bSize))
    int kHi = int(math.floor(high / bSize))
    if kHi - kLo <= 200
        float part = vv / (kHi - kLo + 1)
        for kk = kLo to kHi
            sVol.put(kk, nz(sVol.get(kk)) + part)

touchN = false
if nPrice.size() > 0
    for i = nPrice.size() - 1 to 0
        float pr  = nPrice.get(i)
        int   age = sessCount - nBorn.get(i)
        if bar_index > nBar.get(i) and high >= pr and low <= pr
            touchN := true
            if showN
                hitLb.push(label.new(bar_index, pr, "🧲 ✓", style = label.style_label_center, color = color(na), textcolor = pocT, size = size.small,
                     tooltip = "Magnet reached: " + px(pr) + " (" + str.tostring(age) + " " + sessName + " after it formed)"))
                if hitLb.size() > 80
                    hitLb.shift().delete()
            if not nDone.get(i)
                revisited += 1
                sumAge += age

            int id = nId.get(i)
            if smB.size() > 0
                for q = smB.size() - 1 to 0
                    if smId.get(q) == id
                        smHit.set(q, true)
            nPrice.remove(i)
            nBorn.remove(i)
            nBar.remove(i)
            nTm.remove(i)
            nDone.remove(i)
            nId.remove(i)
        else if age > revWin and not nDone.get(i)
            expired += 1
            nDone.set(i, true)
while nPrice.size() > 200
    if not nDone.get(0)
        expired += 1
    nPrice.shift()
    nBorn.shift()
    nBar.shift()
    nTm.shift()
    nDone.shift()
    nId.shift()

f_prob(int b) => bTot.get(b) >= minSamp ? 100.0 * bHit.get(b) / bTot.get(b) : na
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)

var float        zLo   = na
var float        zStep = na
var float        zHi   = na
var int          zN    = 0
var array<float> pRb   = array.new<float>()
var array<float> pRs   = array.new<float>()
var array<float> bzT   = array.new<float>()
var array<float> bzB   = array.new<float>()
var array<float> szT   = array.new<float>()
var array<float> szB   = array.new<float>()
var array<bool>  usedB = array.new<bool>()
var array<bool>  usedS = array.new<bool>()
var array<box>   zBox  = array.new<box>()
var array<box>   zLive = array.new<box>()
var array<int>   zCnt  = array.new<int>()
var array<bool>  zSide = array.new<bool>()    // true = buyer zone (for history colour)     // boxes drawn per session (for history clean-up)

if (newS or na(zStep)) and bar_index > 60

    for b in zLive
        b.delete()
    zLive.clear()
    zSide.clear()

    int n = math.min(lookN, bar_index)
    float hiR = high[1]
    float loR = low[1]
    for i = 1 to n
        hiR := math.max(hiR, high[i])
        loR := math.min(loR, low[i])
    if hiR > loR
        float step = (hiR - loR) / rows
        rb = array.new<float>(rows, 0.0)
        rs = array.new<float>(rows, 0.0)
        for i = 1 to n
            float h = high[i]
            float l = low[i]
            float r = h - l
            if r > 0
                float v  = nz(volume[i]) > 0 ? volume[i] : 1.0
                float bt = math.max(open[i], close[i])
                float bb = math.min(open[i], close[i])
                f_spread(rs, bt, h, v * (h - bt) / r, loR, step, rows)
                f_spread(rb, l, bb, v * (bb - l) / r, loR, step, rows)
        zLo := loR
        zHi := hiR
        zStep := step
        zN := n
        pRb := rb
        pRs := rs
        [t1, b1] = f_zones(rb, loR, step, rows, zPer)
        [t2, b2] = f_zones(rs, loR, step, rows, zPer)
        bzT := t1
        bzB := b1
        szT := t2
        szB := b2

        int jb = bzT.size() - 1
        while jb >= 0
            bool dropB = false
            int js = szT.size() - 1
            while js >= 0 and not dropB
                if bzT.get(jb) > szB.get(js) and bzB.get(jb) < szT.get(js)
                    float sB = f_str(rb, bzT.get(jb), bzB.get(jb), loR, step, rows)
                    float sS = f_str(rs, szT.get(js), szB.get(js), loR, step, rows)
                    if sB >= sS
                        szT.remove(js)
                        szB.remove(js)
                    else
                        dropB := true
                js -= 1
            if dropB
                bzT.remove(jb)
                bzB.remove(jb)
            jb -= 1
        usedB := array.new<bool>(bzT.size(), false)
        usedS := array.new<bool>(szT.size(), false)
        if showZ
            if bzT.size() > 0
                for j = 0 to bzT.size() - 1
                    bx = box.new(bar_index, bzT.get(j), bar_index + 1, bzB.get(j), border_color = color.new(buyC, j == 0 ? 30 : 60), border_width = 1,
                         bgcolor = color.new(buyC, j == 0 ? 84 : 91), text = j == 0 ? "BUYERS DEFEND" : "", text_color = color.new(buyC, 10),
                         text_size = size.small, text_halign = text.align_right, text_valign = text.align_bottom)
                    zLive.push(bx)
                    zSide.push(true)
                    zBox.push(bx)
            if szT.size() > 0
                for j = 0 to szT.size() - 1
                    bx = box.new(bar_index, szT.get(j), bar_index + 1, szB.get(j), border_color = color.new(selC, j == 0 ? 30 : 60), border_width = 1,
                         bgcolor = color.new(selC, j == 0 ? 84 : 91), text = j == 0 ? "SELLERS DEFEND" : "", text_color = color.new(selC, 10),
                         text_size = size.small, text_halign = text.align_right, text_valign = text.align_top)
                    zLive.push(bx)
                    zSide.push(false)
                    zBox.push(bx)

for b in zLive
    b.set_right(bar_index + offB - 2)

var bool  tOn   = false
var int   tDir  = 0
var float tE    = na
var float tSL   = na
var float tTP   = na
var int   tBar  = 0
var box   tbTP  = na
var box   tbSL  = na
var int   wins  = 0
var int   losses = 0
var float sumR  = 0.0
var int   tExits = 0
var int   tStars = 1
var array<int>   gN = array.new<int>(3, 0)
var array<int>   gW = array.new<int>(3, 0)
var array<float> gR = array.new<float>(3, 0.0)
f_stars(int n) => n >= 3 ? "⭐⭐⭐" : n == 2 ? "⭐⭐" : "⭐"
var array<box>   tBoxes = array.new<box>()
var array<label> tLbls  = array.new<label>()

longSig  = false
shortSig = false
tpHit    = false
slHit    = false
string tpTag = ""

if tOn and bar_index > tBar
    if not na(tbTP)
        tbTP.set_right(bar_index)
        tbSL.set_right(bar_index)
    bool hs = tDir == 1 ? low <= tSL : high >= tSL
    bool ht = tDir == 1 ? high >= tTP : low <= tTP
    bool tx = bar_index - tBar >= maxBars
    if hs or ht or tx
        tOn := false
        float risk0 = math.abs(tE - tSL)
        if hs                      // stop first when both are touched on one bar (conservative)
            losses += 1
            sumR -= 1
            gN.set(tStars - 1, gN.get(tStars - 1) + 1)
            gR.set(tStars - 1, gR.get(tStars - 1) - 1)
            slHit := true
            tLbls.push(label.new(bar_index, tSL, "✗ −1R", color = selC, textcolor = #FFFFFF, style = tDir == 1 ? label.style_label_up : label.style_label_down, size = size.small))
        else if ht
            float rr = math.abs(tTP - tE) / risk0
            wins += 1
            sumR += rr
            gN.set(tStars - 1, gN.get(tStars - 1) + 1)
            gW.set(tStars - 1, gW.get(tStars - 1) + 1)
            gR.set(tStars - 1, gR.get(tStars - 1) + rr)
            tpHit := true
            tLbls.push(label.new(bar_index, tTP, "✓ +" + str.tostring(rr, "#.0") + "R", color = buyC, textcolor = #FFFFFF, style = tDir == 1 ? la

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

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

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

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

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

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

Стоимость полного кода
2 442,50₽ ≈ $30.43