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.
- 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.
- Modular pattern logic
- Consistent, easy-to-use API
- Pattern chaining for multi-pattern scans
- 100% test coverage, CI/CD ready
- Modern code style and documentation
npm install candlestick
const { isHammer, hammer, patternChain } = require('candlestick');
const candle = { open: 10, high: 15, low: 8, close: 14 };
console.log(isHammer(candle)); // true or false
const candles = [/* array of OHLC objects */];
console.log(hammer(candles)); // [indices]
const results = patternChain(candles);
console.log(results); // [{ index, pattern, match }]
// Import all patterns (CommonJS)
const candlestick = require('candlestick');
// Or import only what you need (recommended for tree-shaking in ESM)
const { isHammer, hammer, patternChain } = require('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).
- 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.
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] }, ... ]
See the examples/
directory for runnable, copy-pasteable usage of every pattern and utility:
examples/hammer.js
— Hammer pattern detectionexamples/invertedHammer.js
— Inverted Hammer pattern detectionexamples/doji.js
— Doji pattern detectionexamples/engulfing.js
— Engulfing pattern detectionexamples/harami.js
— Harami pattern detectionexamples/kicker.js
— Kicker pattern detectionexamples/reversal.js
— Hanging Man and Shooting Starexamples/patternChain.js
— Multi-pattern detection with patternChainexamples/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.
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?
- The library is written in JS, but JSDoc comments provide some type hints. TypeScript support is planned (see ROADMAP.md).
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.