meridianalgo-js
Version:
Advanced algorithmic trading library for Node.js & TypeScript with 100+ technical indicators, pattern recognition, and risk management tools.
473 lines • 16.9 kB
JavaScript
"use strict";
/**
* Candlestick Pattern Recognition
*
* This module provides candlestick pattern recognition capabilities for
* technical analysis including doji, hammer, engulfing patterns, and more.
*
* @fileoverview Candlestick pattern recognition for technical analysis
* @author MeridianAlgo
* @version 1.0.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.PatternRecognition = exports.detectAllPatterns = exports.detectThreeBlackCrows = exports.detectThreeWhiteSoldiers = exports.detectBearishHarami = exports.detectBullishHarami = exports.detectEveningStar = exports.detectMorningStar = exports.detectBearishEngulfing = exports.detectBullishEngulfing = exports.detectShootingStar = exports.detectHammer = exports.detectDoji = void 0;
/**
* Calculate the body size of a candlestick
*/
function getBodySize(candle) {
return Math.abs(candle.close - candle.open);
}
/**
* Calculate the upper shadow size of a candlestick
*/
function getUpperShadow(candle) {
return candle.high - Math.max(candle.open, candle.close);
}
/**
* Calculate the lower shadow size of a candlestick
*/
function getLowerShadow(candle) {
return Math.min(candle.open, candle.close) - candle.low;
}
/**
* Calculate the total range of a candlestick
*/
function getTotalRange(candle) {
return candle.high - candle.low;
}
/**
* Check if a candlestick is bullish (close > open)
*/
function isBullish(candle) {
return candle.close > candle.open;
}
/**
* Check if a candlestick is bearish (close < open)
*/
function isBearish(candle) {
return candle.close < candle.open;
}
/**
* Doji Pattern
*
* A doji occurs when the open and close prices are very close or equal,
* indicating indecision in the market.
*
* @param candle - Candlestick data
* @param threshold - Threshold for body size relative to total range (default: 0.1)
* @returns Pattern result if doji is detected
*/
function detectDoji(candle, threshold = 0.1) {
const bodySize = getBodySize(candle);
const totalRange = getTotalRange(candle);
if (totalRange === 0)
return null;
const bodyRatio = bodySize / totalRange;
if (bodyRatio <= threshold) {
return {
pattern: 'Doji',
bullish: false,
bearish: false,
confidence: 1 - bodyRatio,
description: 'Indecision in the market, potential reversal signal'
};
}
return null;
}
exports.detectDoji = detectDoji;
/**
* Hammer Pattern
*
* A hammer is a bullish reversal pattern with a small body at the top
* and a long lower shadow, indicating potential upward reversal.
*
* @param candle - Candlestick data
* @param threshold - Threshold for shadow ratio (default: 2)
* @returns Pattern result if hammer is detected
*/
function detectHammer(candle, threshold = 2) {
const bodySize = getBodySize(candle);
const lowerShadow = getLowerShadow(candle);
const upperShadow = getUpperShadow(candle);
const totalRange = getTotalRange(candle);
if (totalRange === 0)
return null;
const bodyRatio = bodySize / totalRange;
const lowerShadowRatio = lowerShadow / totalRange;
const upperShadowRatio = upperShadow / totalRange;
if (bodyRatio <= 0.3 && lowerShadowRatio >= 0.6 && upperShadowRatio <= 0.1) {
return {
pattern: 'Hammer',
bullish: true,
bearish: false,
confidence: lowerShadowRatio,
description: 'Bullish reversal pattern, potential upward movement'
};
}
return null;
}
exports.detectHammer = detectHammer;
/**
* Shooting Star Pattern
*
* A shooting star is a bearish reversal pattern with a small body at the bottom
* and a long upper shadow, indicating potential downward reversal.
*
* @param candle - Candlestick data
* @param threshold - Threshold for shadow ratio (default: 2)
* @returns Pattern result if shooting star is detected
*/
function detectShootingStar(candle, threshold = 2) {
const bodySize = getBodySize(candle);
const lowerShadow = getLowerShadow(candle);
const upperShadow = getUpperShadow(candle);
const totalRange = getTotalRange(candle);
if (totalRange === 0)
return null;
const bodyRatio = bodySize / totalRange;
const lowerShadowRatio = lowerShadow / totalRange;
const upperShadowRatio = upperShadow / totalRange;
if (bodyRatio <= 0.3 && upperShadowRatio >= 0.6 && lowerShadowRatio <= 0.1) {
return {
pattern: 'Shooting Star',
bullish: false,
bearish: true,
confidence: upperShadowRatio,
description: 'Bearish reversal pattern, potential downward movement'
};
}
return null;
}
exports.detectShootingStar = detectShootingStar;
/**
* Engulfing Pattern (Bullish)
*
* A bullish engulfing pattern occurs when a small bearish candle is followed
* by a larger bullish candle that completely engulfs the previous candle.
*
* @param prevCandle - Previous candlestick
* @param currentCandle - Current candlestick
* @returns Pattern result if bullish engulfing is detected
*/
function detectBullishEngulfing(prevCandle, currentCandle) {
if (!isBearish(prevCandle) || !isBullish(currentCandle))
return null;
const prevBodySize = getBodySize(prevCandle);
const currentBodySize = getBodySize(currentCandle);
if (currentBodySize > prevBodySize &&
currentCandle.open < prevCandle.close &&
currentCandle.close > prevCandle.open) {
return {
pattern: 'Bullish Engulfing',
bullish: true,
bearish: false,
confidence: Math.min(currentBodySize / prevBodySize, 3),
description: 'Bullish reversal pattern, strong buying pressure'
};
}
return null;
}
exports.detectBullishEngulfing = detectBullishEngulfing;
/**
* Engulfing Pattern (Bearish)
*
* A bearish engulfing pattern occurs when a small bullish candle is followed
* by a larger bearish candle that completely engulfs the previous candle.
*
* @param prevCandle - Previous candlestick
* @param currentCandle - Current candlestick
* @returns Pattern result if bearish engulfing is detected
*/
function detectBearishEngulfing(prevCandle, currentCandle) {
if (!isBullish(prevCandle) || !isBearish(currentCandle))
return null;
const prevBodySize = getBodySize(prevCandle);
const currentBodySize = getBodySize(currentCandle);
if (currentBodySize > prevBodySize &&
currentCandle.open > prevCandle.close &&
currentCandle.close < prevCandle.open) {
return {
pattern: 'Bearish Engulfing',
bullish: false,
bearish: true,
confidence: Math.min(currentBodySize / prevBodySize, 3),
description: 'Bearish reversal pattern, strong selling pressure'
};
}
return null;
}
exports.detectBearishEngulfing = detectBearishEngulfing;
/**
* Morning Star Pattern
*
* A morning star is a three-candle bullish reversal pattern consisting of
* a long bearish candle, a small body candle (doji), and a long bullish candle.
*
* @param candles - Array of three candlesticks
* @returns Pattern result if morning star is detected
*/
function detectMorningStar(candles) {
if (candles.length !== 3)
return null;
const [first, second, third] = candles;
if (!isBearish(first) || !isBullish(third))
return null;
const firstBodySize = getBodySize(first);
const secondBodySize = getBodySize(second);
const thirdBodySize = getBodySize(third);
const firstRange = getTotalRange(first);
const secondRange = getTotalRange(second);
if (firstBodySize / firstRange >= 0.6 &&
secondBodySize / secondRange <= 0.3 &&
thirdBodySize >= firstBodySize * 0.5) {
return {
pattern: 'Morning Star',
bullish: true,
bearish: false,
confidence: Math.min(thirdBodySize / firstBodySize, 2),
description: 'Strong bullish reversal pattern, three-candle formation'
};
}
return null;
}
exports.detectMorningStar = detectMorningStar;
/**
* Evening Star Pattern
*
* An evening star is a three-candle bearish reversal pattern consisting of
* a long bullish candle, a small body candle (doji), and a long bearish candle.
*
* @param candles - Array of three candlesticks
* @returns Pattern result if evening star is detected
*/
function detectEveningStar(candles) {
if (candles.length !== 3)
return null;
const [first, second, third] = candles;
if (!isBullish(first) || !isBearish(third))
return null;
const firstBodySize = getBodySize(first);
const secondBodySize = getBodySize(second);
const thirdBodySize = getBodySize(third);
const firstRange = getTotalRange(first);
const secondRange = getTotalRange(second);
if (firstBodySize / firstRange >= 0.6 &&
secondBodySize / secondRange <= 0.3 &&
thirdBodySize >= firstBodySize * 0.5) {
return {
pattern: 'Evening Star',
bullish: false,
bearish: true,
confidence: Math.min(thirdBodySize / firstBodySize, 2),
description: 'Strong bearish reversal pattern, three-candle formation'
};
}
return null;
}
exports.detectEveningStar = detectEveningStar;
/**
* Harami Pattern (Bullish)
*
* A bullish harami is a two-candle pattern where a small bullish candle
* is contained within the body of the previous large bearish candle.
*
* @param prevCandle - Previous candlestick
* @param currentCandle - Current candlestick
* @returns Pattern result if bullish harami is detected
*/
function detectBullishHarami(prevCandle, currentCandle) {
if (!isBearish(prevCandle) || !isBullish(currentCandle))
return null;
const prevBodySize = getBodySize(prevCandle);
const currentBodySize = getBodySize(currentCandle);
if (currentBodySize < prevBodySize * 0.5 &&
currentCandle.open > prevCandle.close &&
currentCandle.close < prevCandle.open) {
return {
pattern: 'Bullish Harami',
bullish: true,
bearish: false,
confidence: 1 - (currentBodySize / prevBodySize),
description: 'Bullish reversal pattern, indecision after bearish move'
};
}
return null;
}
exports.detectBullishHarami = detectBullishHarami;
/**
* Harami Pattern (Bearish)
*
* A bearish harami is a two-candle pattern where a small bearish candle
* is contained within the body of the previous large bullish candle.
*
* @param prevCandle - Previous candlestick
* @param currentCandle - Current candlestick
* @returns Pattern result if bearish harami is detected
*/
function detectBearishHarami(prevCandle, currentCandle) {
if (!isBullish(prevCandle) || !isBearish(currentCandle))
return null;
const prevBodySize = getBodySize(prevCandle);
const currentBodySize = getBodySize(currentCandle);
if (currentBodySize < prevBodySize * 0.5 &&
currentCandle.open < prevCandle.close &&
currentCandle.close > prevCandle.open) {
return {
pattern: 'Bearish Harami',
bullish: false,
bearish: true,
confidence: 1 - (currentBodySize / prevBodySize),
description: 'Bearish reversal pattern, indecision after bullish move'
};
}
return null;
}
exports.detectBearishHarami = detectBearishHarami;
/**
* Three White Soldiers Pattern
*
* Three white soldiers is a bullish continuation pattern consisting of
* three consecutive long bullish candles with higher closes.
*
* @param candles - Array of three candlesticks
* @returns Pattern result if three white soldiers is detected
*/
function detectThreeWhiteSoldiers(candles) {
if (candles.length !== 3)
return null;
const [first, second, third] = candles;
if (!isBullish(first) || !isBullish(second) || !isBullish(third))
return null;
const firstBodySize = getBodySize(first);
const secondBodySize = getBodySize(second);
const thirdBodySize = getBodySize(third);
const firstRange = getTotalRange(first);
const secondRange = getTotalRange(second);
const thirdRange = getTotalRange(third);
if (firstBodySize / firstRange >= 0.6 &&
secondBodySize / secondRange >= 0.6 &&
thirdBodySize / thirdRange >= 0.6 &&
second.close > first.close &&
third.close > second.close) {
return {
pattern: 'Three White Soldiers',
bullish: true,
bearish: false,
confidence: Math.min(thirdBodySize / firstBodySize, 2),
description: 'Strong bullish continuation pattern, three consecutive bullish candles'
};
}
return null;
}
exports.detectThreeWhiteSoldiers = detectThreeWhiteSoldiers;
/**
* Three Black Crows Pattern
*
* Three black crows is a bearish continuation pattern consisting of
* three consecutive long bearish candles with lower closes.
*
* @param candles - Array of three candlesticks
* @returns Pattern result if three black crows is detected
*/
function detectThreeBlackCrows(candles) {
if (candles.length !== 3)
return null;
const [first, second, third] = candles;
if (!isBearish(first) || !isBearish(second) || !isBearish(third))
return null;
const firstBodySize = getBodySize(first);
const secondBodySize = getBodySize(second);
const thirdBodySize = getBodySize(third);
const firstRange = getTotalRange(first);
const secondRange = getTotalRange(second);
const thirdRange = getTotalRange(third);
if (firstBodySize / firstRange >= 0.6 &&
secondBodySize / secondRange >= 0.6 &&
thirdBodySize / thirdRange >= 0.6 &&
second.close < first.close &&
third.close < second.close) {
return {
pattern: 'Three Black Crows',
bullish: false,
bearish: true,
confidence: Math.min(thirdBodySize / firstBodySize, 2),
description: 'Strong bearish continuation pattern, three consecutive bearish candles'
};
}
return null;
}
exports.detectThreeBlackCrows = detectThreeBlackCrows;
/**
* Detect all patterns in a series of candlesticks
*
* @param candles - Array of candlestick data
* @returns Array of detected patterns
*/
function detectAllPatterns(candles) {
const patterns = [];
for (let i = 0; i < candles.length; i++) {
const currentCandle = candles[i];
// Single candle patterns
const doji = detectDoji(currentCandle);
if (doji)
patterns.push(doji);
const hammer = detectHammer(currentCandle);
if (hammer)
patterns.push(hammer);
const shootingStar = detectShootingStar(currentCandle);
if (shootingStar)
patterns.push(shootingStar);
// Two candle patterns
if (i > 0) {
const prevCandle = candles[i - 1];
const bullishEngulfing = detectBullishEngulfing(prevCandle, currentCandle);
if (bullishEngulfing)
patterns.push(bullishEngulfing);
const bearishEngulfing = detectBearishEngulfing(prevCandle, currentCandle);
if (bearishEngulfing)
patterns.push(bearishEngulfing);
const bullishHarami = detectBullishHarami(prevCandle, currentCandle);
if (bullishHarami)
patterns.push(bullishHarami);
const bearishHarami = detectBearishHarami(prevCandle, currentCandle);
if (bearishHarami)
patterns.push(bearishHarami);
}
// Three candle patterns
if (i >= 2) {
const threeCandles = candles.slice(i - 2, i + 1);
const morningStar = detectMorningStar(threeCandles);
if (morningStar)
patterns.push(morningStar);
const eveningStar = detectEveningStar(threeCandles);
if (eveningStar)
patterns.push(eveningStar);
const threeWhiteSoldiers = detectThreeWhiteSoldiers(threeCandles);
if (threeWhiteSoldiers)
patterns.push(threeWhiteSoldiers);
const threeBlackCrows = detectThreeBlackCrows(threeCandles);
if (threeBlackCrows)
patterns.push(threeBlackCrows);
}
}
return patterns;
}
exports.detectAllPatterns = detectAllPatterns;
/**
* Collection of candlestick pattern recognition functions
*/
exports.PatternRecognition = {
detectDoji,
detectHammer,
detectShootingStar,
detectBullishEngulfing,
detectBearishEngulfing,
detectMorningStar,
detectEveningStar,
detectBullishHarami,
detectBearishHarami,
detectThreeWhiteSoldiers,
detectThreeBlackCrows,
detectAllPatterns
};
//# sourceMappingURL=patterns.js.map