Py-CandleKit
A lightweight, pandas-friendly Python library for detecting candlestick patterns in financial time-series data.
✨ Features
- 20+ Classic Patterns: Detect Hammer, Engulfing, Morning Star, and more
- Pandas Integration: Works directly with pandas DataFrames (OHLC format)
- Clear Classification: Bullish/bearish/neutral signal identification
- Academic Foundation: Based on Nison's "Japanese Candlestick Charting Techniques"
- Production Ready: Comprehensive testing and type hints
- Easy Extension: Simple API for adding custom patterns
📊 Supported Patterns
Single-Candle Patterns
- Doji - Indecision (neutral)
- Hammer - Bullish reversal after downtrend
- Shooting Star - Bearish reversal after uptrend
- Bullish/Bearish Marubozu - Strong conviction with minimal shadows
- Bullish/Bearish Belt Hold - Strong opening at extreme
Two-Candle Patterns
- Bullish/Bearish Engulfing - Reversal patterns
- Piercing Line / Dark Cloud Cover - Counter-trend reversals
- Harami Cross - Reversal with doji
- Kicking - Reversal with marubozu gap
Three-Candle Patterns
- Morning/Evening Star - Classic reversal patterns
- Morning/Evening Doji Star - Reversal with doji confirmation
- Three White Soldiers - Strong bullish continuation
- Three Black Crows - Strong bearish continuation
- Three Inside/Outside Up - Bullish reversal variations
Five-Candle Patterns
- Rising/Falling Three Methods - Continuation patterns
- Mat Hold - Bullish continuation with pullback
📦 Installation
pip install py-candlekit
🚀 Quick Start
import pandas as pd
from candlekit import scan_symbol_df, CandlePatterns
# Your OHLC data (lowercase column names required)
data = {
'open': [100, 102, 101, 103, 105],
'high': [103, 104, 102, 106, 107],
'low': [99, 101, 100, 102, 104],
'close': [102, 101, 102, 105, 106]
}
df = pd.DataFrame(data)
# Scan for all patterns
results_df = scan_symbol_df(df)
print(results_df)
Output:
index pattern_name signal_type candles
0 1 Hammer bullish 1
1 3 Bullish Engulfing bullish 2
📚 Basic Usage
Detect Specific Pattern
from candlekit import detect_pattern_at_index
# Check if index 1 is a Hammer
is_hammer = detect_pattern_at_index(CandlePatterns.Hammer, df, index=1)
print(f"Hammer detected: {is_hammer}") # True
Get Results as List
from candlekit import scan_symbol
results_list = scan_symbol(df)
# Returns: [(1, 'Hammer', 'bullish'), (3, 'BullishEngulfing', 'bullish')]
Scan Specific Patterns Only
# Scan only for reversal patterns
reversal_patterns = [
CandlePatterns.Hammer,
CandlePatterns.ShootingStar,
CandlePatterns.BullishEngulfing,
CandlePatterns.MorningStar
]
results = scan_symbol_df(df, patterns=reversal_patterns)
🔧 Working with Real Data
Using yfinance (Optional)
import yfinance as yf
from candlekit import scan_symbol_df
# Download data
ticker = yf.Ticker("AAPL")
df = ticker.history(period="1mo", interval="1d")
# Ensure correct column names
df.columns = [col.lower() for col in df.columns]
# Scan for patterns
patterns = scan_symbol_df(df)
# Filter recent bullish patterns
recent_bullish = patterns[
(patterns['signal_type'] == 'bullish') &
(patterns['index'] > len(df) - 5)
]
Using CSV Data
import pandas as pd
from candlekit import scan_symbol_df
# Load from CSV (ensure column names match)
df = pd.read_csv('your_data.csv')
df.columns = ['open', 'high', 'low', 'close', 'volume'] # Rename if needed
# Scan for patterns
results = scan_symbol_df(df)
⚙️ Advanced Configuration
Custom Pattern Parameters
# Adjust sensitivity for Doji detection
detect_pattern_at_index(
CandlePatterns.Doji,
df,
index=0,
max_body_ratio=0.15 # Default: 0.1
)
# Custom Hammer parameters
detect_pattern_at_index(
CandlePatterns.Hammer,
df,
index=1,
max_body_ratio=0.3, # Default: 0.25
min_lower_wick_to_body=1.5, # Default: 2.0
max_upper_wick_ratio=0.4 # Default: 0.33
)
Pattern-Specific Parameters
Each pattern has sensible defaults, but you can adjust:
max_body_ratio: Maximum body-to-total-length ratio (for thin candles)min_body_ratio: Minimum body-to-total-length ratio (for thick candles)min_lower_wick_to_body: For Hammer patternmin_upper_wick_to_body: For Shooting Star pattern
🧠 Understanding CandleStick Objects
The library uses CandleStick objects internally. You can access their properties:
from candlekit.src.candlekit.entity import CandleStick
candle = CandleStick(df, index=0)
print(f"Body length: {candle.body_length}")
print(f"Top wick: {candle.top_wick}")
print(f"Bottom wick: {candle.bottom_wick}")
print(f"Body ratio: {candle.body_ratio:.2%}")
print(f"Is bullish: {candle.is_bullish}")
📊 Complete Pattern List
Access All Patterns
from candlekit import CandlePatterns
# List all available patterns
for pattern in CandlePatterns:
print(f"{pattern.pattern_name}: {pattern.signal_type} ({pattern.candles} candle(s))")
Pattern Categories
# Single-candle patterns
single_candle = [p for p in CandlePatterns if p.candles == 1]
# Multi-candle patterns
multi_candle = [p for p in CandlePatterns if p.candles > 1]
# Bullish patterns
bullish = [p for p in CandlePatterns if p.signal_type == 'bullish']
# Bearish patterns
bearish = [p for p in CandlePatterns if p.signal_type == 'bearish']
🧪 Testing & Quality
Run Tests
# Install test dependencies
pip install pytest
# Run all tests
python -m pytest
# Run specific test file
python -m pytest tests/test_patterns.py -v
# Run with coverage
python -m pytest --cov=candlekit tests/
Example Test
import pytest
import pandas as pd
from candlekit import detect_pattern_at_index, CandlePatterns
def test_hammer_detection():
"""Test Hammer pattern detection"""
df = pd.DataFrame({
'open': [100],
'high': [105],
'low': [95],
'close': [99]
})
# This is NOT a hammer (body too large relative to wick)
result = detect_pattern_at_index(CandlePatterns.Hammer, df, index=0)
assert result == False
# This IS a hammer
df = pd.DataFrame({
'open': [95],
'high': [98],
'low': [80],
'close': [96]
})
result = detect_pattern_at_index(CandlePatterns.Hammer, df, index=0)
assert result == True
🛠️ Development
Setup Development Environment
# Clone and install
git clone https://github.com/zhirodadkhah/candlekit.git
cd candlekit
pip install -e ".[dev]"
# Run code quality tools
flake8 src/candlekit # Linting
black src/candlekit # Formatting
mypy src/candlekit # Type checking
Adding New Patterns
- Add detection function in
patterns.py - Add to
CandlePatternsenum inutils.py - Write comprehensive tests
Example:
# In patterns.py
def is_tweezers_top(candle1: CandleStick, candle2: CandleStick) -> bool:
"""Detect Tweezer Top pattern."""
return (
candle1.high == candle2.high and
candle1.is_bullish and
not candle2.is_bullish
)
# In utils.py
CandlePatterns.TweezerTop = (2, is_tweezers_top, "bearish", "Tweezer Top")
📖 Pattern References & Methodology
All patterns are implemented according to Steve Nison's "Japanese Candlestick Charting Techniques, 2nd Edition". Each pattern function includes page references to the textbook.
Key Concepts
- Body Ratio:
body_length / total_length- measures conviction - Window Gap: Price gap between candles with no overlap
- Engulfment: Current candle's body completely contains previous
- Containment: Candle's body is within another's range
Academic Sources
- Nison, S. (2001). Japanese Candlestick Charting Techniques
- Bulkowski, T. N. (2005). Encyclopedia of Candlestick Charts
- Morris, G. L. (1995). Candlestick Charting Explained
🤝 Contributing
We welcome contributions! Please:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-pattern - Add tests for new functionality
- Ensure tests pass:
pytest - Update documentation as needed
- Submit a Pull Request
Contribution Ideas
- Add more candlestick patterns
- Improve performance for large datasets
- Add visualization helpers
- Create Jupyter notebook examples
- Add pattern combination analysis
🙏 Acknowledgments
- Steve Nison for bringing candlestick analysis to markets
- The pandas and numpy communities
- All contributors and users of this library
- Financial analysts and quants who provided feedback
⚠️ Disclaimer
IMPORTANT: This library is for educational and research purposes only.
- Trading involves substantial risk of loss
- Past performance is not indicative of future results
- Always conduct your own research and consult financial advisors
- The authors are not responsible for any trading losses
Use this tool as part of a comprehensive trading strategy, not as standalone advice.
Happy analyzing! 📈
Found a bug or have a feature request? Please open an issue on GitHub!
Metadata
Release files for py-candlekit 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| py_candlekit-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Release files / py_candlekit-1.0.1-py3-none-any.whl
| Download URL | py_candlekit-1.0.1-py3-none-any.whl |
|---|---|
| Size | 22.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d7497b61b367a844d3e15ce335a351460c35784c85e3c868e1e97497deb7c2b5
|
|
BLAKE2b-256 checksum How to use checksums |
47aec6e0f7a6b84769a5a11c715f6187cbeae8f11052a9303d2ecff0debe67db
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|