Pattern Recognition Guide¶
Learn how to identify and trade candlestick patterns using SQA::TAI. This guide covers the fundamentals of pattern recognition, signal interpretation, and practical trading strategies.
Introduction to Candlestick Patterns¶
Candlestick patterns are formations created by one or more candlesticks that provide insights into market psychology and potential price movements. Originating in 18th century Japan, these patterns remain powerful tools for modern traders.
Why Use Candlestick Patterns?¶
- Visual Clarity: Easy to spot and interpret on charts
- Market Psychology: Reveal sentiment shifts between bulls and bears
- Early Signals: Often indicate reversals before other indicators
- Universal Application: Work across all markets and timeframes
- Proven History: Centuries of successful trading applications
Getting Started with Pattern Recognition¶
Basic Pattern Detection¶
All pattern recognition functions in SQA::TAI follow a consistent API:
require 'sqa/tai'
# OHLC data required for all patterns
open = [100.0, 101.0, 102.0, 101.5, 103.0]
high = [102.0, 103.0, 104.0, 103.0, 105.0]
low = [99.5, 100.0, 101.0, 100.5, 102.0]
close = [101.0, 102.0, 101.5, 103.0, 104.0]
# Detect a pattern
result = SQA::TAI.cdl_hammer(open, high, low, close)
# Interpret the signal
signal = result.last
case signal
when 100
puts "Bullish Hammer detected!"
when -100
puts "Bearish pattern detected!"
when 0
puts "No pattern detected"
end
Understanding Pattern Signals¶
Pattern functions return integer arrays with these values:
| Value | Meaning | Action |
|---|---|---|
| 0 | No pattern detected | Continue monitoring |
| +100 | Bullish pattern | Consider long positions |
| -100 | Bearish pattern | Consider short positions |
| +200/-200 | Strong pattern | Higher confidence signals |
Pattern Categories¶
1. Single Candlestick Patterns¶
Formed by one candle, these patterns offer quick signals:
# Doji - Indecision
doji = SQA::TAI.cdl_doji(open, high, low, close)
# Hammer - Bullish reversal
hammer = SQA::TAI.cdl_hammer(open, high, low, close)
# Shooting Star - Bearish reversal
shooting_star = SQA::TAI.cdl_shootingstar(open, high, low, close)
# Spinning Top - Indecision
spinning_top = SQA::TAI.cdl_spinningtop(open, high, low, close)
Characteristics: - Quick to form (1 candle) - Less reliable alone - Best with confirmation - Good for intraday trading
2. Two Candlestick Patterns¶
More reliable, requiring two consecutive candles:
# Engulfing - Strong reversal
engulfing = SQA::TAI.cdl_engulfing(open, high, low, close)
# Harami - Potential reversal
harami = SQA::TAI.cdl_harami(open, high, low, close)
# Piercing Pattern - Bullish reversal
piercing = SQA::TAI.cdl_piercing(open, high, low, close)
# Dark Cloud Cover - Bearish reversal
dark_cloud = SQA::TAI.cdl_darkcloudcover(open, high, low, close)
Characteristics: - More reliable than single patterns - Clearer market intent - Better risk/reward setups - Suitable for swing trading
3. Three+ Candlestick Patterns¶
Most reliable, showing sustained market behavior:
# Morning Star - Strong bullish reversal
morning_star = SQA::TAI.cdl_morningstar(open, high, low, close)
# Evening Star - Strong bearish reversal
evening_star = SQA::TAI.cdl_eveningstar(open, high, low, close)
# Three White Soldiers - Strong bullish continuation
three_white = SQA::TAI.cdl_3whitesoldiers(open, high, low, close)
# Three Black Crows - Strong bearish continuation
three_black = SQA::TAI.cdl_3blackcrows(open, high, low, close)
Characteristics: - Highest reliability - Best for position trading - Clearest trend signals - Lower false signal rate
Pattern Scanning Strategy¶
Scanning Multiple Patterns¶
require 'sqa/tai'
# Load market data
open, high, low, close = load_ohlc_data('AAPL')
# Define patterns to scan
patterns = {
'Hammer' => :cdl_hammer,
'Shooting Star' => :cdl_shootingstar,
'Engulfing' => :cdl_engulfing,
'Harami' => :cdl_harami,
'Morning Star' => :cdl_morningstar,
'Evening Star' => :cdl_eveningstar,
'Doji' => :cdl_doji,
'Hanging Man' => :cdl_hangingman
}
# Scan for active patterns
puts "Pattern Scan Results for AAPL"
puts "=" * 50
patterns.each do |name, method|
result = SQA::TAI.send(method, open, high, low, close)
signal = result.last
next if signal == 0
sentiment = signal > 0 ? "BULLISH" : "BEARISH"
strength = signal.abs == 200 ? "STRONG" : "MODERATE"
puts "#{name}: #{sentiment} (#{strength})"
puts "Signal Value: #{signal}"
puts ""
end
Multi-Market Scanner¶
require 'sqa/tai'
symbols = ['AAPL', 'MSFT', 'GOOGL', 'TSLA', 'NVDA']
puts "Market-Wide Pattern Scanner"
puts "=" * 60
symbols.each do |symbol|
open, high, low, close = load_ohlc_data(symbol)
# Scan for strong reversal patterns
hammer = SQA::TAI.cdl_hammer(open, high, low, close)
engulfing = SQA::TAI.cdl_engulfing(open, high, low, close)
morning_star = SQA::TAI.cdl_morningstar(open, high, low, close)
signals = []
signals << "Hammer" if hammer.last == 100
signals << "Bullish Engulfing" if engulfing.last == 100
signals << "Morning Star" if morning_star.last == 100
if signals.any?
puts "\n#{symbol} - Bullish Patterns Detected:"
signals.each { |s| puts " - #{s}" }
end
end
Pattern Confirmation Techniques¶
1. Trend Context Confirmation¶
# Load data
open, high, low, close = load_ohlc_data('MSFT')
# Identify trend
sma_50 = SQA::TAI.sma(close, period: 50)
sma_200 = SQA::TAI.sma(close, period: 200)
trend = if close.last > sma_50.last && sma_50.last > sma_200.last
"UPTREND"
elsif close.last < sma_50.last && sma_50.last < sma_200.last
"DOWNTREND"
else
"SIDEWAYS"
end
# Detect reversal pattern
hammer = SQA::TAI.cdl_hammer(open, high, low, close)
# Pattern context matters
if hammer.last == 100
if trend == "DOWNTREND"
puts "STRONG SIGNAL: Bullish hammer in downtrend"
puts "High probability reversal setup"
elsif trend == "UPTREND"
puts "WEAK SIGNAL: Bullish hammer in uptrend"
puts "May be continuation, not reversal"
end
end
2. Volume Confirmation¶
# Load data with volume
open, high, low, close, volume = load_ohlc_volume('TSLA')
# Calculate average volume
avg_volume = volume[-20..-1].sum / 20.0
# Detect pattern
engulfing = SQA::TAI.cdl_engulfing(open, high, low, close)
if engulfing.last != 0
pattern_type = engulfing.last > 0 ? "Bullish" : "Bearish"
volume_ratio = volume.last / avg_volume
puts "#{pattern_type} Engulfing Pattern"
puts "Volume Ratio: #{volume_ratio.round(2)}x average"
if volume_ratio > 1.5
puts "CONFIRMED: High volume supports pattern"
elsif volume_ratio < 0.8
puts "WEAK: Low volume, pattern less reliable"
else
puts "NEUTRAL: Normal volume"
end
end
3. Momentum Confirmation¶
# Load data
open, high, low, close = load_ohlc_data('NVDA')
# Detect pattern
morning_star = SQA::TAI.cdl_morningstar(open, high, low, close)
# Check momentum
rsi = SQA::TAI.rsi(close, period: 14)
macd, signal, hist = SQA::TAI.macd(close)
if morning_star.last == 100
puts "Morning Star Pattern Detected"
# Momentum confirmation
confirmations = 0
confirmations += 1 if rsi.last < 40 # Oversold
confirmations += 1 if macd.last > signal.last # MACD bullish
confirmations += 1 if hist.last > hist[-1] # MACD histogram rising
puts "Confirmations: #{confirmations}/3"
if confirmations >= 2
puts "STRONG BUY: Pattern + momentum aligned"
elsif confirmations == 1
puts "MODERATE: Some confirmation"
else
puts "WEAK: No momentum confirmation"
end
end
4. Support/Resistance Confirmation¶
# Identify support level
def find_support(low_prices, lookback = 20)
low_prices[-lookback..-1].min
end
# Load data
open, high, low, close = load_ohlc_data('AAPL')
# Find support
support = find_support(low)
# Detect hammer
hammer = SQA::TAI.cdl_hammer(open, high, low, close)
if hammer.last == 100
distance_from_support = ((low.last - support) / support * 100).round(2)
puts "Hammer Pattern Detected"
puts "Distance from Support: #{distance_from_support}%"
if distance_from_support.abs < 1.0
puts "EXCELLENT: Pattern at key support"
puts "Very high probability setup"
elsif distance_from_support.abs < 3.0
puts "GOOD: Pattern near support"
else
puts "NEUTRAL: No support nearby"
end
end
Complete Pattern Trading System¶
Here's a comprehensive example integrating multiple confirmation techniques:
require 'sqa/tai'
class PatternTradingSystem
def initialize(symbol)
@symbol = symbol
@open, @high, @low, @close, @volume = load_ohlc_volume(symbol)
end
def analyze
puts "=" * 70
puts "Pattern Analysis: #{@symbol}"
puts "=" * 70
# Step 1: Market Context
analyze_market_context
# Step 2: Pattern Detection
patterns = detect_patterns
# Step 3: Confirmation Analysis
patterns.each do |pattern|
analyze_pattern_with_confirmation(pattern)
end
end
private
def analyze_market_context
sma_50 = SQA::TAI.sma(@close, period: 50)
sma_200 = SQA::TAI.sma(@close, period: 200)
atr = SQA::TAI.atr(@high, @low, @close, period: 14)
atr_pct = (atr.last / @close.last * 100).round(2)
@trend = if @close.last > sma_50.last && sma_50.last > sma_200.last
"UPTREND"
elsif @close.last < sma_50.last && sma_50.last < sma_200.last
"DOWNTREND"
else
"SIDEWAYS"
end
@avg_volume = @volume[-20..-1].sum / 20.0
puts "\n1. Market Context"
puts " Trend: #{@trend}"
puts " Price: $#{@close.last.round(2)}"
puts " Volatility (ATR): #{atr_pct}%"
puts " Avg Volume: #{@avg_volume.round(0)}"
end
def detect_patterns
patterns = []
# Define patterns to check
pattern_checks = {
'Hammer' => [:cdl_hammer, :bullish],
'Hanging Man' => [:cdl_hangingman, :bearish],
'Shooting Star' => [:cdl_shootingstar, :bearish],
'Engulfing' => [:cdl_engulfing, :either],
'Harami' => [:cdl_harami, :either],
'Morning Star' => [:cdl_morningstar, :bullish],
'Evening Star' => [:cdl_eveningstar, :bearish],
'Doji' => [:cdl_doji, :indecision]
}
puts "\n2. Pattern Detection"
pattern_checks.each do |name, (method, direction)|
result = SQA::TAI.send(method, @open, @high, @low, @close)
signal = result.last
next if signal == 0
patterns << {
name: name,
signal: signal,
direction: direction,
sentiment: signal > 0 ? :bullish : :bearish
}
puts " ✓ #{name} detected (#{signal})"
end
puts " Found #{patterns.length} active pattern(s)" if patterns.empty?
patterns
end
def analyze_pattern_with_confirmation(pattern)
puts "\n" + "=" * 70
puts "Pattern: #{pattern[:name]}"
puts "Signal: #{pattern[:signal]} (#{pattern[:sentiment].to_s.upcase})"
puts "=" * 70
score = 0
max_score = 6
# Confirmation 1: Trend Context
puts "\n▸ Trend Context:"
if @trend == "UPTREND" && pattern[:sentiment] == :bullish
score += 2
puts " ✓ Bullish pattern in uptrend (continuation)"
elsif @trend == "DOWNTREND" && pattern[:sentiment] == :bullish
score += 2
puts " ✓✓ Bullish pattern in downtrend (reversal) - STRONG"
elsif @trend == "DOWNTREND" && pattern[:sentiment] == :bearish
score += 2
puts " ✓ Bearish pattern in downtrend (continuation)"
elsif @trend == "UPTREND" && pattern[:sentiment] == :bearish
score += 2
puts " ✓✓ Bearish pattern in uptrend (reversal) - STRONG"
else
puts " - Neutral trend context"
end
# Confirmation 2: Volume
puts "\n▸ Volume Confirmation:"
volume_ratio = @volume.last / @avg_volume
if volume_ratio > 1.5
score += 2
puts " ✓✓ High volume (#{volume_ratio.round(2)}x) - STRONG"
elsif volume_ratio > 1.0
score += 1
puts " ✓ Above average volume (#{volume_ratio.round(2)}x)"
else
puts " - Below average volume (#{volume_ratio.round(2)}x)"
end
# Confirmation 3: Momentum
puts "\n▸ Momentum Confirmation:"
rsi = SQA::TAI.rsi(@close, period: 14)
macd, signal_line, hist = SQA::TAI.macd(@close)
if pattern[:sentiment] == :bullish
if rsi.last < 40
score += 1
puts " ✓ RSI oversold (#{rsi.last.round(2)})"
end
if macd.last > signal_line.last
score += 1
puts " ✓ MACD bullish"
end
elsif pattern[:sentiment] == :bearish
if rsi.last > 60
score += 1
puts " ✓ RSI overbought (#{rsi.last.round(2)})"
end
if macd.last < signal_line.last
score += 1
puts " ✓ MACD bearish"
end
end
# Final Assessment
puts "\n" + "-" * 70
puts "SCORE: #{score}/#{max_score}"
if score >= 5
puts "RATING: ★★★★★ EXCELLENT - High probability setup"
generate_trade_plan(pattern, :high)
elsif score >= 3
puts "RATING: ★★★☆☆ GOOD - Moderate probability"
generate_trade_plan(pattern, :moderate)
else
puts "RATING: ★☆☆☆☆ WEAK - Low probability"
puts "Action: Wait for better confirmation"
end
end
def generate_trade_plan(pattern, confidence)
puts "\n▸ Trade Plan:"
atr = SQA::TAI.atr(@high, @low, @close, period: 14)
current_price = @close.last
if pattern[:sentiment] == :bullish
entry = current_price
stop = current_price - (2 * atr.last)
target1 = current_price + (2 * atr.last)
target2 = current_price + (3 * atr.last)
puts " Direction: LONG"
puts " Entry: $#{entry.round(2)}"
puts " Stop Loss: $#{stop.round(2)} (-#{((entry - stop) / entry * 100).round(2)}%)"
puts " Target 1: $#{target1.round(2)} (+#{((target1 - entry) / entry * 100).round(2)}%)"
puts " Target 2: $#{target2.round(2)} (+#{((target2 - entry) / entry * 100).round(2)}%)"
else
entry = current_price
stop = current_price + (2 * atr.last)
target1 = current_price - (2 * atr.last)
target2 = current_price - (3 * atr.last)
puts " Direction: SHORT"
puts " Entry: $#{entry.round(2)}"
puts " Stop Loss: $#{stop.round(2)} (+#{((stop - entry) / entry * 100).round(2)}%)"
puts " Target 1: $#{target1.round(2)} (-#{((entry - target1) / entry * 100).round(2)}%)"
puts " Target 2: $#{target2.round(2)} (-#{((entry - target2) / entry * 100).round(2)}%)"
end
position_size = if confidence == :high
"100% of normal size"
elsif confidence == :moderate
"50-75% of normal size"
else
"25-50% of normal size"
end
puts " Position Size: #{position_size}"
end
end
# Run the system
system = PatternTradingSystem.new('AAPL')
system.analyze
Best Practices¶
1. Never Trade Patterns Alone¶
Always confirm patterns with: - Trend analysis - Volume - Momentum indicators - Support/Resistance levels
2. Wait for Confirmation¶
Don't enter immediately on pattern detection. Wait for: - Next candle closing in pattern direction - Volume increase - Break of key levels
3. Use Proper Risk Management¶
- Always use stop losses
- Risk only 1-2% per trade
- Calculate position size based on stop distance
- Have predefined profit targets
4. Consider Context¶
Patterns are more reliable when they: - Form at key support/resistance - Appear after strong trends - Occur on higher timeframes - Align with overall market direction
5. Track Performance¶
Keep a trading journal: - Which patterns work best - What confirmation methods help most - Win rate by pattern type - Adjust strategy based on results
Common Mistakes to Avoid¶
- Overtrading: Not every pattern is worth trading
- Ignoring Trend: Fighting the overall trend reduces success
- No Confirmation: Trading patterns without supporting evidence
- Poor Risk Management: Not using stops or risking too much
- Cherry Picking: Only seeing patterns you want to see
Next Steps¶
- Practice Pattern Recognition: Study historical charts
- Paper Trade: Test strategies without real money
- Start Small: Begin with proven high-probability patterns
- Keep Learning: Study why patterns succeed or fail
- Build Systems: Automate scanning and analysis