npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

candlestick

v2.0.1

Published

JavaScript library for candlestick patterns detection.

Downloads

2,219

Readme

Candlestick

Node.js CI workflow npm npm downloads Bundle Size Coverage Status ESLint code style: prettier Socket Badge License: MIT PRs Welcome Contributors Last Commit

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.

✨ Highlights:

  • 🎯 18 candlestick patterns, 29 variants across single, two, and three-candle formations
  • 📦 ESM & CommonJS support (dual export)
  • 🔷 Full TypeScript definitions with IntelliSense
  • ✅ 347 tests — 99.75% line coverage, 100% function coverage
  • 🚀 Streaming API for massive datasets (~70% memory reduction)
  • 🔬 Property-based testing with fast-check (1000+ generated scenarios)
  • 🔌 Plugin system for custom patterns
  • ✅ Data validation (validateOHLC, validateOHLCArray)
  • 📊 Pattern metadata (confidence, strength, type, direction)
  • 💻 CLI tool for CSV/JSON analysis

Table of Contents


Why Candlestick?

  • 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.

Features

  • 18 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: 347 tests with 99.75% coverage (97.63% branches, 100% functions)
  • High Performance: 59K+ candles/sec throughput
  • Well Documented: Architecture guides, examples, and API docs

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 = [
  /* 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 }]

ESM (Modern JavaScript)

import { isHammer, hammer, patternChain, allPatterns } from "candlestick";

const candles = [
  /* array of OHLC objects */
];
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

Boolean (Single/Pair) Detection

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)

Array (Series) Detection

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)

All array functions return an array of indices where the pattern occurs.


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 match array 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 the paramCount property on each pattern definition.


Pattern Descriptions

Single Candle Patterns

  • 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.

Two Candle Patterns

  • 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: Opposite-color candles with a body gap between them (second body does not overlap first body). The second candle must not be a Hammer or Inverted Hammer shape. 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 (body ≥ 50% of range) followed by bullish candle (body ≥ 50% of range) that opens below first's low, closes above the first body's midpoint but below the first body's top (i.e., does not fully engulf).
  • Dark Cloud Cover: Bearish reversal. Bullish candle (body ≥ 50% of range) followed by bearish candle (body ≥ 50% of range) that opens above first's high, closes below the first body's midpoint but above the first body's bottom (i.e., does not fully engulf).
  • Tweezers Top: Bearish reversal. Bullish candle followed by bearish candle with matching highs (within 1% of the candles' average range). Both candles must have significant bodies (≥ 40% of their range). Indicates resistance level.
  • Tweezers Bottom: Bullish reversal. Bearish candle followed by bullish candle with matching lows (within 1% of the candles' average range). Both candles must have significant bodies (≥ 40% of their range). Indicates support level.

Three Candle Patterns

  • Morning Star: Bullish reversal. Long bearish candle (body ≥ 60% of range), small-bodied star (body ≤ 30% of range) whose body gaps down from the first candle's body, long bullish candle (body ≥ 60% of range) closing above the midpoint of the first candle's body.
  • Evening Star: Bearish reversal. Long bullish candle (body ≥ 60% of range), small-bodied star (body ≤ 30% of range) whose body gaps up from the first candle's body, long bearish candle (body ≥ 60% of range) closing below the midpoint of the first candle's body.
  • Three White Soldiers: Three consecutive bullish candles, each opening within the previous body and closing higher. Each body ≥ 60% of its candle's range; upper shadows ≤ 30% of body. Signals strong bullish continuation/reversal.
  • Three Black Crows: Three consecutive bearish candles, each opening within the previous body and closing lower. Each body ≥ 60% of its candle's range; lower shadows ≤ 30% of body. Signals strong bearish continuation/reversal.

Note: The library does not mutate your input data. Pattern functions return arrays of indices; precomputeCandleProps returns new enriched candle objects. If you call individual pattern series functions (e.g., hammer(), doji()) multiple times on the same raw array, precompute once for better performance (see below). When using patternChain, precomputation is handled internally and no manual call is needed.

Performance: precomputeCandleProps

When calling multiple pattern functions on the same dataset, use precomputeCandleProps to compute bodyLen, wickLen, tailLen, isBullish, isBearish, and bodyEnds once instead of repeatedly:

const { hammer, doji, utils } = require("candlestick");

// Without precomputation: each function enriches the raw array independently.
// With precomputation: props are computed once and reused across all calls.
const precomputed = utils.precomputeCandleProps(data);

const hammers = hammer(precomputed);
const dojis = doji(precomputed);
// Extra fields (date, volume) are preserved in the enriched objects.

This is useful when calling individual series functions on the same dataset multiple times. patternChain already handles precomputation internally via ensurePrecomputed, so no manual call is needed there.


Examples

Boolean Detection

const { isBullishKicker, isBearishKicker } = require("candlestick");

// Bullish candle, then bearish candle gapping down → bearish kicker
const prev = { open: 40, high: 41, low: 39.5, close: 40.8 };
const curr = { open: 39.5, high: 39.8, low: 38.5, close: 38.9 };

console.log(isBullishKicker(prev, curr)); // false
console.log(isBearishKicker(prev, curr)); // true

Finding Patterns in Series

const { shootingStar } = require("candlestick");

const data = [
  { open: 29.01, high: 29.03, low: 28.56, close: 28.64 },
  // ...
];

console.log(shootingStar(data)); // [index, ...]

Pattern Chaining

const { patternChain, allPatterns } = require("candlestick");
const matches = patternChain(data, allPatterns);
console.log(matches);
// [ { index: 3, pattern: 'hammer', match: [Object] }, ... ]

Streaming API

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

Data Validation

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

Plugin System

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.

CLI Tool

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.


Full Example Files

See the examples/ directory for runnable, copy-pasteable usage of every pattern and utility:

Single Candle Patterns:

Two Candle Patterns:

Multi-Pattern Detection:

Utilities:

  • examples/utils.js — Utility functions: bodyLen, wickLen, tailLen, isBullish, isBearish, hasGapUp, hasGapDown, findPattern
  • examples/real-data.js — Real market data with date/volume fields, precomputeCandleProps, gap detection, and frequency breakdown

See examples/README.md for more details and instructions.


Linting & Formatting

  • ESLint: Modern flat config (eslint.config.js)
  • Prettier: For code formatting
  • Run npm run lint and npm run format

Running Tests

npm test

Contributing

  • 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.

Changelog

See CHANGELOG.md for release history and major changes.

Latest (v2.0.1):

  • BREAKING: Drop Node.js 18 support, require Node.js >= 20
  • Upgrade @eslint/js to v10, c8 to v11
  • Error chain preservation ({ cause }) in validateOHLCArray

Previous (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
  • 347 tests with 99.75% coverage

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

FAQ

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 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 section above.

Roadmap

See ROADMAP.md for planned features and future directions.


Code of Conduct

See CODE_OF_CONDUCT.md for community standards and enforcement.


License

MIT. See LICENSE.