Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
A candlestick detector does three helpful jobs:
But it doesn’t magically guarantee profits. Candlestick patterns are clues—not promises. A bullish pattern in a strong downtrend can fail. A doji in the middle of nowhere can mean… nothing. That’s why adding context (trend, key levels, volatility) matters.
Think of the script like a smoke detector. It can warn you quickly, but you still check what’s happening before you act. The best traders combine candle signals with:
Candle patterns tend to behave more cleanly when:
Candles are built from four prices:
These simple ideas power most pattern rules.
This script focuses on patterns many traders actually use:
You’ll also see optional logic for Morning Star / Evening Star (3-candle reversals). If you prefer to keep things simple, you can leave them off.
Here’s a common beginner trap: taking every pattern everywhere.
A smarter approach is to filter signals by trend. One easy method is a fast EMA vs slow EMA filter:
This won’t be perfect, but it helps cut “random middle-of-range” signals.
Paste this into TradingView → Pine Editor → Save → Add to chart.
//@version=5
indicator("Auto Candlestick Patterns Detector (FREE)", overlay=true, max_labels_count=500)//========================
// Inputs
//========================
groupPatterns = "Patterns"
showEngulfing = input.bool(true, "Engulfing", group=groupPatterns)
showHammer = input.bool(true, "Hammer / Hanging Man", group=groupPatterns)
showStar = input.bool(true, "Shooting Star / Inverted Hammer", group=groupPatterns)
showDoji = input.bool(true, "Doji", group=groupPatterns)
showMorningEven = input.bool(false, "Morning/Evening Star (3-candle)", group=groupPatterns)groupFilters = "Filters"
useTrendFilter = input.bool(true, "Use EMA trend filter", group=groupFilters)
emaFastLen = input.int(20, "EMA Fast", minval=1, group=groupFilters)
emaSlowLen = input.int(50, "EMA Slow", minval=1, group=groupFilters)useATRFilter = input.bool(false, "Use ATR size filter (reduces noise)", group=groupFilters)
atrLen = input.int(14, "ATR Length", minval=1, group=groupFilters)
minBodyATR = input.float(0.10, "Min body size (ATR x)", step=0.01, group=groupFilters)useVolFilter = input.bool(false, "Use volume confirmation (vol > vol[1])", group=groupFilters)groupStyle = "Style"
showLabels = input.bool(true, "Show labels", group=groupStyle)
labelSize = input.string("small", "Label size", options=["tiny","small","normal","large","huge"], group=groupStyle)//========================
// Helpers (candle anatomy)
//========================
isBull = close > open
isBear = close < openbody = math.abs(close - open)
range = high - low
upperW = high - math.max(open, close)
lowerW = math.min(open, close) - low// Avoid division by zero
safeRange = range == 0.0 ? 0.0000001 : rangebodyPct = body / safeRange// Trend filter
emaFast = ta.ema(close, emaFastLen)
emaSlow = ta.ema(close, emaSlowLen)
inUpTrend = emaFast > emaSlow
inDownTrend = emaFast < emaSlow// Optional filters
atr = ta.atr(atrLen)
atrOk = not useATRFilter or (body >= atr * minBodyATR)
volOk = not useVolFilter or (volume > volume[1])filtersOk() =>
atrOk and volOktrendOkBull() =>
not useTrendFilter or inUpTrendtrendOkBear() =>
not useTrendFilter or inDownTrend//========================
// Pattern Rules
//========================// 1) Engulfing (body engulfing body)
prevBodyHigh = math.max(open[1], close[1])
prevBodyLow = math.min(open[1], close[1])
curBodyHigh = math.max(open, close)
curBodyLow = math.min(open, close)bullEngulf = showEngulfing and isBull and isBear[1] and (curBodyHigh >= prevBodyHigh) and (curBodyLow <= prevBodyLow) and filtersOk() and trendOkBull()
bearEngulf = showEngulfing and isBear and isBull[1] and (curBodyHigh >= prevBodyHigh) and (curBodyLow <= prevBodyLow) and filtersOk() and trendOkBear()// 2) Hammer / Hanging Man (long lower wick, small body near top)
hammerLike = showHammer and (lowerW >= body * 2.0) and (upperW <= body * 0.7) and (bodyPct <= 0.5) and filtersOk()
hammer = hammerLike and trendOkBull() // best after down move, but we use bull trend filter as a simple bias toggle
hangingMan = hammerLike and trendOkBear() // best after up move, using bear trend filter as a bias toggle// 3) Shooting Star / Inverted Hammer (long upper wick, small body near bottom)
starLike = showStar and (upperW >= body * 2.0) and (lowerW <= body * 0.7) and (bodyPct <= 0.5) and filtersOk()
shootingStar = starLike and trendOkBear()
invertedHammer= starLike and trendOkBull()// 4) Doji (very small body)
doji = showDoji and (bodyPct <= 0.10) and filtersOk()// 5) Morning Star / Evening Star (simplified 3-candle logic)
smallBody(i) =>
math.abs(close[i] - open[i]) / ((high[i] - low[i]) == 0.0 ? 0.0000001 : (high[i] - low[i])) <= 0.30morningStar = showMorningEven and isBear[2] and smallBody(1) and isBull and close > (open[2] + close[2]) / 2 and filtersOk() and trendOkBull()
eveningStar = showMorningEven and isBull[2] and smallBody(1) and isBear and close < (open[2] + close[2]) / 2 and filtersOk() and trendOkBear()//========================
// Plotting (labels)
//========================
makeLabel(_cond, _text, _y, _style) =>
if _cond and showLabels
label.new(bar_index, _y, _text, style=_style, textcolor=color.white, size=labelSize)// Bullish labels under candles
makeLabel(bullEngulf, "Bull Engulf", low, label.style_label_up)
makeLabel(hammer, "Hammer", low, label.style_label_up)
makeLabel(invertedHammer, "Inv Hammer", low, label.style_label_up)
makeLabel(morningStar, "Morning ★", low, label.style_label_up)// Bearish labels above candles
makeLabel(bearEngulf, "Bear Engulf", high, label.style_label_down)
makeLabel(hangingMan, "Hanging", high, label.style_label_down)
makeLabel(shootingStar, "Shoot Star", high, label.style_label_down)
makeLabel(eveningStar, "Evening ★", high, label.style_label_down)// Neutral label
makeLabel(doji, "Doji", close, label.style_label_left)//========================
// Alerts
//========================
alertcondition(bullEngulf, "Bullish Engulfing", "Bullish Engulfing detected")
alertcondition(bearEngulf, "Bearish Engulfing", "Bearish Engulfing detected")
alertcondition(hammer, "Hammer", "Hammer detected")
alertcondition(hangingMan, "Hanging Man", "Hanging Man detected")
alertcondition(shootingStar, "Shooting Star", "Shooting Star detected")
alertcondition(invertedHammer, "Inverted Hammer", "Inverted Hammer detected")
alertcondition(doji, "Doji", "Doji detected")
alertcondition(morningStar, "Morning Star", "Morning Star detected")
alertcondition(eveningStar, "Evening Star", "Evening Star detected")// Optional: show EMAs if trend filter enabled
plot(useTrendFilter ? emaFast : na, title="EMA Fast", linewidth=1)
plot(useTrendFilter ? emaSlow : na, title="EMA Slow", linewidth=1)
Why this approach works well for beginners
To receive notifications:
If you feel like you’re getting “too many signals,” do these in order:
Also remember: many public TradingView candle indicators add extra confirmation steps for a reason—candles alone can be noisy.
Even a perfect detector won’t save a bad plan. Here are simple rules many traders use:
Keep it boring. Boring is good.
Before trusting any pattern:
If you later want automation, you can convert the logic into a strategy script, but it’s smarter to start as an indicator first.
Yes—this is a normal TradingView Pine Script indicator. It draws labels and creates alert conditions; it doesn’t place real trades by itself.
The patterns are calculated on candle close. If you use it on a live candle, the candle can change until it closes—so wait for the bar to finish for clean signals.
Candlestick patterns are probability tools, not guarantees. That’s why trend filters, key levels, and risk management matter.
Yes. You can extend the script with more multi-candle logic. TradingView’s community has large pattern libraries you can learn from.
The script defines alert triggers via alertcondition(). You still create the actual alert from TradingView’s “Create Alert” window by selecting the trigger.
Start with the EMA trend filter, then add the ATR filter if you still get too much noise.
A good detector saves time and keeps your chart reading consistent. But the real edge comes from pairing candle patterns with trend, structure, and risk control. If you want a simple starting point you can actually edit, this script is a solid base—and it’s an Auto Candlestick Patterns Detector TradingView Script For FREE you can run today.