Eye Rejection Profile
Похожие материалы по тегам
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «indicator eye rejection profile for tradingview.pine» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
«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? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.