A modern, modular JavaScript library for candlestick pattern detection. Detects classic reversal and continuation patterns in OHLC data, with a clean API and no native dependencies.
✨ New in this version (v1.2.0):
- 🎯 19 candlestick patterns, 29 variants (was 16 patterns, +18.75%)
- 📦 ESM & CommonJS support (dual export)
- 🔷 Full TypeScript definitions
- ✅ 306 tests with 99.75% coverage (97.63% branches, 100% functions)
- 🚀 Streaming API for massive datasets (70% memory reduction)
- 🔬 Property-based testing with fast-check
- 🔌 Plugin system for custom patterns
- ✅ Data validation system
- 📊 Pattern metadata (confidence, type, strength)
- 💻 CLI tool for CSV/JSON analysis
- Why Candlestick?
- Features
- Quick Start
- Usage
- Pattern Detection Functions
- High-Level Pattern Chaining
- Pattern Descriptions
- Examples
- Full Example Files
- Linting & Formatting
- Running Tests
- Contributing
- Changelog
- Roadmap
- Code of Conduct
- License
- No native dependencies: 100% JavaScript, works everywhere Node.js runs.
- Modular: Each pattern is its own module, easy to extend or customize.
- Consistent API: All pattern functions use a standard interface.
- Pattern Chaining: Scan for multiple patterns in a single pass.
- Comprehensive Test Suite: Each pattern and utility is unit tested.
- Modern Tooling: Uses ESLint (flat config) and Prettier for code quality and formatting.
- Actively Maintained: See ROADMAP.md and CHANGELOG.md.
- 19 Candlestick Patterns (29 variants): Comprehensive pattern detection library
- Streaming API: Process massive datasets with 70% memory reduction
- Property-Based Testing: Validated with 1000+ generated test cases
- Dual Module Support: CommonJS and ESM exports
- TypeScript: Complete type definitions with IntelliSense
- Data Validation: Robust OHLC validation system
- Plugin System: Register custom patterns
- Pattern Chaining: Multi-pattern detection in single pass
- Zero Dependencies: Pure JavaScript, works everywhere
- Excellent Test Coverage: 306 tests with 99.75% coverage (97.63% branches, 100% functions)
- High Performance: 59K+ candles/sec throughput
- Well Documented: Architecture guides, examples, and API docs
npm install candlestick
const { isHammer, hammer, patternChain, allPatterns } = require("candlestick");
// Check single candle
const candle = { open: 10, high: 15, low: 8, close: 14 };
console.log(isHammer(candle)); // true or false
// Find patterns in series
const candles = [
/* array of OHLC objects */
];
console.log(hammer(candles)); // [indices where pattern found]
// Detect all patterns at once
const results = patternChain(candles, allPatterns);
console.log(results); // [{ index, pattern, match }]
import { isHammer, hammer, patternChain, allPatterns } from "candlestick";
const candles = [
/* array of OHLC objects */
];
const results = patternChain(candles, allPatterns);
console.log(results);
import { OHLC, PatternMatch, patternChain, allPatterns } from "candlestick";
const candles: OHLC[] = [
{ open: 10, high: 15, low: 8, close: 12 },
{ open: 12, high: 16, low: 11, close: 14 },
];
const results: PatternMatch[] = patternChain(candles, allPatterns);
// Full IntelliSense support ✓
CommonJS (Node.js):
// Import all patterns
const candlestick = require("candlestick");
// Or import only what you need
const { isHammer, hammer, patternChain } = require("candlestick");
ESM (Modern JavaScript):
// Import all patterns
import candlestick from "candlestick";
// Or import only what you need (recommended for tree-shaking)
import { isHammer, hammer, patternChain } from "candlestick";
All functions expect objects with at least:
{
open: Number,
high: Number,
low: Number,
close: Number
}
isHammer(candle)
isBullishHammer(candle)
/isBearishHammer(candle)
isInvertedHammer(candle)
isBullishInvertedHammer(candle)
/isBearishInvertedHammer(candle)
isDoji(candle)
isBullishEngulfing(prev, curr)
/isBearishEngulfing(prev, curr)
isBullishHarami(prev, curr)
/isBearishHarami(prev, curr)
isBullishKicker(prev, curr)
/isBearishKicker(prev, curr)
isHangingMan(prev, curr)
isShootingStar(prev, curr)
hammer(dataArray)
/bullishHammer(dataArray)
/bearishHammer(dataArray)
invertedHammer(dataArray)
/bullishInvertedHammer(dataArray)
/bearishInvertedHammer(dataArray)
doji(dataArray)
bullishEngulfing(dataArray)
/bearishEngulfing(dataArray)
bullishHarami(dataArray)
/bearishHarami(dataArray)
bullishKicker(dataArray)
/bearishKicker(dataArray)
hangingMan(dataArray)
/shootingStar(dataArray)
All array functions return an array of indices where the pattern occurs.
Scan a series for multiple patterns in one pass:
const { patternChain, allPatterns } = require("candlestick");
const matches = patternChain(dataArray, allPatterns);
// matches: [
// { index: 3, pattern: 'hammer', match: [candleObj] },
// { index: 7, pattern: 'bullishEngulfing', match: [candleObj, candleObj] },
// ...
// ]
You can also pass a custom list of patterns:
const matches = patternChain(dataArray, [
{ name: "doji", fn: candlestick.doji },
{ name: "bullishEngulfing", fn: candlestick.bullishEngulfing, paramCount: 2 },
]);
Multi-candle patterns: Patterns like Engulfing, Harami, Kicker, Hanging Man, and Shooting Star span two candles. The
match
array in the result will contain both candles (length 2), thanks to theparamCount
property. Single-candle patterns return a single-element array.
- Hammer: Small body near the top (body < 1/3 of range), long lower shadow (tail ≥ 2× body), small upper shadow. Signals possible bullish reversal.
- Inverted Hammer: Small body near the bottom, long upper shadow (wick ≥ 2× body), small lower shadow. Bullish reversal signal.
- Doji: Very small body (body < 10% of range), open ≈ close. Indicates indecision. Candle must have range (high > low).
- Marubozu: Long body (≥ 70% of range) with minimal shadows (< 10% of body). Strong directional move. Bullish Marubozu shows strong buying, Bearish shows strong selling.
- Spinning Top: Small body (< 30% of range) with long upper and lower shadows (each > 20% of range). Indicates market indecision or potential reversal.
- Engulfing: Second candle's body fully engulfs the previous (body range covers previous body). Bullish or bearish.
- Harami: Second candle's body is inside the previous (body range within previous body). Bullish or bearish.
- Kicker: Strong reversal with a gap and opposite color. Bullish or bearish.
- Hanging Man: Bullish candle followed by a bearish hammer with a gap up. Bearish reversal.
- Shooting Star: Bullish candle followed by a bearish inverted hammer with a gap up. Bearish reversal.
- Piercing Line: Bullish reversal. Bearish candle followed by bullish candle that opens below first's low and closes above its midpoint.
- Dark Cloud Cover: Bearish reversal. Bullish candle followed by bearish candle that opens above first's high and closes below its midpoint.
- Tweezers Top: Bearish reversal. Bullish candle followed by bearish candle with matching highs (within 1% tolerance). Indicates resistance level.
- Tweezers Bottom: Bullish reversal. Bearish candle followed by bullish candle with matching lows (within 1% tolerance). Indicates support level.
- Morning Star: Bullish reversal. Long bearish candle, small-bodied star that gaps down, long bullish candle closing well into first candle's body.
- Evening Star: Bearish reversal. Long bullish candle, small-bodied star that gaps up, long bearish candle closing well into first candle's body.
- Three White Soldiers: Three consecutive bullish candles, each opening within previous body and closing higher. Limited upper shadows. Signals strong bullish continuation/reversal.
- Three Black Crows: Three consecutive bearish candles, each opening within previous body and closing lower. Limited lower shadows. Signals strong bearish continuation/reversal.
Note: The library does not mutate your input data. All pattern functions return new objects with precomputed properties (e.g.,
bodyLen
,wickLen
, etc.) as needed. If you plan to run many pattern detectors on the same data, you can precompute properties once usingprecomputeCandleProps
from the utilities for better performance.
const { isBullishKicker, isBearishKicker } = require("candlestick");
const prev = { open: 40.18, high: 41.03, low: 40.09, close: 40.86 };
const curr = { open: 39.61, high: 39.35, low: 38.71, close: 38.92 };
console.log(isBullishKicker(prev, curr)); // false
console.log(isBearishKicker(prev, curr)); // true
const { shootingStar } = require("candlestick");
const data = [
{ open: 29.01, high: 29.03, low: 28.56, close: 28.64 },
// ...
];
console.log(shootingStar(data)); // [index, ...]
const { patternChain, allPatterns } = require("candlestick");
const matches = patternChain(data, allPatterns);
console.log(matches);
// [ { index: 3, pattern: 'hammer', match: [Object] }, ... ]
For processing very large datasets efficiently with reduced memory usage:
const { streaming } = require("candlestick");
// Option 1: Using createStream with callbacks
const stream = streaming.createStream({
patterns: ["hammer", "doji", "marubozu"],
chunkSize: 1000,
onMatch: (match) => console.log(match),
enrichMetadata: true,
});
// Process data in chunks
for (const chunk of dataChunks) {
stream.process(chunk);
}
stream.end();
// Option 2: Simple helper for large datasets
const results = streaming.processLargeDataset(largeData, {
patterns: null, // all patterns
chunkSize: 1000,
enrichMetadata: true,
});
Benefits: Reduces memory usage by ~70% for datasets > 100K candles
const { validateOHLC, validateOHLCArray } = require("candlestick").utils;
// Validate single candle
try {
validateOHLC({ open: 10, high: 15, low: 8, close: 12 });
console.log("Valid candle ✓");
} catch (error) {
console.error("Invalid:", error.message);
}
// Validate array of candles
validateOHLCArray(candles); // throws on invalid data
const { plugins, patternChain } = require('candlestick');
// Register custom pattern
plugins.registerPattern({
name: 'myCustomPattern',
fn: (dataArray) => {
// Your detection logic
return dataArray
.map((c, i) => /* condition */ ? i : -1)
.filter(idx => idx !== -1);
},
paramCount: 1,
metadata: { type: 'reversal', confidence: 0.85 }
});
// Use with patternChain
const customPattern = plugins.getPattern('myCustomPattern');
const results = patternChain(data, [customPattern]);
For more details on the plugin system, see docs/PLUGIN_API.md.
Detect patterns from command line:
# Install globally
npm install -g candlestick
# Detect patterns in JSON file
candlestick -i data.json --output table --metadata
# Filter by confidence
candlestick -i data.csv --confidence 0.85 --output csv
# Bullish reversals only
candlestick -i data.json --type reversal --direction bullish
# Use with pipes
cat data.json | candlestick --output table
For complete CLI documentation, see docs/CLI_GUIDE.md.
See the examples/
directory for runnable, copy-pasteable usage of every pattern and utility:
Single Candle Patterns:
examples/hammer.js
— Hammer pattern detectionexamples/invertedHammer.js
— Inverted Hammer pattern detectionexamples/doji.js
— Doji pattern detection
Two Candle Patterns:
examples/engulfing.js
— Engulfing pattern detectionexamples/harami.js
— Harami pattern detectionexamples/kicker.js
— Kicker pattern detectionexamples/reversal.js
— Hanging Man and Shooting Star
Multi-Pattern Detection:
examples/patternChain.js
— Multi-pattern detection with patternChainexamples/newPatterns.js
— 3-candle patterns (Morning/Evening Star, Three Soldiers/Crows)examples/newPatternsV2.js
— v1.2.0 patterns (Marubozu, Spinning Top, Tweezers)examples/streaming.js
— Streaming API for large datasetsexamples/esm-example.mjs
— ESM module syntax exampleexamples/metadata.js
— Pattern metadata, filtering, and sorting
Utilities:
examples/utils.js
— Utility functions: bodyLen, wickLen, tailLen, isBullish, isBearish, hasGapUp, hasGapDown, findPattern
See examples/README.md
for more details and instructions.
- ESLint: Modern flat config (
eslint.config.js
) - Prettier: For code formatting
- Run
npm run lint
andnpm run format
(if configured)
npm test
- Please open issues or pull requests for bugs, features, or questions.
- Add tests for new patterns or utilities.
- Follow the code style enforced by ESLint and Prettier.
- See CONTRIBUTING.md for full guidelines.
See CHANGELOG.md for release history and major changes.
Latest (v1.2.0):
- 3 new candlestick patterns (Marubozu, Spinning Top, Tweezers)
- Streaming API for large datasets (70% memory reduction)
- Property-based testing with fast-check
- 306 tests with 99.75% coverage
- Quality badges (Bundle Size, Snyk, Last Commit)
Previous (v1.1.0):
- 6 new candlestick patterns (3-candle patterns, Piercing Line, Dark Cloud Cover)
- ESM support (dual CommonJS/ESM)
- TypeScript definitions
- Plugin system, Data validation, Pattern metadata system, CLI tool
Q: Why is my pattern not detected?
- Ensure your candle objects have all required fields (
open
,high
,low
,close
). - Check that the pattern’s technical thresholds are met (see Pattern Descriptions above).
- The library does not check for trend context (e.g., uptrend/downtrend) — it only looks at candle shapes.
Q: Does this library mutate my data?
- No. All computations are done on copies; your input data is never changed.
Q: Can I use this with TypeScript?
- Yes! The library now includes complete TypeScript definitions in
types/index.d.ts
. Full type safety and IntelliSense support available.
Q: Are there visual examples of patterns?
- Not yet, but this is planned (see ROADMAP.md). For now, see the pattern descriptions and links to external resources.
See ROADMAP.md for planned features and future directions.
See CODE_OF_CONDUCT.md for community standards and enforcement.
MIT. See LICENSE.