PROTECTED SOURCE SCRIPT

ELLIOT WAVE TP11OFC5

46
//version=6
indicator("TP11OFC5", overlay=true, scale=scale.right, max_lines_count=500, max_labels_count=500, max_boxes_count=500, max_bars_back=5000)

//──────────────────────────────── Inputs: Masked Names ───────────────────────────────
// yelow group (EMA200 + 5up/5down)
group200 = "yelow group"
emaLen200 = input.int(200, "yelow length", minval=1, group=group200)
show200Mid = input.bool(true, "show big brown", group=group200) // EMA200 mid
show200_5u = input.bool(true, "show yelow group up", group=group200) // 5up (EMA200)
show200_5d = input.bool(true, "show yelow group down",group=group200) // 5down (EMA200)

// Colors (masked)
groupClrMA = "Colors — lines"
colMid200 = input.color(color.rgb(100, 50, 0), "big brown", group=groupClrMA) // EMA200 mid
col5band = input.color(color.rgb(247, 212, 14), "yelow up/down", group=groupClrMA) // 5up/5down
col85_4 = input.color(color.rgb(9, 77, 202), "blue up/down (x4)",group=groupClrMA) // EMA85 4up/4down
col35 = input.color(color.rgb(7, 9, 155), "big blue", group=groupClrMA) // EMA35
colPNR = input.color(color.rgb(255,17,0), "pn", group=groupClrMA) // PNR

// blue group (EMA85 — 4 up/down)
group85 = "blue group"
emaLen85 = input.int(85, "blue length", minval=1, group=group85)
show85_4u = input.bool(true, "show blue group up", group=group85)
show85_4d = input.bool(true, "show blue group down", group=group85)

// big blue (EMA35)
group35 = "big blue"
emaLen35 = input.int(35, "big blue length", minval=1, group=group35)
useClose35 = input.bool(false, "big blue use close (else effClose)", group=group35)
showEMA35 = input.bool(true, "show big blue", group=group35)

// pn (PNR)
groupPNR = "pn"
pnrLen = input.int(15, "window size", minval=1, group=groupPNR)
pnrPerc = input.int(50, "percentile (0–100)", minval=0, maxval=100, group=groupPNR)
pnrSrc = input.source(close, "source", group=groupPNR)
showPNR = input.bool(true, "show pn", group=groupPNR)

// di (DSI)
groupDSI = "di"
showDSI = input.bool(true, "show di", group=groupDSI)
atrMovement= input.float(1.0, "movement required", step=0.5, group=groupDSI)
lookback = input.int(25, "high/low lookback", step=5, group=groupDSI)
maxZoneSize= input.float(2.5, "max zone size ", step=0.5, group=groupDSI)
newStructureReset = input.int(25, "zone update count before reset", step=5, group=groupDSI)
drawPreviousStructure = input.bool(true, "draw previous zones", group=groupDSI)

groupClrDSI = "Colors — zones"
dsiBullColor = input.color(color.rgb(178, 240, 180), "bull color", group=groupClrDSI)
dsiBearColor = input.color(color.rgb(240, 206, 206), "bear color", group=groupClrDSI)

//──────────────────────────────── FE (Trend-base Fibo) ───────────────────────────────
groupFE = "targets — FE"
feLenBars = input.int(35, "FE length (bars) from P3", minval=5, group=groupFE)
feLife = input.int(500, "FE lifespan (bars) before delete", minval=50, group=groupFE)
showFE = input.bool(true, "show FE", group=groupFE)
roundToTick = input.bool(true, "round FE to tick", group=groupFE)

// FE levels on/off
show95_105 = input.bool(true, "show band", group=groupFE)
show1618 = input.bool(true, "show 1", group=groupFE)
show2618 = input.bool(true, "show 2", group=groupFE)
show3618 = input.bool(true, "show 3", group=groupFE)
show4618 = input.bool(true, "show 4", group=groupFE)

// FE colors
colBand = input.color(color.rgb(79, 247, 46), "line", group=groupFE)
colBandFill = input.color(color.new(#8be95f, 85), "band", group=groupFE)
col1618 = input.color(color.orange, "1line", group=groupFE)
col2618 = input.color(color.fuchsia, "2line", group=groupFE)
col3618 = input.color(color.new(color.purple, 0), "3line", group=groupFE)
col4618 = input.color(color.new(color.maroon, 0), "4line", group=groupFE)

//──────────────────────────────── P-series (เดิม) ───────────────────────────────
groupP1P2P3 = "P-series options"
p1Lookback = input.int(200, "P1 max left scan", minval=20, group=groupP1P2P3)
rightWinBars = input.int(5, "P2 right confirm bars", minval=1, group=groupP1P2P3)
p3MaxWindowBars = input.int(600, "P3 max window (bars)", minval=50, maxval=5000, step=50, group=groupP1P2P3)
resetWithinBars = input.int(50, "reset old set if new within (bars)", minval=1, group=groupP1P2P3)

// >>> NEW: ระยะห่างขั้นต่ำ P1/P3 จาก P2 <<<
minGapBars = input.int(5, "Min gap bars: P1/P3 must be at least this far from P2", minval=1, group=groupP1P2P3)

// ── NEW: De-duplicate labels (no same-type within N bars; keep latest) ─────────────
groupDeDup = "Labels — de-dup"
dedupWinBars = input.int(50, "No same-type label within N bars", minval=1, group=groupDeDup)

// ──────────────────────────────── New: P2 window rule ───────────────────────────────
groupP2Win = "P2 window rule"
p2NewWithinBars = input.int(50, "Window N bars: new P2 within N must be better than last P2 (L: higher / S: lower)", minval=1, group=groupP2Win)

//──────────────────────────────── Visual options ───────────────────────────────
groupPviz = "Visual — Body highlights & labels"
showBodyBoxes = input.bool(true, "show body boxes", group=groupPviz)
P1BoxFullCandle = input.bool(false, "P1: full candle box", group=groupPviz)
P2BoxFullCandle = input.bool(false, "P2: full candle box", group=groupPviz)
P3BoxFullCandle = input.bool(false, "P3: full candle box", group=groupPviz)
P1BoxColor = input.color(color.black, "P1 box color", group=groupPviz)
P1BoxFillTransp = input.int(85, "P1 box fill transp", minval=0, maxval=100, group=groupPviz)
P2BoxColor = input.color(color.lime, "P2 box color", group=groupPviz)
P2BoxFillTransp = input.int(70, "P2 box fill transp", minval=0, maxval=100, group=groupPviz)
P3BoxColor = input.color(color.orange, "P3 box color", group=groupPviz)
P3BoxFillTransp = input.int(70, "P3 box fill transp", minval=0, maxval=100, group=groupPviz)
BoxBorderTransp = input.int(0, "box border transp", minval=0, maxval=100, group=groupPviz)

recolorBars = input.bool(true, "barcolor P1/P2/P3", group=groupPviz)
colP1Candle = input.color(color.black, "P1 candle", group=groupPviz)
colP2Candle = input.color(color.lime, "P2 candle", group=groupPviz)
colP3Candle = input.color(color.orange,"P3 candle", group=groupPviz)

showP1Label = input.bool(true, "show P1 label", group=groupPviz)
showP2Label = input.bool(true, "show P2 label", group=groupPviz)
showP3Label = input.bool(true, "show P3 label", group=groupPviz)
PLabelTextColor = input.color(color.white, "label text color", group=groupPviz)
PLabelBgColor = input.color(color.black, "label bg color", group=groupPviz)

// ── Label placement/offset (split LONG/SHORT) ───────────────────────────────
groupLbl = "Labels — placement"
LP_AUTO = "Auto"
LP_ABOVE = "Above"
LP_BELOW = "Below"
OM_TICKS = "Ticks"
OM_ATR = "ATR"

lblPlaceLong = input.string(LP_ABOVE, "Placement (LONG)", options=[LP_AUTO, LP_ABOVE, LP_BELOW], group=groupLbl)
lblPlaceShort = input.string(LP_BELOW, "Placement (SHORT)", options=[LP_AUTO, LP_ABOVE, LP_BELOW], group=groupLbl)
lblOffsetMet = input.string(OM_ATR, "Offset method", options=[OM_TICKS, OM_ATR], group=groupLbl)
lblTicks = input.int(5, "Ticks offset", minval=0, group=groupLbl)
lblAtrLen = input.int(14, "ATR length", minval=1, group=groupLbl)
lblAtrMult = input.float(0.25, "ATR multiple", minval=0.0, step=0.05, group=groupLbl)
lblSizeSel = input.string("small", "Label size", options=["tiny","small","normal","large"], group=groupLbl)
lblBgTransp = input.int(0, "Label BG transparency", minval=0, maxval=100, group=groupLbl)

//──────────────────────────────── Manual (แทน Override) ─────────────────────────
PM_OPEN = "Open"
PM_CLOSE = "Close"
PM_MID = "Mid"
PM_HIGH = "High"
PM_LOW = "Low"
PM_CUST = "Custom"
PK_TIME = "Time"
PK_OFF = "Offset"

// LONG
groupManL = "Manual (LONG)"
useManP1L = input.bool(false, "Use P1 manual (L)", group=groupManL)
pickP1L = input.string(PK_TIME, "P1 pick mode (L)", options=[PK_TIME, PK_OFF], group=groupManL)
manP1L_t = input.time(timestamp("01 Jan 2024 00:00 +0000"), "P1 time (L)", group=groupManL)
manP1L_of = input.int(-5, "P1 offset (bars, L)", group=groupManL)
pmP1L = input.string(PM_OPEN, "P1 price mode (L)", options=[PM_OPEN, PM_CLOSE, PM_MID, PM_HIGH, PM_LOW, PM_CUST], group=groupManL)
p1L_custom= input.float(0.0, "P1 custom price (L)", group=groupManL)

useManP2L = input.bool(false, "Use P2 manual (L)", group=groupManL)
pickP2L = input.string(PK_TIME, "P2 pick mode (L)", options=[PK_TIME, PK_OFF], group=groupManL)
manP2L_t = input.time(timestamp("01 Jan 2024 00:00 +0000"), "P2 time (L)", group=groupManL)
manP2L_of = input.int(-3, "P2 offset (bars, L)", group=groupManL)
pmP2L = input.string(PM_CLOSE, "P2 price mode (L)", options=[PM_OPEN, PM_CLOSE, PM_MID, PM_HIGH, PM_LOW, PM_CUST], group=groupManL)
p2L_custom= input.float(0.0, "P2 custom price (L)", group=groupManL)

useManP3L = input.bool(false, "Use P3 manual (L)", group=groupManL)
pickP3L = input.string(PK_TIME, "P3 pick mode (L)", options=[PK_TIME, PK_OFF], group=groupManL)
manP3L_t = input.time(timestamp("01 Jan 2024 00:00 +0000"), "P3 time (L)", group=groupManL)
manP3L_of = input.int(-1, "P3 offset (bars, L)", group=groupManL)
pmP3L = input.string(PM_OPEN, "P3 price mode (L)", options=[PM_OPEN, PM_CLOSE, PM_MID, PM_HIGH, PM_LOW, PM_CUST], group=groupManL)
p3L_custom= input.float(0.0, "P3 custom price (L)", group=groupManL)

// SHORT
groupManS = "Manual (SHORT)"
useManP1S = input.bool(false, "Use P1 manual (S)", group=groupManS)
pickP1S = input.string(PK_TIME, "P1 pick mode (S)", options=[PK_TIME, PK_OFF], group=groupManS)
manP1S_t = input.time(timestamp("01 Jan 2024 00:00 +0000"), "P1 time (S)", group=groupManS)
manP1S_of = input.int(-5, "P1 offset (bars, S)", group=groupManS)
pmP1S = input.string(PM_OPEN, "P1 price mode (S)", options=[PM_OPEN, PM_CLOSE, PM_MID, PM_HIGH, PM_LOW, PM_CUST], group=groupManS)
p1S_custom= input.float(0.0, "P1 custom price (S)", group=groupManS)

useManP2S = input.bool(false, "Use P2 manual (S)", group=groupManS)
pickP2S = input.string(PK_TIME, "P2 pick mode (S)", options=[PK_TIME, PK_OFF], group=groupManS)
manP2S_t = input.time(timestamp("01 Jan 2024 00:00 +0000"), "P2 time (S)", group=groupManS)
manP2S_of = input.int(-3, "P2 offset (bars, S)", group=groupManS)
pmP2S = input.string(PM_CLOSE, "P2 price mode (S)", options=[PM_OPEN, PM_CLOSE, PM_MID, PM_HIGH, PM_LOW, PM_CUST], group=groupManS)
p2S_custom= input.float(0.0, "P2 custom price (S)", group=groupManS)

useManP3S = input.bool(false, "Use P3 manual (S)", group=groupManS)
pickP3S = input.string(PK_TIME, "P3 pick mode (S)", options=[PK_TIME, PK_OFF], group=groupManS)
manP3S_t = input.time(timestamp("01 Jan 2024 00:00 +0000"), "P3 time (S)", group=groupManS)
manP3S_of = input.int(-1, "P3 offset (bars, S)", group=groupManS)
pmP3S = input.string(PM_OPEN, "P3 price mode (S)", options=[PM_OPEN, PM_CLOSE, PM_MID, PM_HIGH, PM_LOW, PM_CUST], group=groupManS)
p3S_custom= input.float(0.0, "P3 custom price (S)", group=groupManS)

// Buttons: Reset (UI switches)
groupBtnL = "Manual Controls — Buttons (LONG)"
btnResetAllL = input.bool(false, "Reset ALL manual (L)", group=groupBtnL)
btnResetP1L = input.bool(false, "Reset P1 manual (L)", group=groupBtnL)
btnResetP2L = input.bool(false, "Reset P2 manual (L)", group=groupBtnL)
btnResetP3L = input.bool(false, "Reset P3 manual (L)", group=groupBtnL)

groupBtnS = "Manual Controls — Buttons (SHORT)"
btnResetAllS = input.bool(false, "Reset ALL manual (S)", group=groupBtnS)
btnResetP1S = input.bool(false, "Reset P1 manual (S)", group=groupBtnS)
btnResetP2S = input.bool(false, "Reset P2 manual (S)", group=groupBtnS)
btnResetP3S = input.bool(false, "Reset P3 manual (S)", group=groupBtnS)

// ── Momentary Reset (edge-detect) ───────────────────────────────
var bool resetReqAllL = false
var bool resetReqP1L = false
var bool resetReqP2L = false
var bool resetReqP3L = false
var bool resetReqAllS = false
var bool resetReqP1S = false
var bool resetReqP2S = false
var bool resetReqP3S = false

bool fireAllL = ta.change(btnResetAllL) and btnResetAllL
bool fireP1L = ta.change(btnResetP1L) and btnResetP1L
bool fireP2L = ta.change(btnResetP2L) and btnResetP2L
bool fireP3L = ta.change(btnResetP3L) and btnResetP3L

bool fireAllS = ta.change(btnResetAllS) and btnResetAllS
bool fireP1S = ta.change(btnResetP1S) and btnResetP1S
bool fireP2S = ta.change(btnResetP2S) and btnResetP2S
bool fireP3S = ta.change(btnResetP3S) and btnResetP3S

if fireAllL
resetReqAllL := true
resetReqP1L := true
resetReqP2L := true
resetReqP3L := true
if fireP1L
resetReqP1L := true
if fireP2L
resetReqP2L := true
if fireP3L
resetReqP3L := true

if fireAllS
resetReqAllS := true
resetReqP1S := true
resetReqP2S := true
resetReqP3S := true
if fireP1S
resetReqP1S := true
if fireP2S
resetReqP2S := true
if fireP3S
resetReqP3S := true

//──────────────────────────────── Core helpers ───────────────────────────────
float effClose = close >= open ? math.max(open, close) : math.min(open, close)
f_bodyTop(_o, _c) => math.max(_o, _c)
f_bodyBot(_o, _c) => math.min(_o, _c)
f_midBody_at(_i) =>
float bt = f_bodyTop(open[_i], close[_i])
float bb = f_bodyBot(open[_i], close[_i])
(bt + bb) / 2.0

f_core(_len) =>
float mid = ta.ema(effClose, _len)
float _dev = ta.stdev(effClose, _len)
float devS = _dev == 0.0 ? na : _dev
float plus = na(mid) or na(devS) ? na : (close > mid ? (close - mid) / devS : 0.0)
float minus = na(mid) or na(devS) ? na : (close < mid ? (mid - close) / devS : 0.0)
float mmax = na(plus) or na(minus) ? na : math.max(plus, minus)
float lm = ta.ema(mmax, _len)
[mid, devS, lm]

f_core_src(_src, _len) =>
float mid = ta.ema(_src, _len)
float _dev = ta.stdev(_src, _len)
float devS = _dev == 0.0 ? na : _dev
float plus = na(mid) or na(devS) ? na : (_src > mid ? (_src - mid) / devS : 0.0)
float minus = na(mid) or na(devS) ? na : (_src < mid ? (mid - _src) / devS : 0.0)
float mmax = na(plus) or na(minus) ? na : math.max(plus, minus)
float lm = ta.ema(mmax, _len)
[mid, devS, lm]

// Price by mode
f_price_by_mode(off, mode, custom) =>
switch mode
PM_OPEN => open[off]
PM_CLOSE => close[off]
PM_MID => (math.max(open[off], close[off]) + math.min(open[off], close[off]))/2.0
PM_HIGH => high[off]
PM_LOW => low[off]
PM_CUST => custom > 0 ? (roundToTick ? math.round(custom / syminfo.mintick) * syminfo.mintick : custom) : na
=> na

// NEW: Gap helpers
f_gap_ok_left(p1Abs, p2Abs) =>
not na(p1Abs) and not na(p2Abs) and (p2Abs - p1Abs) >= minGapBars
f_gap_ok_right(p3Abs, p2Abs) =>
not na(p3Abs) and not na(p2Abs) and (p3Abs - p2Abs) >= minGapBars

//──────────────────────────────── yelow group (EMA200 + 5up/5down) ───────────────────
[mid200, dev200, lm200] = f_core_src(close, emaLen200)
phi_adj = 1.38196601
float fiveUp_200 = na(mid200) or na(dev200) or na(lm200) ? na : mid200 + (lm200 * phi_adj) * dev200
float fiveDown_200 = na(mid200) or na(dev200) or na(lm200) ? na : mid200 - (lm200 * phi_adj) * dev200

plot(show200_5d ? fiveDown_200 : na, title="yelow group down", color=col5band, linewidth=3)
plot(show200Mid ? mid200 : na, title="big brown", color=colMid200, linewidth=3)
plot(show200_5u ? fiveUp_200 : na, title="yelow group up", color=col5band, linewidth=3)

//──────────────────────────────── blue group (EMA85 — 4 up/down) ────────────────────
[mid85, dev85, lm85] = f_core(emaLen85)
float up4_85 = na(mid85) or na(dev85) or na(lm85) ? na : mid85 + lm85 * dev85
float down4_85 = na(mid85) or na(dev85) or na(lm85) ? na : mid85 - lm85 * dev85
float fiveUp_85 = na(mid85) or na(dev85) or na(lm85) ? na : mid85 + (lm85 * phi_adj) * dev85
float fiveDown_85 = na(mid85) or na(dev85) or na(lm85) ? na : mid85 - (lm85 * phi_adj) * dev85
plot(show85_4u ? up4_85 : na, title="blue group up", color=col85_4, linewidth=2)
plot(show85_4d ? down4_85 : na, title="blue group down", color=col85_4, linewidth=2)

// big blue (EMA35)
float ema35 = useClose35 ? ta.ema(close, emaLen35) : ta.ema(effClose, emaLen35)
plot(showEMA35 ? ema35 : na, title="big blue", color=col35, linewidth=2)

// pn (PNR)
float pnr = na
if bar_index >= pnrLen - 1
float[] win = array.new_float()
for i = 0 to pnrLen - 1
array.push(win, pnrSrc)
array.sort(win)
float rankF = (pnrPerc / 100.0) * (pnrLen - 1)
int idx = int(math.round(rankF))
idx := math.max(0, math.min(idx, pnrLen - 1))
pnr := array.get(win, idx)
plot(showPNR ? pnr : na, title="pn", color=colPNR, linewidth=2)
//──────────────────────────────── Masked EMA Clouds (line 1–5) ───────────────────────
groupCloud = "line clouds"
showClouds = input.bool(true, "show lines clouds", group=groupCloud)
l1Len = input.int(5, "line 1 length", minval=1, group=groupCloud)
l2Len = input.int(8, "line 2 length", minval=1, group=groupCloud)
l3Len = input.int(21, "line 3 length", minval=1, group=groupCloud)
l4Len = input.int(34, "line 4 length", minval=1, group=groupCloud)
l5Len = input.int(50, "line 5 length", minval=1, group=groupCloud)
cloudUpColor = input.color(color.green, "cloud up color", group=groupCloud)
cloudDnColor = input.color(color.red, "cloud down color", group=groupCloud)
cloudTransp = input.int(60, "cloud transparency (0–100)", minval=0, maxval=100, group=groupCloud)

l1 = ta.ema(close, l1Len)
l2 = ta.ema(close, l2Len)
l3 = ta.ema(close, l3Len)
l4 = ta.ema(close, l4Len)
l5 = ta.ema(close, l5Len)

// พล็อตเส้นพราง (transp=100) และใช้ชื่อ line 1..5
p1 = plot(showClouds ? l1 : na, color=color.new(color.gray, 100), style=plot.style_line, linewidth=1, title="line 1")
p2 = plot(showClouds ? l2 : na, color=color.new(color.gray, 100), style=plot.style_line, linewidth=1, title="line 2")
p3 = plot(showClouds ? l3 : na, color=color.new(color.gray, 100), style=plot.style_line, linewidth=1, title="line 3")
p4 = plot(showClouds ? l4 : na, color=color.new(color.gray, 100), style=plot.style_line, linewidth=1, title="line 4")
p5 = plot(showClouds ? l5 : na, color=color.new(color.gray, 100), style=plot.style_line, linewidth=1, title="line 5")

// เรียก fill ที่ "global scope" แล้วคุมการแสดงผลด้วยสี (ถ้าไม่โชว์ให้ทำเป็นโปร่งใส)
cloud23Color = showClouds ? (l2 > l3 ? color.new(cloudUpColor, cloudTransp) : color.new(cloudDnColor, cloudTransp)) : color.new(color.black, 100)
cloud45Color = showClouds ? (l4 > l5 ? color.new(cloudUpColor, cloudTransp) : color.new(cloudDnColor, cloudTransp)) : color.new(color.black, 100)

fill(p2, p3, color=cloud23Color, title="cloud 2–3")
fill(p4, p5, color=cloud45Color, title="cloud 4–5")

//──────────────────────────────── Utilities ───────────────────────────────
isGreen_at(i) => close > open
isRed_at(i) => close < open
bodyTop_at(i) => f_bodyTop(open, close)

f_frac_body_above_line(i, lineV) =>
float bt = bodyTop_at(i), bb = f_bodyBot(open, close)
float body = bt - bb
body <= 0 or na(lineV) ? 0.0 : math.max(0.0, bt - math.max(bb, lineV)) / body

f_frac_body_below_line(i, lineV) =>
float bt = bodyTop_at(i), bb = f_bodyBot(open, close)
float body = bt - bb
body <= 0 or na(lineV) ? 0.0 : math.max(0.0, math.min(bt, lineV) - bb) / body

// Draw helpers
var box[] PBOXES = array.new_box()
var label[] PLABELS = array.new_label()

f_delete_boxes(box[] arr) =>
int n = array.size(arr)
for k = 0 to n - 1
int i = n - 1 - k
box.delete(array.get(arr, i))
array.clear(arr)

f_delete_labels(label[] arr) =>
int n = array.size(arr)
for k = 0 to n - 1
int i = n - 1 - k
label.delete(array.get(arr, i))
array.clear(arr)

// size mapper
f_lbl_size(s) =>
s == "tiny" ? size.tiny : s == "large" ? size.large : s == "normal" ? size.normal : size.small

// helper: one-line label.new
f_make_label(_x, _y, _text, _placeAbove) =>
label.new(_x, _y, _text, xloc=xloc.bar_time, style=(_placeAbove ? label.style_label_down : label.style_label_up), textcolor=PLabelTextColor, color=color.new(PLabelBgColor, lblBgTransp), size=f_lbl_size(lblSizeSel))

// smarter label placement (split LONG/SHORT) → return handles
f_add_label_ret(_abs, _text, _isLong) =>
label lb = na
int off = bar_index - _abs
if off >= 0 and off <= 5000 and not na(time[off]) and not na(high[off]) and not na(low[off])
float pad = lblOffsetMet == OM_TICKS ? (syminfo.mintick * lblTicks) : (ta.atr(lblAtrLen)[off] * lblAtrMult)
string opt = _isLong ? lblPlaceLong : lblPlaceShort
bool placeAbove = (opt == LP_ABOVE) ? true : (opt == LP_BELOW) ? false : (close[off] >= open[off])
float yPos = placeAbove ? (high[off] + pad) : (low[off] - pad)
lb := f_make_label(time[off], yPos, _text, placeAbove)
array.push(PLABELS, lb)
if array.size(PLABELS) > 500
label.delete(array.get(PLABELS, 0))
array.remove(PLABELS, 0)
lb

// draw mark → return [box,label]
f_draw_mark_group(_abs, _full, _boxCol, _fillT, _borderT, _labelOn, _labelText, _isLong) =>
box nb = na
label lb = na
if not na(_abs)
int off = bar_index - _abs
if off >= 0 and off <= 5000
float top = _full ? high[off] : bodyTop_at(off)
float bot = _full ? low[off] : f_bodyBot(open[off], close[off])
if showBodyBoxes
nb := box.new(math.max(0, int(_abs) - 1), math.max(top, bot), int(_abs), math.min(top, bot), xloc=xloc.bar_index, bgcolor=color.new(_boxCol, _fillT), border_color=color.new(_boxCol, _borderT))
array.push(PBOXES, nb)
if array.size(PBOXES) > 500
box.delete(array.get(PBOXES, 0))
array.remove(PBOXES, 0)
if _labelOn
lb := f_add_label_ret(_abs, _labelText, _isLong)
[nb, lb]

//───────────────────── De-dup helpers (keep latest; delete older within window) ─────
f_del_if_exists(_bx, _lb) =>
if not na(_bx)
box.delete(_bx)
if not na(_lb)
label.delete(_lb)

// Strict int for last Abs to avoid NA-type errors
var int L_lastP1Abs = int(na)
var int L_lastP2Abs = int(na)
var int L_lastP3Abs = int(na)
var int S_lastP1Abs = int(na)
var int S_lastP2Abs = int(na)
var int S_lastP3Abs = int(na)

// IMPORTANT: declare one per line to keep type info on all variables
var box L_lastP1Box = na
var box L_lastP2Box = na
var box L_lastP3Box = na
var box S_lastP1Box = na
var box S_lastP2Box = na
var box S_lastP3Box = na

var label L_lastP1Lbl = na
var label L_lastP2Lbl = na
var label L_lastP3Lbl = na
var label S_lastP1Lbl = na
var label S_lastP2Lbl = na
var label S_lastP3Lbl = na

// >>> NEW: true-last P2 trackers (separate from de-dup) <<<
var int L_prevP2Abs = int(na)
var float L_prevP2Close = na
var int S_prevP2Abs = int(na)
var float S_prevP2Close = na

// enforce unique per type & side
f_enforce_and_set(_newAbs, _newBox, _newLbl, _lastAbs, _lastBox, _lastLbl) =>
bool keepNew = true
int lastAbsNew = _lastAbs
box lastBoxNew = _lastBox
label lastLblNew = _lastLbl
if not na(_lastAbs) and math.abs(_newAbs - _lastAbs) <= dedupWinBars
if _newAbs > _lastAbs
f_del_if_exists(_lastBox, _lastLbl)
lastAbsNew := _newAbs
lastBoxNew := _newBox
lastLblNew := _newLbl
else
f_del_if_exists(_newBox, _newLbl)
keepNew := false
else
lastAbsNew := _newAbs
lastBoxNew := _newBox
lastLblNew := _newLbl
[keepNew, lastAbsNew, lastBoxNew, lastLblNew]

//──────────────────────────────── FE helpers ───────────────────────────────
f_rt(v) => roundToTick ? math.round(v / syminfo.mintick) * syminfo.mintick : v

var line[] FE_l95 = array.new_line()
var line[] FE_l105 = array.new_line()
var line[] FE_l161 = array.new_line()
var line[] FE_l261 = array.new_line()
var line[] FE_l361 = array.new_line()
var line[] FE_l461 = array.new_line()
var linefill[] FE_fill = array.new_linefill()
var int[] FE_born = array.new_int()

f_delete_fe_index(idx) =>
int nAll = array.size(FE_born)
if idx >= 0 and idx < nAll
if idx < array.size(FE_fill)
linefill.delete(array.get(FE_fill, idx))
if idx < array.size(FE_l95)
line.delete(array.get(FE_l95, idx))
if idx < array.size(FE_l105)
line.delete(array.get(FE_l105, idx))
if idx < array.size(FE_l161)
line.delete(array.get(FE_l161, idx))
if idx < array.size(FE_l261)
line.delete(array.get(FE_l261, idx))
if idx < array.size(FE_l361)
line.delete(array.get(FE_l361, idx))
if idx < array.size(FE_l461)
line.delete(array.get(FE_l461, idx))
if idx < array.size(FE_l95)
array.remove(FE_l95, idx)
if idx < array.size(FE_l105)
array.remove(FE_l105, idx)
if idx < array.size(FE_l161)
array.remove(FE_l161, idx)
if idx < array.size(FE_l261)
array.remove(FE_l261, idx)
if idx < array.size(FE_l361)
array.remove(FE_l361, idx)
if idx < array.size(FE_l461)
array.remove(FE_l461, idx)
if idx < array.size(FE_fill)
array.remove(FE_fill, idx)
array.remove(FE_born, idx)

f_clear_all_fe() =>
int n = array.size(FE_born)
for k = 0 to n - 1
int i = n - 1 - k
f_delete_fe_index(i)

// ───────────── ADD: helper แปลง bar-abs → time (ms) ─────────────
f_abs_to_time(_abs) =>
if na(_abs)
na
else
int off = bar_index - _abs
if off < 0
na
else
int tfms = timeframe.in_seconds(timeframe.period) * 1000
off <= 5000 ? time[off] : (time - off * tfms)

// ───────────── REPLACE: f_add_fe_set เดิม ด้วยเวอร์ชันกัน error ─────────────
f_add_fe_set(p3Abs, y95, y105, y161, y261, y361, y461) =>
int off = bar_index - p3Abs
bool useTime = off > 4500
int tfms = timeframe.in_seconds(timeframe.period) * 1000

color c95 = show95_105 ? colBand : color.new(colBand, 100)
color c105 = show95_105 ? colBand : color.new(colBand, 100)
color c161 = show1618 ? col1618 : color.new(col1618, 100)
color c261 = show2618 ? col2618 : color.new(col2618, 100)
color c361 = show3618 ? col3618 : color.new(col3618, 100)
color c461 = show4618 ? col4618 : color.new(col4618, 100)

// <<< แก้ไขตรงนี้: ประกาศตัวแปร line ทีละบรรทัด >>>
line l95 = na
line l105 = na
line l161 = na
line l261 = na
line l361 = na
line l461 = na
linefill lf = na

if not useTime
int x1 = p3Abs
int x2 = p3Abs + feLenBars
l95 := line.new(x1, y95, x2, y95, xloc=xloc.bar_index, extend=extend.none, color=c95, width=3)
l105 := line.new(x1, y105, x2, y105, xloc=xloc.bar_index, extend=extend.none, color=c105, width=3)
l161 := line.new(x1, y161, x2, y161, xloc=xloc.bar_index, extend=extend.none, color=c161, width=2)
l261 := line.new(x1, y261, x2, y261, xloc=xloc.bar_index, extend=extend.none, color=c261, width=2)
l361 := line.new(x1, y361, x2, y361, xloc=xloc.bar_index, extend=extend.none, color=c361, width=2)
l461 := line.new(x1, y461, x2, y461, xloc=xloc.bar_index, extend=extend.none, color=c461, width=2)
lf := linefill.new(l95, l105, color= show95_105 ? colBandFill : color.new(color.black, 100))
else
int t1 = f_abs_to_time(p3Abs)
int t2 = int(na)
if not na(t1)
t2 := t1 + feLenBars * tfms
l95 := line.new(t1, y95, t2, y95, xloc=xloc.bar_time, extend=extend.none, color=c95, width=3)
l105 := line.new(t1, y105, t2, y105, xloc=xloc.bar_time, extend=extend.none, color=c105, width=3)
l161 := line.new(t1, y161, t2, y161, xloc=xloc.bar_time, extend=extend.none, color=c161, width=2)
l261 := line.new(t1, y261, t2, y261, xloc=xloc.bar_time, extend=extend.none, color=c261, width=2)
l361 := line.new(t1, y361, t2, y361, xloc=xloc.bar_time, extend=extend.none, color=c361, width=2)
l461 := line.new(t1, y461, t2, y461, xloc=xloc.bar_time, extend=extend.none, color=c461, width=2)
lf := linefill.new(l95, l105, color= show95_105 ? colBandFill : color.new(color.black, 100))

array.push(FE_l95, l95)
array.push(FE_l105, l105)
array.push(FE_l161, l161)
array.push(FE_l261, l261)
array.push(FE_l361, l361)
array.push(FE_l461, l461)
array.push(FE_fill, lf)
array.push(FE_born, bar_index)

f_find_abs_by_time(t) =>
int bestAbs = na
if na(t)
na
else
int maxBack = math.min(5000, bar_index)
int bestDiff = 1000000000
for i = 0 to maxBack
int ti = time
int diff = ti > t ? (ti - t) : (t - ti)
if diff < bestDiff
bestDiff := diff
bestAbs := bar_index - i
bestAbs

//──────────────────────────────── P3 picker (แบบเดิม/คลาสสิก) ─────────────────────
f_pickP3_abs(sAbs, eAbs, isLong) =>
if na(sAbs) or na(eAbs)
[na, na]
else
int eInit = math.min(eAbs, bar_index)
int sInit = sAbs
int s = math.max(sInit, bar_index - 10000)
int e = eInit
if s > e
[na, na]
else
float[] levels = array.new_float()
int[] counts = array.new_int()
int[] firstI = array.new_int()
int[] maxRun = array.new_int()
float prevBin = na
int curRun = 0
float minLowGreen = 1e100
int minLowGreenI = na
float minLowRed = 1e100
int minLowRedI = na
float minLowAll = 1e100
int minLowAllI = na
float maxHighRed = -1e100
int maxHighRedI = na
float maxHighGreen = -1e100
int maxHighGreenI= na
float maxHighAll = -1e100
int maxHighAllI = na
for t = s to e
int tOff = bar_index - t
if tOff < 0 or tOff > 10000
continue
float bin = math.round(open[tOff] / syminfo.mintick) * syminfo.mintick
int idx = array.indexof(levels, bin)
if idx == -1
array.push(levels, bin)
array.push(counts, 1)
array.push(firstI, t)
array.push(maxRun, 1)
curRun := 1
else
array.set(counts, idx, array.get(counts, idx) + 1)
if not na(prevBin) and bin == prevBin
curRun += 1
else
curRun := 1
int prevMax = array.get(maxRun, idx)
if curRun > prevMax
array.set(maxRun, idx, curRun)
prevBin := bin
// ... (ส่วนท้ายของ f_pickP3_abs เดิม)
int needCnt = 2
int best = -1, bestCnt = 0, bestRun = 0, bestFirst = 1000000000
int L = array.size(levels)
if L > 0
for m = 0 to L - 1
int c = array.get(counts, m)
if c >= needCnt
int r = array.get(maxRun, m)
int f = array.get(firstI, m)
if c > bestCnt or (c == bestCnt and (r > bestRun or (r == bestRun and f < bestFirst)))
best := m
bestCnt := c
bestRun := r
bestFirst := f
if best != -1
int pickAbs = array.get(firstI, best)
float pickPx = array.get(levels, best)
[pickPx, pickAbs]
else
if isLong
// เลือกจาก logic เดิม (ย่อ)
float minLowGreen = 1e100
int minLowGreenI = na
float minLowRed = 1e100
int minLowRedI = na
float minLowAll = 1e100
int minLowAllI = na
for t2 = s to e
int toff2 = bar_index - t2
if toff2 < 0 or toff2 > 10000
continue
bool g = close[toff2] > open[toff2]
bool r = close[toff2] < open[toff2]
if g and low[toff2] < minLowGreen
minLowGreen := low[toff2]
minLowGreenI := t2
if r and low[toff2] < minLowRed
minLowRed := low[toff2]
minLowRedI := t2
if low[toff2] < minLowAll
minLowAll := low[toff2]
minLowAllI := t2
bool redIsGlobalMin = not na(minLowRedI) and (minLowRed <= minLowAll + 0.0)
if redIsGlobalMin
int offR = bar_index - minLowRedI
[close[offR], minLowRedI]
else
int useAbs = na(minLowGreenI) ? minLowAllI : minLowGreenI
int offU = bar_index - useAbs
[open[offU], useAbs]
else
float maxHighRed = -1e100
int maxHighRedI = na
float maxHighGreen = -1e100
int maxHighGreenI= na
float maxHighAll = -1e100
int maxHighAllI = na
for t3 = s to e
int toff3 = bar_index - t3
if toff3 < 0 or toff3 > 10000
continue
bool g2 = close[toff3] > open[toff3]
bool r2 = close[toff3] < open[toff3]
if r2 and high[toff3] > maxHighRed
maxHighRed := high[toff3]
maxHighRedI := t3
if g2 and high[toff3] > maxHighGreen
maxHighGreen := high[toff3]
maxHighGreenI:= t3
if high[toff3] > maxHighAll
maxHighAll := high[toff3]
maxHighAllI := t3
bool greenIsGlobalMax = not na(maxHighGreenI) and (maxHighGreen >= maxHighAll - 0.0)
if greenIsGlobalMax
int offG = bar_index - maxHighGreenI
[close[offG], maxHighGreenI]
else
int useAbsS = na(maxHighRedI) ? maxHighAllI : maxHighRedI
int offS = bar_index - useAbsS
[open[offS], useAbsS]

//──────────────────────────────── P1/P2/P3 (Auto; state) ────────────────
// LONG state vars
var int L_P1Abs = int(na)
var int L_P2Abs = int(na)
var int L_P3Abs = int(na)
var int L_winOpenAbs = int(na)
var float L_P1Open = na
var float L_P2Close = na
var float L_P3Px = na
var float L_P2_bodyTop = na
var float L_P2_bodyBot = na

// SHORT state vars
var int S_P1Abs = int(na)
var int S_P2Abs = int(na)
var int S_P3Abs = int(na)
var int S_winOpenAbs = int(na)
var float S_P1Open = na
var float S_P2Close = na
var float S_P3Px = na
var float S_P2_bodyTop = na
var float S_P2_bodyBot = na

// draw-set containers
var box[] L_SET_BOX = array.new_box()
var label[] L_SET_LBL = array.new_label()
var box[] S_SET_BOX = array.new_box()
var label[] S_SET_LBL = array.new_label()

// scanners
var bool L_seek = false
var bool L_confirmActive = false
var int L_runMaxAbs = int(na)
var float L_runMaxClose = na
var int L_candAbs = int(na)
var float L_candClose = na

var bool S_seek = false
var bool S_confirmActive = false
var int S_runMinAbs = int(na)
var float S_runMinClose = na
var int S_candAbs = int(na)
var float S_candClose = na

// LONG: seed/confirm P2 (UPDATED: ต้องทั้งแท่งอยู่เหนือ fiveUp_200)
if not L_seek and not L_confirmActive
float __btL = math.max(open, close)
float __bbL = math.min(open, close)
float __fiveL = fiveUp_200
bool startLongSeed = close > open and not na(__fiveL) and (__bbL >= __fiveL)
if startLongSeed
L_seek := true
L_runMaxAbs := bar_index
L_runMaxClose := close

if L_confirmActive
if close > L_candClose and close > open
L_seek := true
L_confirmActive := false
L_candAbs := int(na)
L_candClose := na
L_runMaxAbs := bar_index
L_runMaxClose := close
else if bar_index >= L_candAbs + rightWinBars
bool acceptL = true
// ตรวจซ้ำที่แท่งผู้สมัคร (ทั้งแท่งต้องอยู่เหนือ fiveUp_200)
int offCandL = bar_index - L_candAbs
float _btL = math.max(open[offCandL], close[offCandL])
float _bbL = math.min(open[offCandL], close[offCandL])
float _fiveL = fiveUp_200[offCandL]
bool bodyAbove5 = not na(_fiveL) and (_bbL >= _fiveL)
acceptL := acceptL and bodyAbove5

if not na(L_prevP2Abs)
int dBarsL = L_candAbs - L_prevP2Abs
if dBarsL <= p2NewWithinBars
acceptL := acceptL and (L_candClose > L_prevP2Close)
if not acceptL
L_seek := true
L_confirmActive := false
L_runMaxAbs := bar_index
L_runMaxClose := close
L_candAbs := int(na)
L_candClose := na
else
array.clear(L_SET_BOX)
array.clear(L_SET_LBL)
L_P2Abs := L_candAbs

resetReqAllL := false
resetReqP1L := false
resetReqP2L := false
resetReqP3L := false

int offP2 = bar_index - L_P2Abs
L_P2Close := close[offP2]
L_P2_bodyTop := math.max(open[offP2], close[offP2])
L_P2_bodyBot := math.min(open[offP2], close[offP2])

L_prevP2Abs := L_P2Abs
L_prevP2Close := L_P2Close

[bxP2, lbP2] = f_draw_mark_group(L_P2Abs, false, P2BoxColor, P2BoxFillTransp, BoxBorderTransp, showP2Label, "P2", true)
[keepNewP2L, _newAbsP2L, _newBoxP2L, _newLblP2L] = f_enforce_and_set(L_P2Abs, bxP2, lbP2, L_lastP2Abs, L_lastP2Box, L_lastP2Lbl)
if keepNewP2L
L_lastP2Abs := _newAbsP2L
L_lastP2Box := _newBoxP2L
L_lastP2Lbl := _newLblP2L

f_del_if_exists(L_lastP3Box, L_lastP3Lbl)
L_lastP3Abs := int(na)
L_lastP3Box := na
L_lastP3Lbl := na
L_P3Abs := int(na)
L_P3Px := na
f_clear_all_fe()

L_winOpenAbs := L_P2Abs + 1

int bestAbs = int(na)
float bestDist = na
for k = 1 to 50
int a = L_P2Abs - k
if a < 0
break
int off = bar_index - a
if off < 0 or off > 5000
continue
if close[off] <= open[off]
continue
float ema5u85 = fiveUp_85[off]
if na(ema5u85)
continue
float bt = math.max(open[off], close[off])
float bb = math.min(open[off], close[off])
float body = bt - bb
float fracAbove = body <= 0 ? 0.0 : math.max(0.0, bt - math.max(bb, ema5u85))/body
if fracAbove >= 0.25
float d = math.abs(mid200[off] - (bt+bb)/2.0)
if na(bestDist) or d < bestDist or (d == bestDist and (na(bestAbs) or a < bestAbs))
bestDist := d
bestAbs := a
if not na(bestAbs) and f_gap_ok_left(bestAbs, L_P2Abs)
int offb = bar_index - bestAbs
L_P1Open := open[offb]
L_P1Abs := bestAbs
[bxP1, lbP1] = f_draw_mark_group(L_P1Abs, false, P1BoxColor, P1BoxFillTransp, BoxBorderTransp, showP1Label, "P1", true)
[keepNewP1L, _newAbsP1L, _newBoxP1L, _newLblP1L] = f_enforce_and_set(L_P1Abs, bxP1, lbP1, L_lastP1Abs, L_lastP1Box, L_lastP1Lbl)
if keepNewP1L
L_lastP1Abs := _newAbsP1L
L_lastP1Box := _newBoxP1L
L_lastP1Lbl := _newLblP1L

L_seek := false
L_confirmActive := false
L_candAbs := int(na)
L_candClose := na
L_runMaxAbs := int(na)
L_runMaxClose := na

if L_seek and not L_confirmActive
if close > open
if close > nz(L_runMaxClose, -1e100)
L_runMaxClose := close
L_runMaxAbs := bar_index
else if close < nz(L_runMaxClose, 1e100)
L_candAbs := L_runMaxAbs
L_candClose := L_runMaxClose
L_seek := false
L_confirmActive := true
else if open < nz(L_runMaxClose, 1e100)
L_candAbs := L_runMaxAbs
L_candClose := L_runMaxClose
L_seek := false
L_confirmActive := true

// SHORT: seed/confirm P2 (UPDATED: ต้องทั้งแท่งอยู่ใต้ fiveDown_200)
if not S_seek and not S_confirmActive
float __btS = math.max(open, close)
float __bbS = math.min(open, close)
float __fiveS = fiveDown_200
bool startShortSeed = close < open and not na(__fiveS) and (__btS <= __fiveS)
if startShortSeed
S_seek := true
S_runMinAbs := bar_index
S_runMinClose := close

if S_confirmActive
if close < S_candClose and close < open
S_seek := true
S_confirmActive := false
S_candAbs := int(na)
S_candClose := na
S_runMinAbs := bar_index
S_runMinClose := close
else if bar_index >= S_candAbs + rightWinBars
bool acceptS = true
// ตรวจซ้ำที่แท่งผู้สมัคร (ทั้งแท่งต้องอยู่ใต้ fiveDown_200)
int offCandS = bar_index - S_candAbs
float _btS = math.max(open[offCandS], close[offCandS])
float _bbS = math.min(open[offCandS], close[offCandS])
float _fiveS = fiveDown_200[offCandS]
bool bodyBelow5 = not na(_fiveS) and (_btS <= _fiveS)
acceptS := acceptS and bodyBelow5

if not na(S_prevP2Abs)
int dBarsS = S_candAbs - S_prevP2Abs
if dBarsS <= p2NewWithinBars
acceptS := acceptS and (S_candClose < S_prevP2Close)
if not acceptS
S_seek := true
S_confirmActive := false
S_runMinAbs := bar_index
S_runMinClose := close
S_candAbs := int(na)
S_candClose := na
else
array.clear(S_SET_BOX)
array.clear(S_SET_LBL)
S_P2Abs := S_candAbs

resetReqAllS := false
resetReqP1S := false
resetReqP2S := false
resetReqP3S := false

int offP2s = bar_index - S_P2Abs
S_P2Close := close[offP2s]
S_P2_bodyTop := math.max(open[offP2s], close[offP2s])
S_P2_bodyBot := math.min(open[offP2s], close[offP2s])

S_prevP2Abs := S_P2Abs
S_prevP2Close := S_P2Close

[bxP2s, lbP2s] = f_draw_mark_group(S_P2Abs, false, P2BoxColor, P2BoxFillTransp, BoxBorderTransp, showP2Label, "P2", false)
[keepNewP2S, _newAbsP2S, _newBoxP2S, _newLblP2S] = f_enforce_and_set(S_P2Abs, bxP2s, lbP2s, S_lastP2Abs, S_lastP2Box, S_lastP2Lbl)
if keepNewP2S
S_lastP2Abs := _newAbsP2S
S_lastP2Box := _newBoxP2S
S_lastP2Lbl := _newLblP2S

f_del_if_exists(S_lastP3Box, S_lastP3Lbl)
S_lastP3Abs := int(na)
S_lastP3Box := na
S_lastP3Lbl := na
S_P3Abs := int(na)
S_P3Px := na
f_clear_all_fe()

S_winOpenAbs := S_P2Abs + 1

int bestAbsS = int(na)
float bestDistS = na
for k = 1 to 50
int a = S_P2Abs - k
if a < 0
break
int off = bar_index - a
if off < 0 or off > 5000
continue
if close[off] >= open[off]
continue
float ema5d85 = fiveDown_85[off]
if na(ema5d85)
continue
float bt = math.max(open[off], close[off])
float bb = math.min(open[off], close[off])
float body = bt - bb
float fracBelow = body <= 0 ? 0.0 : math.max(0.0, math.min(bt, ema5d85) - bb)/body
if fracBelow >= 0.25
float d = math.abs(mid200[off] - (bt+bb)/2.0)
if na(bestDistS) or d < bestDistS or (d == bestDistS and (na(bestAbsS) or a < bestAbsS))
bestDistS := d
bestAbsS := a
if not na(bestAbsS) and f_gap_ok_left(bestAbsS, S_P2Abs)
int offb = bar_index - bestAbsS
S_P1Open := open[offb]
S_P1Abs := bestAbsS
[bxP1s, lbP1s] = f_draw_mark_group(S_P1Abs, false, P1BoxColor, P1BoxFillTransp, BoxBorderTransp, showP1Label, "P1", false)
[keepNewP1S, _newAbsP1S, _newBoxP1S, _newLblP1S] = f_enforce_and_set(S_P1Abs, bxP1s, lbP1s, S_lastP1Abs, S_lastP1Box, S_lastP1Lbl)
if keepNewP1S
S_lastP1Abs := _newAbsP1S
S_lastP1Box := _newBoxP1S
S_lastP1Lbl := _newLblP1S

S_seek := false
S_confirmActive := false
S_candAbs := int(na)
S_candClose := na
S_runMinAbs := int(na)
S_runMinClose := na

if S_seek and not S_confirmActive
if close < open
if close < nz(S_runMinClose, 1e100)
S_runMinClose := close
S_runMinAbs := bar_index
else if close > nz(S_runMinClose, -1e100)
S_candAbs := S_runMinAbs
S_candClose := S_runMinClose
S_seek := false
S_confirmActive := true
else if open > nz(S_runMinClose, -1e100)
S_candAbs := S_runMinAbs
S_candClose := S_runMinClose
S_seek := false
S_confirmActive := true

// ---------- LONG: close P3 window (classic picker) ----------
if not na(L_winOpenAbs)
int sAbs = L_winOpenAbs
int eAbs = bar_index
float rangeBody = L_P2_bodyTop - L_P2_bodyBot
float T33 = L_P2_bodyBot + rangeBody/3.0
float T75 = L_P2_bodyBot + rangeBody*0.75
int barsInWin = bar_index - L_winOpenAbs + 1
bool allowNormal = barsInWin >= 5 and close > open and close >= T33
bool allowEarly = barsInWin < 5 and close > open and close >= T75
if allowNormal or allowEarly
[p3PxL_tmp, p3AbsL] = f_pickP3_abs(sAbs, eAbs, true)
if not na(p3AbsL) and f_gap_ok_right(p3AbsL, L_P2Abs)
L_P3Abs := p3AbsL
L_P3Px := p3PxL_tmp
[bxP3, lbP3] = f_draw_mark_group(L_P3Abs, false, P3BoxColor, P3BoxFillTransp, BoxBorderTransp, showP3Label, "P3", true)
[keepNewP3L, _newAbsP3L, _newBoxP3L, _newLblP3L] = f_enforce_and_set(L_P3Abs, bxP3, lbP3, L_lastP3Abs, L_lastP3Box, L_lastP3Lbl)
if keepNewP3L
L_lastP3Abs := _newAbsP3L
L_lastP3Box := _newBoxP3L
L_lastP3Lbl := _newLblP3L

if showFE and not na(L_P1Open) and not na(L_P2Close)
float W = L_P2Close - L_P1Open
if W > 0
float y95 = f_rt(L_P3Px + 0.95 * W)
float y105 = f_rt(L_P3Px + 1.05 * W)
float y1618 = f_rt(L_P3Px + 1.618 * W)
float y2618 = f_rt(L_P3Px + 2.618 * W)
float y3618 = f_rt(L_P3Px + 3.618 * W)
float y4618 = f_rt(L_P3Px + 4.618 * W)
f_clear_all_fe()
f_add_fe_set(L_P3Abs, y95, y105, y1618, y2618, y3618, y4618)
L_winOpenAbs := int(na)

// ---------- SHORT: close P3 window (classic picker) ----------
if not na(S_winOpenAbs)
int sAbsS = S_winOpenAbs
int eAbsS = bar_index
float rangeBodyS = S_P2_bodyTop - S_P2_bodyBot
float T33d = S_P2_bodyTop - rangeBodyS/3.0
float T75d = S_P2_bodyTop - rangeBodyS*0.75
int barsInWinS = bar_index - S_winOpenAbs + 1
bool allowNormalS = barsInWinS >= 5 and close < open and close <= T33d
bool allowEarlyS = barsInWinS < 5 and close < open and close <= T75d
if allowNormalS or allowEarlyS
[p3PxS_tmp, p3AbsS] = f_pickP3_abs(sAbsS, eAbsS, false)
if not na(p3AbsS) and f_gap_ok_right(p3AbsS, S_P2Abs)
S_P3Abs := p3AbsS
S_P3Px := p3PxS_tmp
[bxP3s, lbP3s] = f_draw_mark_group(S_P3Abs, false, P3BoxColor, P3BoxFillTransp, BoxBorderTransp, showP3Label, "P3", false)
[keepNewP3S, _newAbsP3S, _newBoxP3S, _newLblP3S] = f_enforce_and_set(S_P3Abs, bxP3s, lbP3s, S_lastP3Abs, S_lastP3Box, S_lastP3Lbl)
if keepNewP3S
S_lastP3Abs := _newAbsP3S
S_lastP3Box := _newBoxP3S
S_lastP3Lbl := _newLblP3S

if showFE and not na(S_P1Open) and not na(S_P2Close)
float Ws = S_P2Close - S_P1Open
if Ws < 0
float y95s = f_rt(S_P3Px + 0.95 * Ws)
float y105s = f_rt(S_P3Px + 1.05 * Ws)
float y1618s = f_rt(S_P3Px + 1.618 * Ws)
float y2618s = f_rt(S_P3Px + 2.618 * Ws)
float y3618s = f_rt(S_P3Px + 3.618 * Ws)
float y4618s = f_rt(S_P3Px + 4.618 * Ws)
f_clear_all_fe()
f_add_fe_set(S_P3Abs, y95s, y105s, y1618s, y2618s, y3618s, y4618s)
S_winOpenAbs := int(na)

//──────────────────────────────── Manual Layer (+ Reset Latches) ─────────────────────
f_pick_abs_from_manual(_use, _pickMode, _time, _offset) =>
if not _use
na
else
_pickMode == PK_TIME ? f_find_abs_by_time(_time) : (bar_index + _offset)

f_pick_price_from_manual(_use, _abs, _pmode, _custom) =>
if not _use or na(_abs)
na
else
int off = bar_index - _abs
off < 0 or off > 5000 ? na : f_price_by_mode(off, _pmode, _custom)

useP1L_eff = useManP1L and not (resetReqAllL or resetReqP1L)
useP2L_eff = useManP2L and not (resetReqAllL or resetReqP2L)
useP3L_eff = useManP3L and not (resetReqAllL or resetReqP3L)

useP1S_eff = useManP1S and not (resetReqAllS or resetReqP1S)
useP2S_eff = useManP2S and not (resetReqAllS or resetReqP2S)
useP3S_eff = useManP3S and not (resetReqAllS or resetReqP3S)

// Effective ABS
int L_P1Abs_eff = useP1L_eff ? f_pick_abs_from_manual(useP1L_eff, pickP1L, manP1L_t, manP1L_of) : L_P1Abs
int L_P2Abs_eff = useP2L_eff ? f_pick_abs_from_manual(useP2L_eff, pickP2L, manP2L_t, manP2L_of) : L_P2Abs
int L_P3Abs_eff = useP3L_eff ? f_pick_abs_from_manual(useP3L_eff, pickP3L, manP3L_t, manP3L_of) : L_P3Abs

int S_P1Abs_eff = useP1S_eff ? f_pick_abs_from_manual(useP1S_eff, pickP1S, manP1S_t, manP1S_of) : S_P1Abs
int S_P2Abs_eff = useP2S_eff ? f_pick_abs_from_manual(useP2S_eff, pickP2S, manP2S_t, manP2S_of) : S_P2Abs
int S_P3Abs_eff = useP3S_eff ? f_pick_abs_from_manual(useP3S_eff, pickP3S, manP3S_t, manP3S_of) : S_P3Abs

// Effective Prices
float L_P1Open_eff = useP1L_eff ? f_pick_price_from_manual(useP1L_eff, L_P1Abs_eff, pmP1L, p1L_custom) : L_P1Open
float L_P2Close_eff = useP2L_eff ? f_pick_price_from_manual(useP2L_eff, L_P2Abs_eff, pmP2L, p2L_custom) : L_P2Close
float L_P3Px_eff = useP3L_eff ? f_pick_price_from_manual(useP3L_eff, L_P3Abs_eff, pmP3L, p3L_custom) : L_P3Px

float S_P1Open_eff = useP1S_eff ? f_pick_price_from_manual(useP1S_eff, S_P1Abs_eff, pmP1S, p1S_custom) : S_P1Open
float S_P2Close_eff = useP2S_eff ? f_pick_price_from_manual(useP2S_eff, S_P2Abs_eff, pmP2S, p2S_custom) : S_P2Close
float S_P3Px_eff = useP3S_eff ? f_pick_price_from_manual(useP3S_eff, S_P3Abs_eff, pmP3S, p3S_custom) : S_P3Px

// Redraw labels/boxes if manual in effect (apply de-dup too) — with GAP RULE
bool needRedrawL = useP1L_eff or useP2L_eff or useP3L_eff
bool needRedrawS = useP1S_eff or useP2S_eff or useP3S_eff
if needRedrawL
f_delete_boxes(L_SET_BOX)
f_delete_labels(L_SET_LBL)
if not na(L_P1Abs_eff) and not na(L_P2Abs_eff) and f_gap_ok_left(L_P1Abs_eff, L_P2Abs_eff) and showP1Label
[bx1, lb1] = f_draw_mark_group(L_P1Abs_eff, false, P1BoxColor, P1BoxFillTransp, BoxBorderTransp, true, "P1", true)
[keepP1L_m, nAbsP1L_m, nBoxP1L_m, nLblP1L_m] = f_enforce_and_set(L_P1Abs_eff, bx1, lb1, L_lastP1Abs, L_lastP1Box, L_lastP1Lbl)
if keepP1L_m
L_lastP1Abs := nAbsP1L_m
L_lastP1Box := nBoxP1L_m
L_lastP1Lbl := nLblP1L_m
if not na(L_P2Abs_eff) and showP2Label
[bx2, lb2] = f_draw_mark_group(L_P2Abs_eff, false, P2BoxColor, P2BoxFillTransp, BoxBorderTransp, true, "P2", true)
[keepP2L_m, nAbsP2L_m, nBoxP2L_m, nLblP2L_m] = f_enforce_and_set(L_P2Abs_eff, bx2, lb2, L_lastP2Abs, L_lastP2Box, L_lastP2Lbl)
if keepP2L_m
L_lastP2Abs := nAbsP2L_m
L_lastP2Box := nBoxP2L_m
L_lastP2Lbl := nLblP2L_m
if not na(L_P3Abs_eff) and not na(L_P2Abs_eff) and f_gap_ok_right(L_P3Abs_eff, L_P2Abs_eff) and showP3Label
[bx3, lb3] = f_draw_mark_group(L_P3Abs_eff, false, P3BoxColor, P3BoxFillTransp, BoxBorderTransp, true, "P3", true)
[keepP3L_m, nAbsP3L_m, nBoxP3L_m, nLblP3L_m] = f_enforce_and_set(L_P3Abs_eff, bx3, lb3, L_lastP3Abs, L_lastP3Box, L_lastP3Lbl)
if keepP3L_m
L_lastP3Abs := nAbsP3L_m
L_lastP3Box := nBoxP3L_m
L_lastP3Lbl := nLblP3L_m
if needRedrawS
f_delete_boxes(S_SET_BOX)
f_delete_labels(S_SET_LBL)
if not na(S_P1Abs_eff) and not na(S_P2Abs_eff) and f_gap_ok_left(S_P1Abs_eff, S_P2Abs_eff) and showP1Label
[bx1s, lb1s] = f_draw_mark_group(S_P1Abs_eff, false, P1BoxColor, P1BoxFillTransp, BoxBorderTransp, true, "P1", false)
[keepP1S_m, nAbsP1S_m, nBoxP1S_m, nLblP1S_m] = f_enforce_and_set(S_P1Abs_eff, bx1s, lb1s, S_lastP1Abs, S_lastP1Box, S_lastP1Lbl)
if keepP1S_m
S_lastP1Abs := nAbsP1S_m
S_lastP1Box := nBoxP1S_m
S_lastP1Lbl := nLblP1S_m
if not na(S_P2Abs_eff) and showP2Label
[bx2s, lb2s] = f_draw_mark_group(S_P2Abs_eff, false, P2BoxColor, P2BoxFillTransp, BoxBorderTransp, true, "P2", false)
[keepP2S_m, nAbsP2S_m, nBoxP2S_m, nLblP2S_m] = f_enforce_and_set(S_P2Abs_eff, bx2s, lb2s, S_lastP2Abs, S_lastP2Box, S_lastP2Lbl)
if keepP2S_m
S_lastP2Abs := nAbsP2S_m
S_lastP2Box := nBoxP2S_m
S_lastP2Lbl := nLblP2S_m
if not na(S_P3Abs_eff) and not na(S_P2Abs_eff) and f_gap_ok_right(S_P3Abs_eff, S_P2Abs_eff) and showP3Label
[bx3s, lb3s] = f_draw_mark_group(S_P3Abs_eff, false, P3BoxColor, P3BoxFillTransp, BoxBorderTransp, true, "P3", false)
[keepP3S_m, nAbsP3S_m, nBoxP3S_m, nLblP3S_m] = f_enforce_and_set(S_P3Abs_eff, bx3s, lb3s, S_lastP3Abs, S_lastP3Box, S_lastP3Lbl)
if keepP3S_m
S_lastP3Abs := nAbsP3S_m
S_lastP3Box := nBoxP3S_m
S_lastP3Lbl := nLblP3S_m

// FE from effective points (Manual precedence) — add GAP RULE
bool canFE_L = showFE and not na(L_P1Open_eff) and not na(L_P2Close_eff) and not na(L_P3Px_eff) and not na(L_P1Abs_eff) and not na(L_P2Abs_eff) and not na(L_P3Abs_eff) and f_gap_ok_left(L_P1Abs_eff, L_P2Abs_eff) and f_gap_ok_right(L_P3Abs_eff, L_P2Abs_eff)
bool canFE_S = showFE and not na(S_P1Open_eff) and not na(S_P2Close_eff) and not na(S_P3Px_eff) and not na(S_P1Abs_eff) and not na(S_P2Abs_eff) and not na(S_P3Abs_eff) and f_gap_ok_left(S_P1Abs_eff, S_P2Abs_eff) and f_gap_ok_right(S_P3Abs_eff, S_P2Abs_eff)

if canFE_L
float W = L_P2Close_eff - L_P1Open_eff
if W > 0
float y95 = f_rt(L_P3Px_eff + 0.95 * W)
float y105 = f_rt(L_P3Px_eff + 1.05 * W)
float y1618 = f_rt(L_P3Px_eff + 1.618 * W)
float y2618 = f_rt(L_P3Px_eff + 2.618 * W)
float y3618 = f_rt(L_P3Px_eff + 3.618 * W)
float y4618 = f_rt(L_P3Px_eff + 4.618 * W)
f_clear_all_fe()
f_add_fe_set(L_P3Abs_eff, y95, y105, y1618, y2618, y3618, y4618)
else if canFE_S
float Ws = S_P2Close_eff - S_P1Open_eff
if Ws < 0
float y95s = f_rt(S_P3Px_eff + 0.95 * Ws)
float y105s = f_rt(S_P3Px_eff + 1.05 * Ws)
float y1618s = f_rt(S_P3Px_eff + 1.618 * Ws)
float y2618s = f_rt(S_P3Px_eff + 2.618 * Ws)
float y3618s = f_rt(S_P3Px_eff + 3.618 * Ws)
float y4618s = f_rt(S_P3Px_eff + 4.618 * Ws)
f_clear_all_fe()
f_add_fe_set(S_P3Abs_eff, y95s, y105s, y1618s, y2618s, y3618s, y4618s)

// FE lifespan cleanup
int nBorn = array.size(FE_born)
if nBorn > 0
for k = 0 to nBorn - 1
int idx = nBorn - 1 - k
int born = array.get(FE_born, idx)
if bar_index - born > feLife
f_delete_fe_index(idx)

// Candle coloring
bool isP1_bar = (not na(L_P1Abs_eff) and bar_index == L_P1Abs_eff) or (not na(S_P1Abs_eff) and bar_index == S_P1Abs_eff)
bool isP2_bar = (not na(L_P2Abs_eff) and bar_index == L_P2Abs_eff) or (not na(S_P2Abs_eff) and bar_index == S_P2Abs_eff)
bool isP3_bar = (not na(L_P3Abs_eff) and bar_index == L_P3Abs_eff) or (not na(S_P3Abs_eff) and bar_index == S_P3Abs_eff)
color _candleCol = na
_candleCol := isP3_bar ? colP3Candle : (isP2_bar ? colP2Candle : (isP1_bar ? colP1Candle : na))
barcolor(recolorBars ? _candleCol : na)

// Reserve style slot
plot(showFE ? na : na, title="fe-slot")

//──────────────────────────────── di (DSI; masked) ───────────────────────────
float dsi_atr = ta.atr(14)
float dsi_highestBody = open > close ? open : close
float dsi_lowestBody = open > close ? close : open

var float dsi_res1 = na
var float dsi_res2 = na
var float dsi_sup1 = na
var float dsi_sup2 = na
var bool dsi_lookForNewResistance = true
var bool dsi_lookForNewSupport = true
var float dsi_prevRes1 = na
var float dsi_prevRes2 = na
var float dsi_prevSup1 = na
var float dsi_prevSup2 = na
var float dsi_atrSaved = na
var float dsi_potR1 = na
var float dsi_potR2 = na
var float dsi_potS1 = na
var float dsi_potS2 = na

if high[1] == ta.highest(high, lookback) and high < high[1] and dsi_lookForNewResistance
float r1 = high[1]
float hb2 = (open[2] > close[2] ? open[2] : close[2])
float hb1 = (open[1] > close[1] ? open[1] : close[1])
float hb0 = (open > close ? open : close)
float r2 = hb2 > hb1 ? hb2 : (hb0 > hb1 ? hb0 : hb1)
if (r1 - r2) / dsi_atr <= maxZoneSize
dsi_lookForNewResistance := false
dsi_potR1 := r1
dsi_potR2 := r2
dsi_atrSaved := dsi_atr

if low[1] == ta.lowest(low, lookback) and low > low[1] and dsi_lookForNewSupport
float s1 = low[1]
float lb2 = (open[2] > close[2] ? close[2] : open[2])
float lb1 = (open[1] > close[1] ? close[1] : open[1])
float lb0 = (open > close ? close : open)
float s2 = lb2 < lb1 ? lb2 : (lb0 < lb1 ? lb0 : lb1)
if (s2 - s1) / dsi_atr <= maxZoneSize
dsi_lookForNewSupport := false
dsi_potS1 := s1
dsi_potS2 := s2
dsi_atrSaved := dsi_atr

if close > dsi_potR1 and barstate.isconfirmed
dsi_potR1 := na
dsi_potR2 := na
if close < dsi_potS1 and barstate.isconfirmed
dsi_potS1 := na
dsi_potS2 := na

if not na(dsi_potR1) and dsi_potR1 - low >= (nz(dsi_atrSaved, dsi_atr) * atrMovement)
dsi_prevRes1 := na(dsi_prevRes1) ? dsi_potR1 : dsi_prevRes1
dsi_prevRes2 := na(dsi_prevRes2) ? dsi_potR2 : dsi_prevRes2
dsi_res1 := dsi_potR1
dsi_res2 := dsi_potR2
dsi_potR1 := na
dsi_potR2 := na

if not na(dsi_potS1) and high - dsi_potS1 >= (nz(dsi_atrSaved, dsi_atr) * atrMovement)
dsi_prevSup1 := na(dsi_prevSup1) ? dsi_potS1 : dsi_prevSup1
dsi_prevSup2 := na(dsi_prevSup2) ? dsi_potS2 : dsi_prevSup2
dsi_sup1 := dsi_potS1
dsi_sup2 := dsi_potS2
dsi_potS1 := na
dsi_potS2 := na

var int dsi_supCount = 0
var int dsi_resCount = 0
if close >= dsi_res1 and barstate.isconfirmed
dsi_lookForNewResistance := true
dsi_lookForNewSupport := true
dsi_resCount += 1
if close <= dsi_sup1 and barstate.isconfirmed
dsi_lookForNewSupport := true
dsi_lookForNewResistance := true
dsi_supCount += 1

if (close > dsi_res1 and na(dsi_prevRes1) and barstate.isconfirmed) or na(dsi_prevRes1) or dsi_resCount >= newStructureReset
dsi_prevRes1 := dsi_res1
dsi_prevRes2 := dsi_res2
dsi_resCount := 0
if (close < dsi_sup1 and na(dsi_prevSup1) and barstate.isconfirmed) or na(dsi_prevSup1) or dsi_supCount >= newStructureReset
dsi_prevSup1 := dsi_sup1
dsi_prevSup2 := dsi_sup2
dsi_supCount := 0

if close < dsi_prevRes2 and barstate.isconfirmed
dsi_prevRes1 := na
dsi_prevRes2 := na
if close > dsi_prevSup2 and barstate.isconfirmed
dsi_prevSup1 := na
dsi_prevSup2 := na

dsi_r1plot = plot(showDSI and (dsi_res1 == dsi_res1[1]) ? dsi_res1 : na, color=close >= dsi_res1 ? dsiBullColor : dsiBearColor, style=plot.style_linebr, title="di R1")
dsi_r2plot = plot(showDSI and (dsi_res1 == dsi_res1[1]) ? dsi_res2 : na, color=close >= dsi_res1 ? dsiBullColor : dsiBearColor, style=plot.style_linebr, title="di R2")
fill(dsi_r1plot, dsi_r2plot, color=showDSI ? (close > dsi_res1 ? dsiBullColor : color.new(dsiBearColor, 50)) : color.new(color.black, 100), title="di Resistance Zone")
dsi_s1plot = plot(showDSI and (dsi_sup1 == dsi_sup1[1]) ? dsi_sup1 : na, color=close < dsi_sup1 ? dsiBearColor : dsiBullColor, style=plot.style_linebr, title="di S1")
dsi_s2plot = plot(showDSI and (dsi_sup1 == dsi_sup1[1]) ? dsi_sup2 : na, color=close < dsi_sup1 ? dsiBearColor : dsiBullColor, style=plot.style_linebr, title="di S2")
fill(dsi_s1plot, dsi_s2plot, color=showDSI ? (close < dsi_sup1 ? dsiBearColor : color.new(dsiBullColor, 50)) : color.new(color.black, 100), title="di Support Zone")
dsi_ps1plot = plot(showDSI and drawPreviousStructure and (dsi_prevSup1 == dsi_prevSup1[1]) and (dsi_prevSup1 != dsi_sup1) ? dsi_prevSup1 : na, color=dsiBearColor, style=plot.style_linebr, title="di PS1")
dsi_ps2plot = plot(showDSI and drawPreviousStructure and (dsi_prevSup1 == dsi_prevSup1[1]) and (dsi_prevSup1 != dsi_sup1) ? dsi_prevSup2 : na, color=dsiBearColor, style=plot.style_linebr, title="di PS2")
fill(dsi_ps1plot, dsi_ps2plot, color=showDSI and drawPreviousStructure ? color.new(dsiBearColor, 10) : color.new(color.black, 100), title="di Previous Support Zone")
dsi_pr1plot = plot(showDSI and drawPreviousStructure and (dsi_prevRes1 == dsi_prevRes1[1]) and (dsi_prevRes1 != dsi_res1) ? dsi_prevRes1 : na, color=dsiBullColor, style=plot.style_linebr, title="di PR1")
dsi_pr2plot = plot(showDSI and drawPreviousStructure and (dsi_prevRes1 == dsi_prevRes1[1]) and (dsi_prevRes1 != dsi_res1) ? dsi_prevRes2 : na, color=dsiBullColor, style=plot.style_linebr, title="di Previous Resistance Zone")
//────────────────────────── Elliptic Bands (masked, locked) ──────────────────────────
groupEllipse = "es bands"
EB_show = input.bool(true, "show es bands", group=groupEllipse)
EB_midColor = input.color(color.rgb(229,236,241), "mid color", group=groupEllipse)
EB_upColor = input.color(color.green, "upper color", group=groupEllipse)
EB_dnColor = input.color(color.red, "lower color", group=groupEllipse)
EB_fillTransp = input.int(80, "band transparency (0–100)", minval=0, maxval=100, group=groupEllipse)
EB_showFill = input.bool(false, "fill es cloud", group=groupEllipse)
EB_showSignals = input.bool(true, "show es signals", group=groupEllipse)
EB_buyColor = input.color(color.green, "buy signal color", group=groupEllipse)
EB_sellColor = input.color(color.red, "sell signal color", group=groupEllipse)

// locked params
const int EB_MA_LEN = 50
const int EB_PERIOD = 50
const float EB_MULTI = 2.0

float EB_central_ma = ta.sma(close, EB_MA_LEN)
float EB_b = ta.stdev(close, EB_MA_LEN) * EB_MULTI
int EB_cycle_pos = bar_index % EB_PERIOD
float EB_x = 2.0 * (EB_cycle_pos / EB_PERIOD) - 1.0
float EB_offset = EB_b * math.sqrt(math.max(0.0, 1.0 - EB_x * EB_x))
float EB_band_upper = EB_central_ma + EB_offset
float EB_band_lower = EB_central_ma - EB_offset

// plot lines (upper/lower/mid)
EB_p_mid = plot(EB_show ? EB_central_ma : na, title="es mid", color=EB_midColor, linewidth=1)
EB_p_up = plot(EB_show ? EB_band_upper : na, title="es upper", color=EB_upColor)
EB_p_dn = plot(EB_show ? EB_band_lower : na, title="es lower", color=EB_dnColor)

// fill only if EB_showFill = true
EB_fillColor = (EB_show and EB_showFill) ? color.new(color.gray, EB_fillTransp) : color.new(color.gray, 100)
fill(EB_p_up, EB_p_dn, color=EB_fillColor, title="es cloud")

// signals
bool EB_buy = EB_show and close[1] < nz(EB_band_lower[1]) and close >= nz(EB_band_lower) and close <= nz(EB_band_upper) and barstate.isconfirmed
bool EB_sell = EB_show and close[1] > nz(EB_band_upper[1]) and close >= nz(EB_band_lower) and close <= nz(EB_band_upper) and barstate.isconfirmed
plotshape(EB_showSignals and EB_buy, title="es buy", location=location.belowbar, color=EB_buyColor, style=shape.triangleup, size=size.tiny)
plotshape(EB_showSignals and EB_sell, title="es sell", location=location.abovebar, color=EB_sellColor, style=shape.triangledown, size=size.tiny)

// Wave Labels (1–5) — minimal module for tp11ofc1 (Pine v6) — labels only
//──────────────────────────────────────────────────────────────────────────────
groupEW = "Wave labels (Elliott)"

srcHiSel = input.string("high", "High source", options=["high","close","max open/close"], group=groupEW)
srcLoSel = input.string("low", "Low source", options=["low","close","min open/close"], group=groupEW)
ew_hi = srcHiSel == "high" ? high : srcHiSel == "close" ? close : math.max(open, close)
ew_lo = srcLoSel == "low" ? low : srcLoSel == "close" ? close : math.min(open, close)

ewShowS1 = input.bool(true, "Show wave S", group=groupEW, inline="s1")
ewLen1 = input.int(4, "len", minval=1, group=groupEW, inline="s1")
ewCol1 = input.color(color.new(color.red,0), "", group=groupEW, inline="s1")

ewShowS2 = input.bool(true, "Show wave M", group=groupEW, inline="s2")
ewLen2 = input.int(8, "len", minval=1, group=groupEW, inline="s2")
ewCol2 = input.color(color.new(#0d86e9, 0), "", group=groupEW, inline="s2")

ewShowS3 = input.bool(true, "Show wave L", group=groupEW, inline="s3")
ewLen3 = input.int(16, "len", minval=1, group=groupEW, inline="s3")
ewCol3 = input.color(color.new(#470303, 0),"", group=groupEW, inline="s3")

ewSizeStr = input.string("small","Label size", options=["tiny","small","normal","large"], group=groupEW)
ew_lsize(s) => s=="tiny"?size.tiny:s=="normal"?size.normal:s=="large"?size.large:size.small

type _ZZ
int[] d
int[] x
float[] y

newZZ() => _ZZ.new(array.new_int(), array.new_int(), array.new_float())

f_push_pivot(_aZZ, _dir, _x1, _y1, _x2, _y2) =>
_aZZ.d.unshift(_dir)
_aZZ.x.unshift(_x2)
_aZZ.y.unshift(_y2)
if array.size(_aZZ.d) > 12
_ = array.pop(_aZZ.d)
_ = array.pop(_aZZ.x)
_ = array.pop(_aZZ.y)

var label[] EW_LABELS = array.new_label()
f_add_label(_x, _y, _txt, _col, _up) =>
label lb = label.new(_x, _y, text=_txt, style=_up?label.style_label_down:label.style_label_up, textcolor=_col, color=color.new(color.black, 100), size=ew_lsize(ewSizeStr), xloc=xloc.bar_index)
array.push(EW_LABELS, lb)
if array.size(EW_LABELS) > 500
label.delete(array.get(EW_LABELS, 0))
array.remove(EW_LABELS, 0)

f_check_motive_bull(_1y,_2y,_3y,_4y,_5y,_6y) =>
_W5 = _6y - _5y
_W3 = _4y - _3y
_W1 = _2y - _1y
_min = math.min(_W1,_W3,_W5)
(_W3 != _min) and (_6y > _4y) and (_3y > _1y) and (_5y > _2y)

f_check_motive_bear(_1y,_2y,_3y,_4y,_5y,_6y) =>
_W5 = _5y - _6y
_W3 = _3y - _4y
_W1 = _1y - _2y
_min = math.min(_W1,_W3,_W5)
(_W3 != _min) and (_4y > _6y) and (_1y > _3y) and (_2y > _5y)

f_wave_labels(_enabled, _len, _col, _rowSep) =>
if _enabled
var _ZZ zz = newZZ()
if barstate.isfirst
for _=0 to 10
array.unshift(zz.d, 0)
array.unshift(zz.x, 0)
array.unshift(zz.y, 0)

x2 = bar_index - 1
ph = ta.pivothigh(ew_hi, _len, 1)
pl = ta.pivotlow (ew_lo, _len, 1)

if not na(ph)
dir = array.get(zz.d, 0)
x1 = array.get(zz.x, 0)
y1 = array.get(zz.y, 0)
y2h = nz(ew_hi[1])
if dir < 1
f_push_pivot(zz, 1, x1, y1, x2, y2h)
else if ph > y1
array.set(zz.x, 0, x2)
array.set(zz.y, 0, y2h)

_6x = x2, _6y = y2h
_5x = array.get(zz.x,1), _5y = array.get(zz.y,1)
_4x = array.get(zz.x

면책사항

이 정보와 게시물은 TradingView에서 제공하거나 보증하는 금융, 투자, 거래 또는 기타 유형의 조언이나 권고 사항을 의미하거나 구성하지 않습니다. 자세한 내용은 이용 약관을 참고하세요.