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)
오픈 소스 스크립트
진정한 트레이딩뷰 정신에 따라 이 스크립트 작성자는 트레이더가 기능을 검토하고 검증할 수 있도록 오픈소스로 공개했습니다. 작성자에게 찬사를 보냅니다! 무료로 사용할 수 있지만 코드를 다시 게시할 경우 하우스 룰이 적용된다는 점을 기억하세요.
면책사항
이 정보와 게시물은 TradingView에서 제공하거나 보증하는 금융, 투자, 거래 또는 기타 유형의 조언이나 권고 사항을 의미하거나 구성하지 않습니다. 자세한 내용은 이용 약관을 참고하세요.
오픈 소스 스크립트
진정한 트레이딩뷰 정신에 따라 이 스크립트 작성자는 트레이더가 기능을 검토하고 검증할 수 있도록 오픈소스로 공개했습니다. 작성자에게 찬사를 보냅니다! 무료로 사용할 수 있지만 코드를 다시 게시할 경우 하우스 룰이 적용된다는 점을 기억하세요.
면책사항
이 정보와 게시물은 TradingView에서 제공하거나 보증하는 금융, 투자, 거래 또는 기타 유형의 조언이나 권고 사항을 의미하거나 구성하지 않습니다. 자세한 내용은 이용 약관을 참고하세요.