Candlestick
Candlestick patterns detection.
Install / Use
npx skills add cm45t3r/candlestickInstalls into whichever agent you are using.
Quality Score
Category
Development & EngineeringSupported Platforms
Tags
README
Candlestick
A modern, modular JavaScript library for candlestick pattern detection. Detects classic reversal and continuation patterns in OHLC (Open, High, Low, Close) price data, with a clean API and no native dependencies.
- 📊 18 candlestick patterns, 29 variants across single, two, and three-candle formations
- 📦 ESM & CommonJS dual export with full TypeScript definitions
- 🌊 Streaming API for massive datasets (~70% memory reduction)
- 🔌 Plugin system for custom patterns, data validation, pattern metadata
- ✅ Comprehensive test suite with high coverage (run
npm testandnpm run coverage) - 🪶 Zero runtime dependencies
Requires Node.js >= 20
Table of Contents
- Quick Start
- Usage
- Pattern Detection Functions
- High-Level Pattern Chaining
- Examples
- Full Example Files
- Performance
- Development
- Architecture
- Contributing
- Upgrading from v1.x
- FAQ
- Changelog
- Roadmap
- Code of Conduct
- License
Quick Start
Installation
npm install candlestick
CommonJS (Node.js)
const { isHammer, hammer, patternChain, allPatterns } = require("candlestick");
// Check single candle (small body in upper third, long lower shadow, tiny upper shadow)
const candle = { open: 14, high: 15, low: 8, close: 14.5 };
console.log(isHammer(candle)); // true
// Find patterns in series
const candles = [
{ open: 14, high: 15, low: 8, close: 14.5 },
{ open: 13, high: 18, low: 13, close: 13.2 },
{ open: 12, high: 12.5, low: 7, close: 12.1 },
];
console.log(hammer(candles)); // [ 0, 2 ]
// Detect all patterns at once
const results = patternChain(candles, allPatterns);
console.log(results); // [{ index, pattern, match }]
ESM (Modern JavaScript)
import { isHammer, hammer, patternChain, allPatterns } from "candlestick";
const candles = [
{ open: 14, high: 15, low: 8, close: 14.5 },
{ open: 13, high: 18, low: 13, close: 13.2 },
{ open: 12, high: 12.5, low: 7, close: 12.1 },
];
const results = patternChain(candles, allPatterns);
console.log(results);
TypeScript
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 ✓
Usage
Importing
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";
OHLC Format
All functions expect objects with at least:
{
open: Number,
high: Number,
low: Number,
close: Number
}
Extra fields (date, volume, etc.) are preserved unchanged and passed through to every match result, so you can attach any metadata you need:
const data = [
{
date: "2024-01-06",
open: 41490,
high: 41500,
low: 39200,
close: 41500,
volume: 61000,
},
// ...
];
const results = patternChain(data, allPatterns);
console.log(results[0].match[0].date); // "2024-01-06"
console.log(results[0].match[0].volume); // 61000
Pattern Detection Functions
Every pattern has two API styles: a boolean function for checking individual candles, and an array function that scans a series and returns matching indices.
<details> <summary><strong>Boolean (Single/Pair) Detection — returns <code>boolean</code></strong></summary>Single candle:
isHammer(candle)/isBullishHammer(candle)/isBearishHammer(candle)isInvertedHammer(candle)/isBullishInvertedHammer(candle)/isBearishInvertedHammer(candle)isDoji(candle)isMarubozu(candle)/isBullishMarubozu(candle)/isBearishMarubozu(candle)isSpinningTop(candle)/isBullishSpinningTop(candle)/isBearishSpinningTop(candle)
Two candles:
isBullishEngulfing(prev, curr)/isBearishEngulfing(prev, curr)isBullishHarami(prev, curr)/isBearishHarami(prev, curr)isBullishKicker(prev, curr)/isBearishKicker(prev, curr)isHangingMan(prev, curr)/isShootingStar(prev, curr)isPiercingLine(prev, curr)/isDarkCloudCover(prev, curr)isTweezers(prev, curr)/isTweezersTop(prev, curr)/isTweezersBottom(prev, curr)
Three candles:
isMorningStar(c1, c2, c3)/isEveningStar(c1, c2, c3)isThreeWhiteSoldiers(c1, c2, c3)/isThreeBlackCrows(c1, c2, c3)
Single candle:
hammer(dataArray)/bullishHammer(dataArray)/bearishHammer(dataArray)invertedHammer(dataArray)/bullishInvertedHammer(dataArray)/bearishInvertedHammer(dataArray)doji(dataArray)marubozu(dataArray)/bullishMarubozu(dataArray)/bearishMarubozu(dataArray)spinningTop(dataArray)/bullishSpinningTop(dataArray)/bearishSpinningTop(dataArray)
Two candles:
bullishEngulfing(dataArray)/bearishEngulfing(dataArray)bullishHarami(dataArray)/bearishHarami(dataArray)bullishKicker(dataArray)/bearishKicker(dataArray)hangingMan(dataArray)/shootingStar(dataArray)piercingLine(dataArray)/darkCloudCover(dataArray)tweezers(dataArray)/tweezersTop(dataArray)/tweezersBottom(dataArray)
Three candles:
morningStar(dataArray)/eveningStar(dataArray)threeWhiteSoldiers(dataArray)/threeBlackCrows(dataArray)
High-Level Pattern Chaining
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 { patternChain, doji, bullishEngulfing } = require("candlestick");
const matches = patternChain(dataArray, [
{ name: "doji", fn: doji },
{ name: "bullishEngulfing", fn: bullishEngulfing, paramCount: 2 },
]);
Strict Mode
Pass { strict: true } to throw on invalid OHLC data instead of silently skipping:
patternChain(dataArray, allPatterns, { strict: true });
// throws if any candle has high < low, NaN fields, etc.
Multi-candle patterns: Two-candle patterns (Engulfing, Harami, Kicker, Hanging Man, Shooting Star, Piercing Line, Dark Cloud Cover, Tweezers Top/Bottom) return a
matcharray with 2 candles. Three-candle patterns (Morning Star, Evening Star, Three White Soldiers, Three Black Crows) return 3. Single-candle patterns return 1. This is driven by theparamCountproperty on each pattern definition.
Trend-Context Confidence Adjustment
The same candle shape can mean opposite things depending on what preceded it — a small body with a long lower shadow is a bullish hammer after a downtrend, but a bearish hangingMan after an uptrend. By default, pattern functions don't check this: they're evaluated independently, so the identical candle can be flagged as both, with contradictory signals. Each pattern also has a fixed, context-blind confidence in its metadata (e.g. hammer: 0.7) that doesn't distinguish a textbook occurrence from a marginal one.
Pass a trendContext option to patternChain to measure the actual preceding trend and score how well it matches what each pattern expects:
const { patternChain, allPatterns } = require("candlestick");
const { enrichWithMetadata } = require("candlestick").metadata;
const matches = patternChain(data, allPatterns, {
trendContext: { trendMethod: "sma-slope", trendPeriod: 10 },
});
const enriched = enrichWithMetadata(matches);
// Each match now carries a `trendContext` label and a
Related Skills
node-connect
385.5kDiagnose OpenClaw Android, iOS, or macOS node pairing, QR/setup code, route, auth, and connection failures.
blender-python-addon
40.5kBlender Python add-on rules for operators, panels, properties, registration, testing, and API-safe scripting
flutter-development-guidelines-cursorrules-prompt-file
40.5kCursor rules for Flutter development with MVVM architecture, Riverpod state management, Material widgets, and Dart style guidelines.
commit-push-pr
140.6kCommit, push, and open a PR
