Candlestick Pattern Recognition
OnlineTechnicalIndicators.jl includes comprehensive support for candlestick pattern recognition using an incremental (online) approach. All pattern detectors work with streaming data and maintain minimal state.
Overview
Pattern recognition indicators detect specific candlestick formations that often signal potential market reversals or continuations. These patterns are categorized by the number of candles required:
- Single-candle patterns: Patterns formed by one candlestick (e.g., Doji, Hammer)
- Two-candle patterns: Patterns formed by two consecutive candlesticks (e.g., Engulfing, Harami)
- Three-candle patterns: Patterns formed by three consecutive candlesticks (e.g., Morning Star, Three White Soldiers)
Pattern Types and Enumerations
Single Candle Patterns
using OnlineTechnicalIndicators
# Available single-candle patterns
SingleCandlePatternType.NONE
SingleCandlePatternType.DOJI
SingleCandlePatternType.DRAGONFLY_DOJI
SingleCandlePatternType.GRAVESTONE_DOJI
SingleCandlePatternType.HAMMER
SingleCandlePatternType.HANGING_MAN
SingleCandlePatternType.SHOOTING_STAR
SingleCandlePatternType.INVERTED_HAMMER
SingleCandlePatternType.MARUBOZU_BULLISH
SingleCandlePatternType.MARUBOZU_BEARISH
SingleCandlePatternType.SPINNING_TOPTwo Candle Patterns
# Available two-candle patterns
TwoCandlePatternType.NONE
TwoCandlePatternType.BULLISH_ENGULFING
TwoCandlePatternType.BEARISH_ENGULFING
TwoCandlePatternType.BULLISH_HARAMI
TwoCandlePatternType.BEARISH_HARAMI
TwoCandlePatternType.PIERCING_LINE
TwoCandlePatternType.DARK_CLOUD_COVER
TwoCandlePatternType.TWEEZER_TOP
TwoCandlePatternType.TWEEZER_BOTTOMThree Candle Patterns
# Available three-candle patterns
ThreeCandlePatternType.NONE
ThreeCandlePatternType.MORNING_STAR
ThreeCandlePatternType.EVENING_STAR
ThreeCandlePatternType.THREE_WHITE_SOLDIERS
ThreeCandlePatternType.THREE_BLACK_CROWS
ThreeCandlePatternType.THREE_INSIDE_UP
ThreeCandlePatternType.THREE_INSIDE_DOWNPattern Direction
# Pattern direction indicates bullish, bearish, or neutral sentiment
PatternDirection.NEUTRAL
PatternDirection.BULLISH
PatternDirection.BEARISHIndividual Pattern Detectors
Doji
A Doji occurs when open and close prices are virtually equal, indicating market indecision.
doji = Doji{OHLCV{Missing,Float64,Missing}}(body_tolerance = 0.1)
fit!(doji, candle)
result = value(doji) # Returns SingleCandlePatternValParameters:
body_tolerance: Maximum ratio of body to total range (default: 0.1)
Subtypes:
- Standard Doji: Equal open and close with shadows on both sides
- Dragonfly Doji: Long lower shadow, no upper shadow (bullish)
- Gravestone Doji: Long upper shadow, no lower shadow (bearish)
Hammer
A Hammer is characterized by a small body at the top with a long lower shadow.
hammer = Hammer{OHLCV{Missing,Float64,Missing}}(
body_ratio = 0.33,
shadow_ratio = 2.0,
upper_shadow_tolerance = 0.1
)
fit!(hammer, candle)
result = value(hammer)Parameters:
body_ratio: Maximum ratio of body to total range (default: 0.33)shadow_ratio: Minimum ratio of lower shadow to body (default: 2.0)upper_shadow_tolerance: Maximum upper shadow tolerance (default: 0.1)
Shooting Star
A Shooting Star has a small body at the bottom with a long upper shadow.
shooting_star = ShootingStar{OHLCV{Missing,Float64,Missing}}()
fit!(shooting_star, candle)Marubozu
A Marubozu has little to no shadows, indicating strong directional momentum.
marubozu = Marubozu{OHLCV{Missing,Float64,Missing}}(shadow_tolerance = 0.05)
fit!(marubozu, candle)Spinning Top
A Spinning Top has a small body with relatively long shadows on both sides.
spinning_top = SpinningTop{OHLCV{Missing,Float64,Missing}}(
body_ratio = 0.25,
min_shadow_ratio = 0.3
)
fit!(spinning_top, candle)Engulfing
An Engulfing pattern occurs when one candle's body completely engulfs the previous candle's body.
engulfing = Engulfing{OHLCV{Missing,Float64,Missing}}(min_body_ratio = 1.1)
# Fit with two consecutive candles
fit!(engulfing, candle1)
fit!(engulfing, candle2)
result = value(engulfing) # Returns TwoCandlePatternValHarami
A Harami occurs when a small candle is contained within the previous candle's body.
harami = Harami{OHLCV{Missing,Float64,Missing}}(max_body_ratio = 0.5)
fit!(harami, candle1)
fit!(harami, candle2)Piercing Line / Dark Cloud Cover
These patterns involve 50%+ penetration of the previous candle's body.
piercing = PiercingDarkCloud{OHLCV{Missing,Float64,Missing}}(min_penetration = 0.5)
fit!(piercing, candle1)
fit!(piercing, candle2)Tweezer Top / Bottom
Tweezer patterns have matching highs (top) or lows (bottom).
tweezer = Tweezer{OHLCV{Missing,Float64,Missing}}(tolerance = 0.001)
fit!(tweezer, candle1)
fit!(tweezer, candle2)Morning Star / Evening Star
Star patterns involve three candles with a small-bodied "star" in the middle.
star = Star{OHLCV{Missing,Float64,Missing}}(
doji_tolerance = 0.1,
min_gap_ratio = 0.1
)
fit!(star, candle1)
fit!(star, candle2)
fit!(star, candle3)
result = value(star) # Returns ThreeCandlePatternValThree White Soldiers / Three Black Crows
These patterns involve three consecutive candles in the same direction with progressive closes.
soldiers = ThreeSoldiersCrows{OHLCV{Missing,Float64,Missing}}(min_progress = 0.2)
fit!(soldiers, candle1)
fit!(soldiers, candle2)
fit!(soldiers, candle3)Three Inside Up / Down
Combination of Harami followed by confirmation candle.
three_inside = ThreeInside{OHLCV{Missing,Float64,Missing}}(max_harami_ratio = 0.5)
fit!(three_inside, candle1)
fit!(three_inside, candle2)
fit!(three_inside, candle3)Comprehensive Pattern Detector
The CandlestickPatternDetector aggregates all pattern detectors and can detect multiple patterns simultaneously.
detector = CandlestickPatternDetector{OHLCV{Missing,Float64,Missing}}(
enable_single = true,
enable_two = true,
enable_three = true
)
# Stream candles
fit!(detector, candle1)
fit!(detector, candle2)
fit!(detector, candle3)
result = value(detector) # Returns AllPatternsVal
# Access detected patterns
for pattern in result.single_patterns
println("Single: $(pattern.pattern), confidence: $(pattern.confidence)")
end
for pattern in result.two_patterns
println("Two: $(pattern.pattern), confidence: $(pattern.confidence)")
end
for pattern in result.three_patterns
println("Three: $(pattern.pattern), confidence: $(pattern.confidence)")
endParameters:
enable_single: Enable single-candle detection (default: true)enable_two: Enable two-candle detection (default: true)enable_three: Enable three-candle detection (default: true)
Return Values
SingleCandlePatternVal
struct SingleCandlePatternVal{T}
pattern::SingleCandlePattern
confidence::T # 0.0 to 1.0
direction::Direction # BULLISH, BEARISH, or NEUTRAL
endTwoCandlePatternVal
struct TwoCandlePatternVal{T}
pattern::TwoCandlePattern
confidence::T
direction::Direction
endThreeCandlePatternVal
struct ThreeCandlePatternVal{T}
pattern::ThreeCandlePattern
confidence::T
direction::Direction
endAllPatternsVal
struct AllPatternsVal{S}
single_patterns::Vector{SingleCandlePatternVal{S}}
two_patterns::Vector{TwoCandlePatternVal{S}}
three_patterns::Vector{ThreeCandlePatternVal{S}}
endIncremental Pattern Detection
All pattern detectors use an incremental (online) approach:
- Minimal State: Each detector maintains only the necessary lookback window (1, 2, or 3 candles)
- Real-time Updates: Patterns are detected as new candles arrive
- Confidence Scoring: Each detected pattern includes a confidence score (0.0 to 1.0)
- Memory Efficient: Uses circular buffers to store historical candles
Example: Streaming Pattern Detection
detector = Doji{OHLCV{Missing,Float64,Missing}}()
for candle in live_candle_stream
fit!(detector, candle)
result = value(detector)
if !ismissing(result) && result.pattern != SingleCandlePatternType.NONE
println("Pattern detected: $(result.pattern)")
println("Confidence: $(result.confidence)")
println("Direction: $(result.direction)")
end
endTips and Best Practices
Use with Context: Patterns are more reliable when considered with market context (trend, volume, support/resistance)
Confidence Scores: Higher confidence scores indicate better pattern fit. Consider using thresholds:
if result.confidence > 0.7 # High-confidence pattern endCombine Patterns: Use
CandlestickPatternDetectorto detect multiple patterns and look for confirmationsPerformance: Individual detectors are faster. Use them if you only need specific patterns
Trend Context: Some patterns (Hammer vs Hanging Man) require trend context for proper interpretation
Complete Example
using OnlineTechnicalIndicators
# Create detector for all patterns
detector = CandlestickPatternDetector{OHLCV{Missing,Float64,Missing}}()
# Simulate streaming data
candles = [
OHLCV(100.0, 105.0, 98.0, 103.0),
OHLCV(103.0, 104.0, 102.0, 103.0), # Doji
OHLCV(100.0, 110.0, 100.0, 110.0), # Marubozu
]
for (i, candle) in enumerate(candles)
fit!(detector, candle)
result = value(detector)
println("After candle $i:")
# Check single-candle patterns
for pattern in result.single_patterns
if pattern.confidence > 0.5
println(" $(pattern.pattern): $(pattern.direction), confidence: $(pattern.confidence)")
end
end
# Check two-candle patterns
for pattern in result.two_patterns
if pattern.confidence > 0.5
println(" $(pattern.pattern): $(pattern.direction), confidence: $(pattern.confidence)")
end
end
# Check three-candle patterns
for pattern in result.three_patterns
if pattern.confidence > 0.5
println(" $(pattern.pattern): $(pattern.direction), confidence: $(pattern.confidence)")
end
end
endSee Also
- OHLCV Data Structure (see Usage documentation)
- Technical Indicators (see Indicators Support documentation)
- Pattern Recognition Examples (see examples directory in repository)