OPEN-SOURCE SCRIPT
Defyler 15m ORB

// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at mozilla.org/MPL/2.0/
// © jeffparker341
//version=6
indicator("Defyler ORB",
overlay=true, max_labels_count=500, max_boxes_count=500)
// =====================
// Inputs
// =====================
sess = input.session("0930-1600", "RTH Session")
showAfterHours = input.bool(false, "Extend Past RTH Close")
// Range visuals
bandColor = input.color(color.new(color.teal, 85), "Range Fill")
hiLineColor = input.color(color.new(color.white, 0), "High Line")
loLineColor = input.color(color.new(color.white, 0), "Low Line")
lineWidth = input.int(2, "Range Line Width", minval=1, maxval=4)
// Chart-TF VWAP
showHourlyVWAP = input.bool(true, "Show VWAP (Chart TF)")
hVwapColor = input.color(color.new(color.yellow, 0), "VWAP Color")
hVwapWidth = input.int(2, "VWAP Width", minval=1, maxval=4)
// Debug / markers
showBreakMarks = input.bool(true, "Show Break Markers (BRK)")
showReclaimMk = input.bool(true, "Show Reclaim Markers (T/R)")
showEntryLabel = input.bool(true, "Show Entry Labels")
showExitLabel = input.bool(true, "Show Exit Labels")
breakUpColor = input.color(color.new(color.lime, 0), "BRK Up Color")
breakDnColor = input.color(color.new(color.red, 0), "BRK Down Color")
reclUpColor = input.color(color.new(color.aqua, 0), "Reclaim Long Color")
reclDnColor = input.color(color.new(color.fuchsia, 0), "Reclaim Short Color")
// Trade enable
enableLong = input.bool(true, "Enable Long Trades")
enableShort = input.bool(true, "Enable Short Trades")
// Break→Reclaim tuning
reclaimTolPct = input.float(10.0, "Reclaim proximity (% of 30m range)", minval=0.0, step=0.5)
// Filters
useVWAPFilter = input.bool(true, "Require VWAP Alignment (Long>VWAP, Short<VWAP)")
requireCandleDir = input.bool(true, "Require Reclaim Candle Direction (Long green / Short red)")
// =====================
// NEW: Two-Stage Entry (Reclaim = setup, entry on follow-through)
// =====================
useTwoStageEntry = input.bool(true, "Two-Stage Entry (Reclaim -> Confirm)")
confirmBufferTicks = input.int(0, "Confirm Buffer (ticks)", minval=0, maxval=100)
// =====================
// 30m Trend Projection (recommended ON)
// =====================
useTrendProjection30m = input.bool(true, "Use 30m Trend Projection for TP/SL")
projLen30m = input.int(30, "30m Trend Length", minval=5, maxval=200)
projBars30m = input.int(2, "Project N 30m Bars Ahead", minval=1, maxval=12)
minProjATR = input.float(0.75, "Min Projection (x 30m ATR)", minval=0.0, step=0.05)
// Risk model (applies to base move, projected or fallback)
slPct = input.float(50.0, "SL = % of Base", minval=0.1, step=0.1)
tpPct = input.float(100.0,"TP = % of Base", minval=0.1, step=0.1)
// Make boxes larger overall (SL/TP distances)
boxSizeMult = input.float(1.65, "Order Box Size Multiplier", minval=0.5, maxval=3.0, step=0.05)
// Fallback base mode (only used when projection is OFF)
fallbackBase = input.string("VWAPDistance", "Fallback Base (when projection OFF)",
options=["30mRange","BreakerRange","ATR","VWAPDistance"])
atrLen = input.int(14, "ATR Length (fallback)", minval=1)
atrTf = input.string("5", "ATR Timeframe (fallback)", options=["1","3","5","15","30","60"])
minBaseMode = input.string("ATR", "Min Base Floor Type (fallback)", options=["None","ATR","30mRangePct"])
minBasePct30m = input.float(10.0, "Min Base = % of 30m Range", minval=0.0, step=1.0)
// Trade box visuals
riskBoxColor = input.color(color.new(color.red, 85), "Risk Box Fill")
rewardBoxColor = input.color(color.new(color.lime, 88), "Reward Box Fill")
boxBorderColor = input.color(color.new(color.white, 80), "Box Border")
// =====================
// Session flags
// =====================
inSess = not na(time(timeframe.period, sess))
newDay = ta.change(time("D")) != 0
// =====================
// VWAP (Chart timeframe; auto-adapts to selected TF)
// =====================
chartVWAP = ta.vwap(hlc3)
showVW = showHourlyVWAP and (inSess or showAfterHours)
plot(showVW ? chartVWAP : na, "VWAP", color=hVwapColor, linewidth=hVwapWidth, style=plot.style_line)
// =====================
// First 30m RTH candle high/low (computed on 30m series)
// =====================
rth30_firstBar = request.security(
syminfo.tickerid,
"30",
(not na(time("30", sess))) and (na(time("30", sess))[1]),
barmerge.gaps_off,
barmerge.lookahead_off
)
rth30_high = request.security(syminfo.tickerid, "30", high, barmerge.gaps_off, barmerge.lookahead_off)
rth30_low = request.security(syminfo.tickerid, "30", low, barmerge.gaps_off, barmerge.lookahead_off)
// Range state
var float firstHi = na
var float firstLo = na
var bool locked = false
if newDay
firstHi := na
firstLo := na
locked := false
if rth30_firstBar and not locked
firstHi := rth30_high
firstLo := rth30_low
locked := true
showRange = locked and (inSess or showAfterHours)
// Range plots
rangeHi = showRange ? firstHi : na
rangeLo = showRange ? firstLo : na
pHi = plot(rangeHi, "First 30m High", color=hiLineColor, linewidth=lineWidth, style=plot.style_linebr)
pLo = plot(rangeLo, "First 30m Low", color=loLineColor, linewidth=lineWidth, style=plot.style_linebr)
fill(pHi, pLo, color=bandColor, title="First 30m Range Fill")
// =====================
// 30m Trend Projection (points)
// =====================
atr30 = request.security(syminfo.tickerid, "30", ta.atr(14), barmerge.gaps_off, barmerge.lookahead_off)
lr30 = request.security(syminfo.tickerid, "30", ta.linreg(close, projLen30m, 0), barmerge.gaps_off, barmerge.lookahead_off)
lr30_prev = request.security(syminfo.tickerid, "30", ta.linreg(close, projLen30m, 0)[1], barmerge.gaps_off, barmerge.lookahead_off)
slope30 = lr30 - lr30_prev
projMoveRaw = math.abs(slope30) * projBars30m
projFloor = atr30 * minProjATR
projMove = math.max(projMoveRaw, projFloor)
// =====================
// Break → Reclaim state machine
// =====================
var bool armedLong = true
var bool armedShort = true
var bool longBroken = false
var bool longTouched = false
var bool shortBroken = false
var bool shortTouched = false
range30 = locked ? (firstHi - firstLo) : na
tol = (not na(range30) ? range30 * (reclaimTolPct / 100.0) : na)
// Daily reset
if newDay
armedLong := true
armedShort := true
longBroken := false
longTouched := false
shortBroken := false
shortTouched := false
// Re-arm ONLY when price closes back inside the 30m range
insideRange = locked and barstate.isconfirmed and close <= firstHi and close >= firstLo
if insideRange
armedLong := true
armedShort := true
longBroken := false
longTouched := false
shortBroken := false
shortTouched := false
// VWAP alignment (chart TF VWAP)
allowLong = not useVWAPFilter or close > chartVWAP
allowShort = not useVWAPFilter or close < chartVWAP
// Break (confirmed close)
brkUp = showRange and barstate.isconfirmed and armedLong and close > firstHi and allowLong
brkDn = showRange and barstate.isconfirmed and armedShort and close < firstLo and allowShort
if brkUp
longBroken := true
longTouched := false
if brkDn
shortBroken := true
shortTouched := false
// Touch zone after break
longTouch = showRange and longBroken and armedLong and not longTouched and not na(tol) and low <= (firstHi + tol)
if longTouch
longTouched := true
shortTouch = showRange and shortBroken and armedShort and not shortTouched and not na(tol) and high >= (firstLo - tol)
if shortTouch
shortTouched := true
// Reclaim/confirm (confirmed close back through boundary)
longReclaim = showRange and barstate.isconfirmed and armedLong and longBroken and longTouched and close > firstHi and allowLong
shortReclaim = showRange and barstate.isconfirmed and armedShort and shortBroken and shortTouched and close < firstLo and allowShort
if requireCandleDir
longReclaim := longReclaim and close > open
shortReclaim := shortReclaim and close < open
// Markers
plotshape(showBreakMarks and brkUp, title="BRK Up", style=shape.triangleup, location=location.belowbar, size=size.tiny, color=breakUpColor, text="BRK↑")
plotshape(showBreakMarks and brkDn, title="BRK Down", style=shape.triangledown, location=location.abovebar, size=size.tiny, color=breakDnColor, text="BRK↓")
plotshape(showReclaimMk and longTouch, title="Touch Long", style=shape.circle, location=location.belowbar, size=size.tiny, color=reclUpColor, text="T")
plotshape(showReclaimMk and shortTouch, title="Touch Short", style=shape.circle, location=location.abovebar, size=size.tiny, color=reclDnColor, text="T")
plotshape(showReclaimMk and longReclaim, title="Reclaim Long", style=shape.diamond, location=location.belowbar, size=size.tiny, color=reclUpColor, text="R")
plotshape(showReclaimMk and shortReclaim, title="Reclaim Short", style=shape.diamond, location=location.abovebar, size=size.tiny, color=reclDnColor, text="R")
// =====================
// Two-Stage Entry setup state
// =====================
var bool hasSetup = false
var int setupDir = 0
var float setupHi = na
var float setupLo = na
// Reset setup daily
if newDay
hasSetup := false
setupDir := 0
setupHi := na
setupLo := na
// If price goes back inside the ORB range, invalidate any pending setup
if hasSetup and insideRange
hasSetup := false
setupDir := 0
setupHi := na
setupLo := na
// Capture setup on reclaim (instead of entering immediately when Two-Stage is ON)
if useTwoStageEntry and not hasSetup and not na(firstHi) and not na(firstLo)
if enableLong and not hasSetup and longReclaim
hasSetup := true
setupDir := 1
setupHi := high
setupLo := low
if enableShort and not hasSetup and shortReclaim
hasSetup := true
setupDir := -1
setupHi := high
setupLo := low
// Confirm conditions (follow-through beyond reclaim candle extreme + optional buffer)
buf = confirmBufferTicks * syminfo.mintick
confirmLong = useTwoStageEntry and hasSetup and setupDir == 1 and barstate.isconfirmed and close > (setupHi + buf) and allowLong
confirmShort = useTwoStageEntry and hasSetup and setupDir == -1 and barstate.isconfirmed and close < (setupLo - buf) and allowShort
// =====================
// Fallback sizing helpers (only used if projection OFF)
// =====================
breakerRange = high - low
atrBase = request.security(syminfo.tickerid, atrTf, ta.atr(atrLen), barmerge.gaps_off, barmerge.lookahead_off)
f_base_fallback(entry) =>
float b = na
if fallbackBase == "30mRange"
b := range30
else if fallbackBase == "BreakerRange"
b := breakerRange
else if fallbackBase == "ATR"
b := atrBase
else
b := math.abs(entry - chartVWAP)
b
f_floor_fallback() =>
float f = 0.0
if minBaseMode == "None"
f := 0.0
else if minBaseMode == "ATR"
f := atrBase
else
f := (not na(range30) ? range30 * (minBasePct30m / 100.0) : 0.0)
f
f_baseEff(entry) =>
float b = useTrendProjection30m ? projMove : math.max(f_base_fallback(entry), f_floor_fallback())
b
// =====================
// Box helper (bar_index anchored; scales/pans/zooms correctly)
// =====================
f_make_box(_box, _leftBar, _rightBar, _top, _bot, _bg) =>
box _b = _box
if na(_b)
_b := box.new(left=_leftBar, right=_rightBar, top=_top, bottom=_bot, xloc=xloc.bar_index,
bgcolor=_bg, border_color=boxBorderColor)
else
box.set_left(_b, _leftBar)
box.set_right(_b, _rightBar)
box.set_top(_b, _top)
box.set_bottom(_b, _bot)
_b
// =====================
// Trade state + boxes
// =====================
var int dir = 0
var bool active = false
var float entryPx = na
var float slPx = na
var float tpPx = na
var int entryBarIndex = na
var box riskBox = na
var box rewardBox = na
if newDay
dir := 0
active := false
entryPx := na
slPx := na
tpPx := na
entryBarIndex := na
riskBox := na
rewardBox := na
// Signals:
// - If Two-Stage is ON: entry only on confirmLong/confirmShort
// - If Two-Stage is OFF: old behavior (enter on reclaim)
longSignal = enableLong and not active and (useTwoStageEntry ? confirmLong : longReclaim)
shortSignal = enableShort and not active and (useTwoStageEntry ? confirmShort : shortReclaim)
// Once confirmation happens (or if we entered), clear pending setup
if (confirmLong or confirmShort) and useTwoStageEntry
hasSetup := false
setupDir := 0
setupHi := na
setupLo := na
if longSignal
dir := 1
active := true
entryPx := close
entryBarIndex := bar_index
baseEff = f_baseEff(entryPx) * boxSizeMult
slPx := entryPx - baseEff * (slPct / 100.0)
tpPx := entryPx + baseEff * (tpPct / 100.0)
armedLong := false
longBroken := false
longTouched := false
riskBox := na
rewardBox := na
riskBox := f_make_box(riskBox, entryBarIndex, bar_index, entryPx, slPx, riskBoxColor)
rewardBox := f_make_box(rewardBox, entryBarIndex, bar_index, tpPx, entryPx, rewardBoxColor)
if showEntryLabel
label.new(bar_index, low, "LONG\nEntry", style=label.style_label_up, textcolor=color.white)
if shortSignal
dir := -1
active := true
entryPx := close
entryBarIndex := bar_index
baseEff = f_baseEff(entryPx) * boxSizeMult
slPx := entryPx + baseEff * (slPct / 100.0)
tpPx := entryPx - baseEff * (tpPct / 100.0)
armedShort := false
shortBroken := false
shortTouched := false
riskBox := na
rewardBox := na
riskBox := f_make_box(riskBox, entryBarIndex, bar_index, slPx, entryPx, riskBoxColor)
rewardBox := f_make_box(rewardBox, entryBarIndex, bar_index, entryPx, tpPx, rewardBoxColor)
if showEntryLabel
label.new(bar_index, high, "SHORT\nEntry", style=label.style_label_down, textcolor=color.white)
// Extend boxes while active
if active and not na(entryBarIndex)
if dir == 1
riskBox := f_make_box(riskBox, entryBarIndex, bar_index, entryPx, slPx, riskBoxColor)
rewardBox := f_make_box(rewardBox, entryBarIndex, bar_index, tpPx, entryPx, rewardBoxColor)
else if dir == -1
riskBox := f_make_box(riskBox, entryBarIndex, bar_index, slPx, entryPx, riskBoxColor)
rewardBox := f_make_box(rewardBox, entryBarIndex, bar_index, entryPx, tpPx, rewardBoxColor)
// Exit detection only AFTER entry bar
canExit = active and not na(entryBarIndex) and bar_index > entryBarIndex
hitTP = canExit and ((dir == 1 and high >= tpPx) or (dir == -1 and low <= tpPx))
hitSL = canExit and ((dir == 1 and low <= slPx) or (dir == -1 and high >= slPx))
exitNow = hitTP or hitSL
exitIsSL = hitSL
if exitNow
if showExitLabel
label.new(bar_index, exitIsSL ? slPx : tpPx, exitIsSL ? "EXIT\nSL" : "EXIT\nTP",
style=label.style_label_left, textcolor=color.white)
// Freeze boxes at this bar and leave them on chart
if not na(riskBox)
box.set_right(riskBox, bar_index)
if not na(rewardBox)
box.set_right(rewardBox, bar_index)
// Clear trade state (boxes remain)
dir := 0
active := false
entryPx := na
slPx := na
tpPx := na
entryBarIndex := na
riskBox := na
rewardBox := na
// © jeffparker341
//version=6
indicator("Defyler ORB",
overlay=true, max_labels_count=500, max_boxes_count=500)
// =====================
// Inputs
// =====================
sess = input.session("0930-1600", "RTH Session")
showAfterHours = input.bool(false, "Extend Past RTH Close")
// Range visuals
bandColor = input.color(color.new(color.teal, 85), "Range Fill")
hiLineColor = input.color(color.new(color.white, 0), "High Line")
loLineColor = input.color(color.new(color.white, 0), "Low Line")
lineWidth = input.int(2, "Range Line Width", minval=1, maxval=4)
// Chart-TF VWAP
showHourlyVWAP = input.bool(true, "Show VWAP (Chart TF)")
hVwapColor = input.color(color.new(color.yellow, 0), "VWAP Color")
hVwapWidth = input.int(2, "VWAP Width", minval=1, maxval=4)
// Debug / markers
showBreakMarks = input.bool(true, "Show Break Markers (BRK)")
showReclaimMk = input.bool(true, "Show Reclaim Markers (T/R)")
showEntryLabel = input.bool(true, "Show Entry Labels")
showExitLabel = input.bool(true, "Show Exit Labels")
breakUpColor = input.color(color.new(color.lime, 0), "BRK Up Color")
breakDnColor = input.color(color.new(color.red, 0), "BRK Down Color")
reclUpColor = input.color(color.new(color.aqua, 0), "Reclaim Long Color")
reclDnColor = input.color(color.new(color.fuchsia, 0), "Reclaim Short Color")
// Trade enable
enableLong = input.bool(true, "Enable Long Trades")
enableShort = input.bool(true, "Enable Short Trades")
// Break→Reclaim tuning
reclaimTolPct = input.float(10.0, "Reclaim proximity (% of 30m range)", minval=0.0, step=0.5)
// Filters
useVWAPFilter = input.bool(true, "Require VWAP Alignment (Long>VWAP, Short<VWAP)")
requireCandleDir = input.bool(true, "Require Reclaim Candle Direction (Long green / Short red)")
// =====================
// NEW: Two-Stage Entry (Reclaim = setup, entry on follow-through)
// =====================
useTwoStageEntry = input.bool(true, "Two-Stage Entry (Reclaim -> Confirm)")
confirmBufferTicks = input.int(0, "Confirm Buffer (ticks)", minval=0, maxval=100)
// =====================
// 30m Trend Projection (recommended ON)
// =====================
useTrendProjection30m = input.bool(true, "Use 30m Trend Projection for TP/SL")
projLen30m = input.int(30, "30m Trend Length", minval=5, maxval=200)
projBars30m = input.int(2, "Project N 30m Bars Ahead", minval=1, maxval=12)
minProjATR = input.float(0.75, "Min Projection (x 30m ATR)", minval=0.0, step=0.05)
// Risk model (applies to base move, projected or fallback)
slPct = input.float(50.0, "SL = % of Base", minval=0.1, step=0.1)
tpPct = input.float(100.0,"TP = % of Base", minval=0.1, step=0.1)
// Make boxes larger overall (SL/TP distances)
boxSizeMult = input.float(1.65, "Order Box Size Multiplier", minval=0.5, maxval=3.0, step=0.05)
// Fallback base mode (only used when projection is OFF)
fallbackBase = input.string("VWAPDistance", "Fallback Base (when projection OFF)",
options=["30mRange","BreakerRange","ATR","VWAPDistance"])
atrLen = input.int(14, "ATR Length (fallback)", minval=1)
atrTf = input.string("5", "ATR Timeframe (fallback)", options=["1","3","5","15","30","60"])
minBaseMode = input.string("ATR", "Min Base Floor Type (fallback)", options=["None","ATR","30mRangePct"])
minBasePct30m = input.float(10.0, "Min Base = % of 30m Range", minval=0.0, step=1.0)
// Trade box visuals
riskBoxColor = input.color(color.new(color.red, 85), "Risk Box Fill")
rewardBoxColor = input.color(color.new(color.lime, 88), "Reward Box Fill")
boxBorderColor = input.color(color.new(color.white, 80), "Box Border")
// =====================
// Session flags
// =====================
inSess = not na(time(timeframe.period, sess))
newDay = ta.change(time("D")) != 0
// =====================
// VWAP (Chart timeframe; auto-adapts to selected TF)
// =====================
chartVWAP = ta.vwap(hlc3)
showVW = showHourlyVWAP and (inSess or showAfterHours)
plot(showVW ? chartVWAP : na, "VWAP", color=hVwapColor, linewidth=hVwapWidth, style=plot.style_line)
// =====================
// First 30m RTH candle high/low (computed on 30m series)
// =====================
rth30_firstBar = request.security(
syminfo.tickerid,
"30",
(not na(time("30", sess))) and (na(time("30", sess))[1]),
barmerge.gaps_off,
barmerge.lookahead_off
)
rth30_high = request.security(syminfo.tickerid, "30", high, barmerge.gaps_off, barmerge.lookahead_off)
rth30_low = request.security(syminfo.tickerid, "30", low, barmerge.gaps_off, barmerge.lookahead_off)
// Range state
var float firstHi = na
var float firstLo = na
var bool locked = false
if newDay
firstHi := na
firstLo := na
locked := false
if rth30_firstBar and not locked
firstHi := rth30_high
firstLo := rth30_low
locked := true
showRange = locked and (inSess or showAfterHours)
// Range plots
rangeHi = showRange ? firstHi : na
rangeLo = showRange ? firstLo : na
pHi = plot(rangeHi, "First 30m High", color=hiLineColor, linewidth=lineWidth, style=plot.style_linebr)
pLo = plot(rangeLo, "First 30m Low", color=loLineColor, linewidth=lineWidth, style=plot.style_linebr)
fill(pHi, pLo, color=bandColor, title="First 30m Range Fill")
// =====================
// 30m Trend Projection (points)
// =====================
atr30 = request.security(syminfo.tickerid, "30", ta.atr(14), barmerge.gaps_off, barmerge.lookahead_off)
lr30 = request.security(syminfo.tickerid, "30", ta.linreg(close, projLen30m, 0), barmerge.gaps_off, barmerge.lookahead_off)
lr30_prev = request.security(syminfo.tickerid, "30", ta.linreg(close, projLen30m, 0)[1], barmerge.gaps_off, barmerge.lookahead_off)
slope30 = lr30 - lr30_prev
projMoveRaw = math.abs(slope30) * projBars30m
projFloor = atr30 * minProjATR
projMove = math.max(projMoveRaw, projFloor)
// =====================
// Break → Reclaim state machine
// =====================
var bool armedLong = true
var bool armedShort = true
var bool longBroken = false
var bool longTouched = false
var bool shortBroken = false
var bool shortTouched = false
range30 = locked ? (firstHi - firstLo) : na
tol = (not na(range30) ? range30 * (reclaimTolPct / 100.0) : na)
// Daily reset
if newDay
armedLong := true
armedShort := true
longBroken := false
longTouched := false
shortBroken := false
shortTouched := false
// Re-arm ONLY when price closes back inside the 30m range
insideRange = locked and barstate.isconfirmed and close <= firstHi and close >= firstLo
if insideRange
armedLong := true
armedShort := true
longBroken := false
longTouched := false
shortBroken := false
shortTouched := false
// VWAP alignment (chart TF VWAP)
allowLong = not useVWAPFilter or close > chartVWAP
allowShort = not useVWAPFilter or close < chartVWAP
// Break (confirmed close)
brkUp = showRange and barstate.isconfirmed and armedLong and close > firstHi and allowLong
brkDn = showRange and barstate.isconfirmed and armedShort and close < firstLo and allowShort
if brkUp
longBroken := true
longTouched := false
if brkDn
shortBroken := true
shortTouched := false
// Touch zone after break
longTouch = showRange and longBroken and armedLong and not longTouched and not na(tol) and low <= (firstHi + tol)
if longTouch
longTouched := true
shortTouch = showRange and shortBroken and armedShort and not shortTouched and not na(tol) and high >= (firstLo - tol)
if shortTouch
shortTouched := true
// Reclaim/confirm (confirmed close back through boundary)
longReclaim = showRange and barstate.isconfirmed and armedLong and longBroken and longTouched and close > firstHi and allowLong
shortReclaim = showRange and barstate.isconfirmed and armedShort and shortBroken and shortTouched and close < firstLo and allowShort
if requireCandleDir
longReclaim := longReclaim and close > open
shortReclaim := shortReclaim and close < open
// Markers
plotshape(showBreakMarks and brkUp, title="BRK Up", style=shape.triangleup, location=location.belowbar, size=size.tiny, color=breakUpColor, text="BRK↑")
plotshape(showBreakMarks and brkDn, title="BRK Down", style=shape.triangledown, location=location.abovebar, size=size.tiny, color=breakDnColor, text="BRK↓")
plotshape(showReclaimMk and longTouch, title="Touch Long", style=shape.circle, location=location.belowbar, size=size.tiny, color=reclUpColor, text="T")
plotshape(showReclaimMk and shortTouch, title="Touch Short", style=shape.circle, location=location.abovebar, size=size.tiny, color=reclDnColor, text="T")
plotshape(showReclaimMk and longReclaim, title="Reclaim Long", style=shape.diamond, location=location.belowbar, size=size.tiny, color=reclUpColor, text="R")
plotshape(showReclaimMk and shortReclaim, title="Reclaim Short", style=shape.diamond, location=location.abovebar, size=size.tiny, color=reclDnColor, text="R")
// =====================
// Two-Stage Entry setup state
// =====================
var bool hasSetup = false
var int setupDir = 0
var float setupHi = na
var float setupLo = na
// Reset setup daily
if newDay
hasSetup := false
setupDir := 0
setupHi := na
setupLo := na
// If price goes back inside the ORB range, invalidate any pending setup
if hasSetup and insideRange
hasSetup := false
setupDir := 0
setupHi := na
setupLo := na
// Capture setup on reclaim (instead of entering immediately when Two-Stage is ON)
if useTwoStageEntry and not hasSetup and not na(firstHi) and not na(firstLo)
if enableLong and not hasSetup and longReclaim
hasSetup := true
setupDir := 1
setupHi := high
setupLo := low
if enableShort and not hasSetup and shortReclaim
hasSetup := true
setupDir := -1
setupHi := high
setupLo := low
// Confirm conditions (follow-through beyond reclaim candle extreme + optional buffer)
buf = confirmBufferTicks * syminfo.mintick
confirmLong = useTwoStageEntry and hasSetup and setupDir == 1 and barstate.isconfirmed and close > (setupHi + buf) and allowLong
confirmShort = useTwoStageEntry and hasSetup and setupDir == -1 and barstate.isconfirmed and close < (setupLo - buf) and allowShort
// =====================
// Fallback sizing helpers (only used if projection OFF)
// =====================
breakerRange = high - low
atrBase = request.security(syminfo.tickerid, atrTf, ta.atr(atrLen), barmerge.gaps_off, barmerge.lookahead_off)
f_base_fallback(entry) =>
float b = na
if fallbackBase == "30mRange"
b := range30
else if fallbackBase == "BreakerRange"
b := breakerRange
else if fallbackBase == "ATR"
b := atrBase
else
b := math.abs(entry - chartVWAP)
b
f_floor_fallback() =>
float f = 0.0
if minBaseMode == "None"
f := 0.0
else if minBaseMode == "ATR"
f := atrBase
else
f := (not na(range30) ? range30 * (minBasePct30m / 100.0) : 0.0)
f
f_baseEff(entry) =>
float b = useTrendProjection30m ? projMove : math.max(f_base_fallback(entry), f_floor_fallback())
b
// =====================
// Box helper (bar_index anchored; scales/pans/zooms correctly)
// =====================
f_make_box(_box, _leftBar, _rightBar, _top, _bot, _bg) =>
box _b = _box
if na(_b)
_b := box.new(left=_leftBar, right=_rightBar, top=_top, bottom=_bot, xloc=xloc.bar_index,
bgcolor=_bg, border_color=boxBorderColor)
else
box.set_left(_b, _leftBar)
box.set_right(_b, _rightBar)
box.set_top(_b, _top)
box.set_bottom(_b, _bot)
_b
// =====================
// Trade state + boxes
// =====================
var int dir = 0
var bool active = false
var float entryPx = na
var float slPx = na
var float tpPx = na
var int entryBarIndex = na
var box riskBox = na
var box rewardBox = na
if newDay
dir := 0
active := false
entryPx := na
slPx := na
tpPx := na
entryBarIndex := na
riskBox := na
rewardBox := na
// Signals:
// - If Two-Stage is ON: entry only on confirmLong/confirmShort
// - If Two-Stage is OFF: old behavior (enter on reclaim)
longSignal = enableLong and not active and (useTwoStageEntry ? confirmLong : longReclaim)
shortSignal = enableShort and not active and (useTwoStageEntry ? confirmShort : shortReclaim)
// Once confirmation happens (or if we entered), clear pending setup
if (confirmLong or confirmShort) and useTwoStageEntry
hasSetup := false
setupDir := 0
setupHi := na
setupLo := na
if longSignal
dir := 1
active := true
entryPx := close
entryBarIndex := bar_index
baseEff = f_baseEff(entryPx) * boxSizeMult
slPx := entryPx - baseEff * (slPct / 100.0)
tpPx := entryPx + baseEff * (tpPct / 100.0)
armedLong := false
longBroken := false
longTouched := false
riskBox := na
rewardBox := na
riskBox := f_make_box(riskBox, entryBarIndex, bar_index, entryPx, slPx, riskBoxColor)
rewardBox := f_make_box(rewardBox, entryBarIndex, bar_index, tpPx, entryPx, rewardBoxColor)
if showEntryLabel
label.new(bar_index, low, "LONG\nEntry", style=label.style_label_up, textcolor=color.white)
if shortSignal
dir := -1
active := true
entryPx := close
entryBarIndex := bar_index
baseEff = f_baseEff(entryPx) * boxSizeMult
slPx := entryPx + baseEff * (slPct / 100.0)
tpPx := entryPx - baseEff * (tpPct / 100.0)
armedShort := false
shortBroken := false
shortTouched := false
riskBox := na
rewardBox := na
riskBox := f_make_box(riskBox, entryBarIndex, bar_index, slPx, entryPx, riskBoxColor)
rewardBox := f_make_box(rewardBox, entryBarIndex, bar_index, entryPx, tpPx, rewardBoxColor)
if showEntryLabel
label.new(bar_index, high, "SHORT\nEntry", style=label.style_label_down, textcolor=color.white)
// Extend boxes while active
if active and not na(entryBarIndex)
if dir == 1
riskBox := f_make_box(riskBox, entryBarIndex, bar_index, entryPx, slPx, riskBoxColor)
rewardBox := f_make_box(rewardBox, entryBarIndex, bar_index, tpPx, entryPx, rewardBoxColor)
else if dir == -1
riskBox := f_make_box(riskBox, entryBarIndex, bar_index, slPx, entryPx, riskBoxColor)
rewardBox := f_make_box(rewardBox, entryBarIndex, bar_index, entryPx, tpPx, rewardBoxColor)
// Exit detection only AFTER entry bar
canExit = active and not na(entryBarIndex) and bar_index > entryBarIndex
hitTP = canExit and ((dir == 1 and high >= tpPx) or (dir == -1 and low <= tpPx))
hitSL = canExit and ((dir == 1 and low <= slPx) or (dir == -1 and high >= slPx))
exitNow = hitTP or hitSL
exitIsSL = hitSL
if exitNow
if showExitLabel
label.new(bar_index, exitIsSL ? slPx : tpPx, exitIsSL ? "EXIT\nSL" : "EXIT\nTP",
style=label.style_label_left, textcolor=color.white)
// Freeze boxes at this bar and leave them on chart
if not na(riskBox)
box.set_right(riskBox, bar_index)
if not na(rewardBox)
box.set_right(rewardBox, bar_index)
// Clear trade state (boxes remain)
dir := 0
active := false
entryPx := na
slPx := na
tpPx := na
entryBarIndex := na
riskBox := na
rewardBox := na
Skrip sumber terbuka
Dalam semangat TradingView sebenar, pencipta skrip ini telah menjadikannya sumber terbuka, jadi pedagang boleh menilai dan mengesahkan kefungsiannya. Terima kasih kepada penulis! Walaupuan anda boleh menggunakan secara percuma, ingat bahawa penerbitan semula kod ini tertakluk kepada Peraturan Dalaman.
Penafian
Maklumat dan penerbitan adalah tidak bertujuan, dan tidak membentuk, nasihat atau cadangan kewangan, pelaburan, dagangan atau jenis lain yang diberikan atau disahkan oleh TradingView. Baca lebih dalam Terma Penggunaan.
Skrip sumber terbuka
Dalam semangat TradingView sebenar, pencipta skrip ini telah menjadikannya sumber terbuka, jadi pedagang boleh menilai dan mengesahkan kefungsiannya. Terima kasih kepada penulis! Walaupuan anda boleh menggunakan secara percuma, ingat bahawa penerbitan semula kod ini tertakluk kepada Peraturan Dalaman.
Penafian
Maklumat dan penerbitan adalah tidak bertujuan, dan tidak membentuk, nasihat atau cadangan kewangan, pelaburan, dagangan atau jenis lain yang diberikan atau disahkan oleh TradingView. Baca lebih dalam Terma Penggunaan.