OPEN-SOURCE SCRIPT
Candle Suite PRO – Engulf + Pin + Regime Filters + Trigger

//version=5
indicator("Candle Suite PRO – Engulf + Pin + Regime Filters + Trigger", overlay=true, max_labels_count=500)
//===================== Inputs =====================
grpPtn = "Patterns"
useEngulf = input.bool(true, "Enable Engulfing", group=grpPtn)
usePin = input.bool(true, "Enable Pin Bar", group=grpPtn)
pinRatio = input.float(2.0, "PinBar shadow >= body ×", group=grpPtn, step=0.1, minval=1)
minBodyP = input.float(0.15, "Min Body% of Range (0~1)", group=grpPtn, step=0.01, minval=0, maxval=1)
coolBars = input.int(3, "Cooldown bars", group=grpPtn, minval=0)
grpReg = "Regime Filters"
useHTF = input.bool(true, "Use HTF EMA50 Filter", group=grpReg)
htfTF = input.timeframe("60", "HTF timeframe", group=grpReg) // 5m/15m → 60 권장
useADX = input.bool(true, "Use ADX Trend Filter", group=grpReg)
adxLen = input.int(14, "ADX Length", group=grpReg, minval=5)
adxMin = input.int(18, "ADX Min Threshold", group=grpReg, minval=5)
useVOL = input.bool(true, "Use Volume Filter (> SMA×k)",group=grpReg)
volMult = input.float(1.10, "k for Volume", group=grpReg, step=0.05)
emaPinchPc = input.float(0.15, "No-Trade if |EMA20-50| < %", group=grpReg, step=0.05)/100.0
maxDistATR = input.float(1.5, "No-Trade if |Close-EMA20| > ATR×", group=grpReg, step=0.1)
useVWAP = input.bool(true, "Require close above/below VWAP", group=grpReg)
//===================== Helpers ====================
ema20 = ta.ema(close, 20)
ema50 = ta.ema(close, 50)
atr14 = ta.atr(14)
vwap = ta.vwap(hlc3)
rng = high - low
body = math.abs(close - open)
upper = high - math.max(open, close)
lower = math.min(open, close) - low
bull = close > open
bear = close < open
bodyOK = rng > 0 ? (body / rng) >= minBodyP : false
//===================== Patterns ===================
prevOpen = open[1]
prevClose = close[1]
prevBull = prevClose > prevOpen
prevBear = prevClose < prevOpen
bullEngulf_raw = useEngulf and prevBear and bull and (open <= prevClose) and (close >= prevOpen) and bodyOK
bearEngulf_raw = useEngulf and prevBull and bear and (open >= prevClose) and (close <= prevOpen) and bodyOK
bullPin_raw = usePin and (lower >= pinRatio * body) and (upper <= body) and bodyOK // Hammer
bearPin_raw = usePin and (upper >= pinRatio * body) and (lower <= body) and bodyOK // Shooting Star
//================= Regime & No-trade ===============
// HTF trend (EMA50 on higher TF)
emaHTF50 = request.security(syminfo.tickerid, htfTF, ta.ema(close, 50))
htfLong = not useHTF or close > emaHTF50
htfShort = not useHTF or close < emaHTF50
// ADX (manual, version-safe)
len = adxLen
upMove = high - high[1]
downMove = low[1] - low
plusDM = (upMove > downMove and upMove > 0) ? upMove : 0.0
minusDM = (downMove > upMove and downMove > 0) ? downMove : 0.0
trur = ta.rma(ta.tr(true), len)
plusDI = 100 * ta.rma(plusDM, len) / trur
minusDI = 100 * ta.rma(minusDM, len) / trur
dx = 100 * math.abs(plusDI - minusDI) / math.max(plusDI + minusDI, 1e-10)
adxVal = ta.rma(dx, len)
trendOK = not useADX or adxVal >= adxMin
// Volume
volOK = not useVOL or (volume >= ta.sma(volume, 20) * volMult)
// Alignment & slope
slopeUp = ema20 > ema20[3]
slopeDown = ema20 < ema20[3]
alignLong = ema20 > ema50 and slopeUp
alignShort = ema20 < ema50 and slopeDown
// Chop / distance / VWAP
pinch = math.abs(ema20 - ema50) / close < emaPinchPc
tooFar = math.abs(close - ema20) / atr14 > maxDistATR
vwapOKL = not useVWAP or close > vwap
vwapOKS = not useVWAP or close < vwap
//================= Final Setups ====================
longSetup_raw = bullEngulf_raw or bullPin_raw
shortSetup_raw = bearEngulf_raw or bearPin_raw
longSetup = longSetup_raw and alignLong and htfLong and trendOK and volOK and not pinch and not tooFar and vwapOKL
shortSetup = shortSetup_raw and alignShort and htfShort and trendOK and volOK and not pinch and not tooFar and vwapOKS
// Trigger: 다음 봉이 전봉의 고/저 돌파 + 종가 확인
longTrig = longSetup[1] and high > high[1] and close > ema20
shortTrig = shortSetup[1] and low < low[1] and close < ema20
// Cooldown & final signals
var int lastLong = na
var int lastShort = na
canLong = na(lastLong) or (bar_index - lastLong > coolBars)
canShort = na(lastShort) or (bar_index - lastShort > coolBars)
finalLong = longTrig and canLong
finalShort = shortTrig and canShort
if finalLong
lastLong := bar_index
if finalShort
lastShort := bar_index
//==================== Plots ========================
plot(ema20, "EMA 20", color=color.new(color.orange, 0))
plot(ema50, "EMA 50", color=color.new(color.blue, 0))
plot(useVWAP ? vwap : na, "VWAP", color=color.new(color.purple, 0))
plotshape(finalLong, title="LONG ▶", style=shape.labelup, location=location.belowbar, text="Long▶", color=color.new(color.blue, 0), size=size.tiny)
plotshape(finalShort, title="SHORT ▶", style=shape.labeldown, location=location.abovebar, text="Short▶", color=color.new(color.red, 0), size=size.tiny)
// Alerts
alertcondition(finalLong, "LONG ▶", "Long trigger")
alertcondition(finalShort, "SHORT ▶", "Short trigger")
// 시각적 노트레이드 힌트
bgcolor(pinch ? color.new(color.gray, 92) : na)
indicator("Candle Suite PRO – Engulf + Pin + Regime Filters + Trigger", overlay=true, max_labels_count=500)
//===================== Inputs =====================
grpPtn = "Patterns"
useEngulf = input.bool(true, "Enable Engulfing", group=grpPtn)
usePin = input.bool(true, "Enable Pin Bar", group=grpPtn)
pinRatio = input.float(2.0, "PinBar shadow >= body ×", group=grpPtn, step=0.1, minval=1)
minBodyP = input.float(0.15, "Min Body% of Range (0~1)", group=grpPtn, step=0.01, minval=0, maxval=1)
coolBars = input.int(3, "Cooldown bars", group=grpPtn, minval=0)
grpReg = "Regime Filters"
useHTF = input.bool(true, "Use HTF EMA50 Filter", group=grpReg)
htfTF = input.timeframe("60", "HTF timeframe", group=grpReg) // 5m/15m → 60 권장
useADX = input.bool(true, "Use ADX Trend Filter", group=grpReg)
adxLen = input.int(14, "ADX Length", group=grpReg, minval=5)
adxMin = input.int(18, "ADX Min Threshold", group=grpReg, minval=5)
useVOL = input.bool(true, "Use Volume Filter (> SMA×k)",group=grpReg)
volMult = input.float(1.10, "k for Volume", group=grpReg, step=0.05)
emaPinchPc = input.float(0.15, "No-Trade if |EMA20-50| < %", group=grpReg, step=0.05)/100.0
maxDistATR = input.float(1.5, "No-Trade if |Close-EMA20| > ATR×", group=grpReg, step=0.1)
useVWAP = input.bool(true, "Require close above/below VWAP", group=grpReg)
//===================== Helpers ====================
ema20 = ta.ema(close, 20)
ema50 = ta.ema(close, 50)
atr14 = ta.atr(14)
vwap = ta.vwap(hlc3)
rng = high - low
body = math.abs(close - open)
upper = high - math.max(open, close)
lower = math.min(open, close) - low
bull = close > open
bear = close < open
bodyOK = rng > 0 ? (body / rng) >= minBodyP : false
//===================== Patterns ===================
prevOpen = open[1]
prevClose = close[1]
prevBull = prevClose > prevOpen
prevBear = prevClose < prevOpen
bullEngulf_raw = useEngulf and prevBear and bull and (open <= prevClose) and (close >= prevOpen) and bodyOK
bearEngulf_raw = useEngulf and prevBull and bear and (open >= prevClose) and (close <= prevOpen) and bodyOK
bullPin_raw = usePin and (lower >= pinRatio * body) and (upper <= body) and bodyOK // Hammer
bearPin_raw = usePin and (upper >= pinRatio * body) and (lower <= body) and bodyOK // Shooting Star
//================= Regime & No-trade ===============
// HTF trend (EMA50 on higher TF)
emaHTF50 = request.security(syminfo.tickerid, htfTF, ta.ema(close, 50))
htfLong = not useHTF or close > emaHTF50
htfShort = not useHTF or close < emaHTF50
// ADX (manual, version-safe)
len = adxLen
upMove = high - high[1]
downMove = low[1] - low
plusDM = (upMove > downMove and upMove > 0) ? upMove : 0.0
minusDM = (downMove > upMove and downMove > 0) ? downMove : 0.0
trur = ta.rma(ta.tr(true), len)
plusDI = 100 * ta.rma(plusDM, len) / trur
minusDI = 100 * ta.rma(minusDM, len) / trur
dx = 100 * math.abs(plusDI - minusDI) / math.max(plusDI + minusDI, 1e-10)
adxVal = ta.rma(dx, len)
trendOK = not useADX or adxVal >= adxMin
// Volume
volOK = not useVOL or (volume >= ta.sma(volume, 20) * volMult)
// Alignment & slope
slopeUp = ema20 > ema20[3]
slopeDown = ema20 < ema20[3]
alignLong = ema20 > ema50 and slopeUp
alignShort = ema20 < ema50 and slopeDown
// Chop / distance / VWAP
pinch = math.abs(ema20 - ema50) / close < emaPinchPc
tooFar = math.abs(close - ema20) / atr14 > maxDistATR
vwapOKL = not useVWAP or close > vwap
vwapOKS = not useVWAP or close < vwap
//================= Final Setups ====================
longSetup_raw = bullEngulf_raw or bullPin_raw
shortSetup_raw = bearEngulf_raw or bearPin_raw
longSetup = longSetup_raw and alignLong and htfLong and trendOK and volOK and not pinch and not tooFar and vwapOKL
shortSetup = shortSetup_raw and alignShort and htfShort and trendOK and volOK and not pinch and not tooFar and vwapOKS
// Trigger: 다음 봉이 전봉의 고/저 돌파 + 종가 확인
longTrig = longSetup[1] and high > high[1] and close > ema20
shortTrig = shortSetup[1] and low < low[1] and close < ema20
// Cooldown & final signals
var int lastLong = na
var int lastShort = na
canLong = na(lastLong) or (bar_index - lastLong > coolBars)
canShort = na(lastShort) or (bar_index - lastShort > coolBars)
finalLong = longTrig and canLong
finalShort = shortTrig and canShort
if finalLong
lastLong := bar_index
if finalShort
lastShort := bar_index
//==================== Plots ========================
plot(ema20, "EMA 20", color=color.new(color.orange, 0))
plot(ema50, "EMA 50", color=color.new(color.blue, 0))
plot(useVWAP ? vwap : na, "VWAP", color=color.new(color.purple, 0))
plotshape(finalLong, title="LONG ▶", style=shape.labelup, location=location.belowbar, text="Long▶", color=color.new(color.blue, 0), size=size.tiny)
plotshape(finalShort, title="SHORT ▶", style=shape.labeldown, location=location.abovebar, text="Short▶", color=color.new(color.red, 0), size=size.tiny)
// Alerts
alertcondition(finalLong, "LONG ▶", "Long trigger")
alertcondition(finalShort, "SHORT ▶", "Short trigger")
// 시각적 노트레이드 힌트
bgcolor(pinch ? color.new(color.gray, 92) : na)
Script de código abierto
Siguiendo fielmente el espíritu de TradingView, el creador de este script lo ha publicado en código abierto, permitiendo que otros traders puedan revisar y verificar su funcionalidad. ¡Enhorabuena al autor! Puede utilizarlo de forma gratuita, pero tenga en cuenta que la publicación de este código está sujeta a nuestras Normas internas.
Exención de responsabilidad
La información y las publicaciones que ofrecemos, no implican ni constituyen un asesoramiento financiero, ni de inversión, trading o cualquier otro tipo de consejo o recomendación emitida o respaldada por TradingView. Puede obtener información adicional en las Condiciones de uso.
Script de código abierto
Siguiendo fielmente el espíritu de TradingView, el creador de este script lo ha publicado en código abierto, permitiendo que otros traders puedan revisar y verificar su funcionalidad. ¡Enhorabuena al autor! Puede utilizarlo de forma gratuita, pero tenga en cuenta que la publicación de este código está sujeta a nuestras Normas internas.
Exención de responsabilidad
La información y las publicaciones que ofrecemos, no implican ni constituyen un asesoramiento financiero, ni de inversión, trading o cualquier otro tipo de consejo o recomendación emitida o respaldada por TradingView. Puede obtener información adicional en las Condiciones de uso.