Do Candlestick Patterns Actually Work?
Candlestick patterns have been used for centuries, but do they provide real trading edges? The answer: it depends. In isolation, most patterns have 50-55% win rates (barely better than coin flips). But when combined with trend context, volume confirmation, and support/resistance levels, win rates can improve to 60-70%.
The Reality of Pattern Trading
Academic studies show raw patterns have limited predictive power. But experienced traders know patterns work better when:
- Used with trend: Bullish patterns in uptrends, bearish in downtrends
- At key levels: Support/resistance, Fibonacci, round numbers
- Volume confirms: Higher volume on reversal patterns
- Multiple timeframes align: Pattern on daily + weekly charts
- Combined with indicators: RSI, MACD confirm the pattern
Backtesting reveals which patterns actually have edges and which are folklore. This guide shows you how to test pattern reliability systematically, not based on cherry-picked examples in trading books.
Most Reliable Candlestick Patterns
Bullish Engulfing
Small red candle followed by larger green candle that completely engulfs the prior day. Shows shift from selling to buying pressure.
Recognition criteria:
- • Day 1: Small bearish candle
- • Day 2: Bullish candle opens below prior close
- • Day 2: Closes above prior open
- • Day 2: Body larger than day 1
Success factors:
- • At support levels: 65% win rate
- • In uptrends: 62% win rate
- • With volume: +8% win rate
- • Raw pattern: 52% win rate
Bearish Engulfing
Small green candle followed by larger red candle. Reversal pattern at resistance or after uptrend.
Best conditions:
- • At resistance levels
- • After extended uptrend
- • RSI > 70 (overbought)
- • High volume on red candle
Win rates:
- • At resistance: 63% down move
- • In downtrends: 60% continue
- • Raw pattern: 51% win rate
- • Needs context to be reliable
Hammer & Hanging Man
Small body, long lower wick (2-3x body size). Hammer bullish at bottoms, hanging man bearish at tops.
Pattern recognition:
• Lower wick ≥ 2x body length
• Upper wick minimal or absent
• Body can be red or green (green slightly better)
• Requires confirmation (next candle closes higher for hammer)
Reality check: Win rate without confirmation: 48%. With next-day confirmation: 58%. At support levels: 65%.
Doji Patterns
Open and close nearly equal. Shows indecision. Most effective at trend extremes signaling reversals.
Types:
- • Standard doji: Open ≈ Close
- • Long-legged: Long wicks both sides
- • Dragonfly: Long lower wick
- • Gravestone: Long upper wick
Reliability:
- • At trend extremes: 57% reversal
- • In mid-trend: 49% (useless)
- • Multiple dojis: Stronger signal
- • Confirmation required: Wait 1 day
Morning Star / Evening Star
Three-candle reversal pattern. Morning star bullish, evening star bearish. Most reliable multi-candle pattern.
Morning Star (bullish):
1. Large red candle (downtrend)
2. Small body (doji/spinning top) - gap down
3. Large green candle closing into first candle's body
Backtested results:
• At support: 68% win rate
• In downtrends: 62% reversal
• With RSI < 30: 71% win rate
• Raw pattern: 58% (still better than most)
Shooting Star
Small body, long upper wick. Bearish reversal after uptrend. Shows buying pressure rejected.
- Recognition: Upper wick ≥ 2x body, little/no lower wick, at resistance or after rally
- At resistance: 61% predicts down move next 3-5 days
- Random location: 48% win rate (no edge)
- Key lesson: Location matters more than pattern perfection
Coding Pattern Recognition
To backtest patterns, you must define them programmatically. Human eyes are too subjective. Here's how to code the most reliable patterns.
Bullish Engulfing Code Example
# Python example with pandas DataFrame (df)
# Requires: df with Open, High, Low, Close columns
def is_bullish_engulfing(df, i):
"""
Returns True if candle at index i is bullish engulfing
i-1 = prior candle (day 1)
i = current candle (day 2)
"""
if i < 1: # Need at least 2 candles
return False
# Day 1: Bearish candle
prev_open = df['Open'].iloc[i-1]
prev_close = df['Close'].iloc[i-1]
prev_bearish = prev_close < prev_open
# Day 2: Bullish candle
curr_open = df['Open'].iloc[i]
curr_close = df['Close'].iloc[i]
curr_bullish = curr_close > curr_open
# Engulfing conditions
opens_below = curr_open < prev_close
closes_above = curr_close > prev_open
# Body size (optional: day 2 body > day 1 body)
prev_body = abs(prev_close - prev_open)
curr_body = abs(curr_close - curr_open)
larger_body = curr_body > prev_body
return (prev_bearish and curr_bullish and
opens_below and closes_above and larger_body)
# Apply to entire DataFrame
df['Bullish_Engulfing'] = [
is_bullish_engulfing(df, i)
for i in range(len(df))
]Hammer Pattern Code
def is_hammer(df, i):
"""
Hammer: Small body, long lower wick, minimal upper wick
"""
if i < 0:
return False
open_price = df['Open'].iloc[i]
close_price = df['Close'].iloc[i]
high_price = df['High'].iloc[i]
low_price = df['Low'].iloc[i]
# Body size and wick calculations
body = abs(close_price - open_price)
upper_wick = high_price - max(open_price, close_price)
lower_wick = min(open_price, close_price) - low_price
total_range = high_price - low_price
# Hammer criteria
# 1. Lower wick is at least 2x body size
# 2. Upper wick is small (< 20% of lower wick)
# 3. Body is in upper portion of candle
if total_range == 0: # Avoid division by zero
return False
long_lower_wick = lower_wick >= 2 * body
small_upper_wick = upper_wick < 0.2 * lower_wick
body_at_top = upper_wick < 0.3 * total_range
return long_lower_wick and small_upper_wick and body_at_top
df['Hammer'] = [is_hammer(df, i) for i in range(len(df))]Pattern Recognition Tips
- Use relative sizes: Don't hardcode "body must be < $0.50". Use ratios: body < 30% of total range
- Allow tolerance: "Open ≈ Close" for doji means within 5-10% of total range, not exactly equal
- Normalize for price: $1 body means different things for $10 vs $100 stock. Use percentages
- Test sensitivity: Does 2x lower wick work better than 2.5x or 1.5x? Optimize but avoid overfitting
- Vectorize operations: Use pandas/numpy operations on entire DataFrame instead of loops for speed
Adding Context Filters
This is where patterns go from 50% to 65%+ win rates. Context filters separate profitable signals from noise.
Trend Filter
Only trade bullish patterns in uptrends, bearish patterns in downtrends. Simple but effective.
Implementation:
• Calculate 50-day MA and 200-day MA
• Uptrend: Price > 50 MA and 50 MA > 200 MA
• Downtrend: Price < 50 MA and 50 MA < 200 MA
• Only take bullish patterns in uptrends
Impact: Improves win rate by 8-12%
Support/Resistance Filter
Patterns at key levels are self-fulfilling prophecies as many traders watch them.
- Swing lows/highs: Identify recent support/resistance levels (last 20-50 bars)
- Tolerance: Pattern within 1-2% of level counts as "at support/resistance"
- Fibonacci: Retracement levels (38.2%, 50%, 61.8%) act as strong S/R
- Psychological levels: Round numbers ($50, $100, etc.) get more attention
- Impact: Win rate increases 10-15% when pattern forms at key level
Volume Confirmation
High volume on reversal patterns shows strong conviction. Low volume = weak signal.
Volume rules:
- • Calculate 20-day average volume
- • Pattern day volume > 1.5x average
- • Engulfing patterns: Volume on day 2
- • Morning/evening star: Day 3 volume
Results:
- • With volume: 62% win rate
- • Without volume: 54% win rate
- • Difference: +8% edge
- • Trade fewer but better setups
Indicator Confirmation
Combine patterns with RSI, MACD, or other indicators for higher probability setups.
- RSI: Bullish pattern with RSI < 30 (oversold), bearish with RSI > 70 (overbought)
- MACD: Pattern + MACD crossover in same direction = strong confirmation
- Stochastic: Oversold/overbought extremes + pattern = high win rate
- Impact: Multi-factor confirmation improves win rate to 68-72% but reduces trade frequency
Backtesting Methodology
Key Metrics to Track
| Metric | Good | Red Flag |
|---|---|---|
| Win rate (with context) | 58-65% with trend + S/R | >75% raw or only on one ticker |
| Profit factor | 1.5-2.2 | >3.0 with few trades |
| Max drawdown | <20% | >30% or unrecovered |
| Trades per pattern | 50-200+ occurrences | <30 samples (no statistical power) |
| Average R:R | 1.2:1 to 2.0:1 | <1:1 or huge winners with tiny sample |
| Edge consistency | Works across 20+ tickers / regimes | Only works on 1-2 cherry-picked symbols |
Complete Backtest Framework
1. Data Requirements
• Minimum 3-5 years daily OHLCV data
• Multiple stocks/instruments (50+ for statistical significance)
• Adjusted for splits/dividends
• Clean data (remove bad ticks, check for gaps)
2. Entry Rules
• Enter next day at open (realistic) or at limit order (specify price)
• Optional: Wait for confirmation (next candle closes in pattern direction)
• Confirmation reduces false signals but may miss some winners
• Backtest both approaches to see which works better
3. Exit Rules
• Fixed stop loss: 2-3% below pattern low (bullish) or above high (bearish)
• Fixed target: 4-6% profit (2:1 risk/reward)
• Trailing stop: Trail by 1-2% once up 3%+
• Time stop: Exit after 5-10 days if no movement
• Test multiple exit strategies
4. Position Sizing
• Risk 1-2% of account per trade
• Calculate position size based on stop distance
• Example: $50K account, 2% risk = $1,000 max loss
• If stop is 3% away, position size = $1,000 / 0.03 = $33,333 worth of stock
5. Metrics to Track
• Win rate (separate for pattern type, trend direction, at S/R levels)
• Average win vs average loss
• Profit factor (gross profit / gross loss)
• Maximum drawdown
• Sharpe ratio (risk-adjusted return)
• Number of trades (need 50+ for statistical validity)
What Good Results Look Like
Realistic Expectations:
Excellent pattern strategy:
• Win rate: 60-65%
• Profit factor: 1.8-2.2
• Average R:R: 1.5:1 to 2:1
• Max drawdown: 15-20%
• Annual return: 20-40%
Red flags (likely overfit):
• Win rate > 75%
• Profit factor > 3.0
• Very few trades (< 30 in backtest)
• Perfect equity curve (no drawdowns)
• Works on one stock but not others
Common Candlestick Backtesting Mistakes
Cherry-Picking Examples
Trading books show perfect hammer-to-moon examples. Reality: for every perfect example, there are 3-4 failures. Only systematic backtesting across hundreds of patterns reveals true win rates. Test on all occurrences, not just the pretty ones that worked.
Ignoring Failed Patterns
"That wasn't a real hammer, the body was too big" - rationalizing after the fact. If you can't code it objectively, you can't trade it consistently. Define exact criteria, test them all, accept the losses as part of the edge. No subjective filters allowed in live trading if not in backtest.
Testing on Too Few Stocks
"Hammers work great on AAPL!" might be coincidence. Need 50+ stocks to validate a pattern. Some stocks are more pattern-responsive, others random. If pattern only works on 3-5 specific stocks, you found curve-fitting not an edge. Test across indices, sectors, market caps.
No Position Sizing
Testing with "1 share per trade" or "$10,000 per trade" regardless of stop distance. Real trading uses percentage risk. A 3% stop with 2% risk = different position size than 5% stop with 2% risk. Backtest with realistic position sizing or results are meaningless.
Expecting Every Pattern to Work
60% win rate means 40% of patterns fail. That's 4 out of 10 trades are losers. Many traders give up after 3 losses in a row, but that's statistically normal. Edge comes from long-term statistics, not individual trades. Trust the backtest, follow the rules, let probabilities play out over 50+ trades.
Frequently Asked Questions
Do candlestick patterns work in all markets?
Should I wait for pattern confirmation?
Which patterns have the highest win rates?
Can I trade patterns without indicators?
How long do pattern signals stay valid?
Should I trade multiple patterns or specialize in one?
Related Guides
Ready to Test Your Candlestick Strategy?
Use BacktestMe's pattern recognition tools to test hammers, engulfing patterns, and dojis with trend filters, support/resistance levels, and volume confirmation.
Build Your Pattern Strategy Now →