UNPKG

@thuantan2060/technicalindicators

Version:
104 lines (91 loc) 4.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.DEFAULT_GRAVESTONE_DOJI_CONFIG = void 0; exports.gravestonedoji = gravestonedoji; var _CandlestickFinder = _interopRequireWildcard(require("./CandlestickFinder")); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /** * Configuration interface for GraveStoneDoji pattern. * Includes thresholds for upper shadow analysis. */ /** * Default configuration for GraveStoneDoji pattern. */ const DEFAULT_GRAVESTONE_DOJI_CONFIG = exports.DEFAULT_GRAVESTONE_DOJI_CONFIG = { ..._CandlestickFinder.DEFAULT_CANDLESTICK_CONFIG, minAbsoluteUpperShadowThreshold: 0.04 }; class GraveStoneDoji extends _CandlestickFinder.default { minAbsoluteUpperShadowThreshold; constructor(config) { const finalConfig = { ...DEFAULT_GRAVESTONE_DOJI_CONFIG, ...config }; super(finalConfig); this.requiredCount = 1; this.name = 'GraveStoneDoji'; // Apply configuration with defaults this.minAbsoluteUpperShadowThreshold = finalConfig.minAbsoluteUpperShadowThreshold; } logic(data) { // For single candle patterns, we need the last (most recent) candle // Since data is in ascending order, the last candle is at the last index let lastIndex = data.open.length - 1; let daysOpen = data.open[lastIndex]; let daysClose = data.close[lastIndex]; let daysHigh = data.high[lastIndex]; let daysLow = data.low[lastIndex]; // Basic validation - ensure we have valid numbers and high >= low if (!isFinite(daysOpen) || !isFinite(daysHigh) || !isFinite(daysLow) || !isFinite(daysClose)) { return false; } if (daysHigh < daysLow) { return false; } // Calculate shadow sizes and body size let bodySize = Math.abs(daysClose - daysOpen); let upperShadow = daysHigh - Math.max(daysOpen, daysClose); let lowerShadow = Math.min(daysOpen, daysClose) - daysLow; let totalRange = daysHigh - daysLow; // Avoid division by zero if (totalRange <= 0) { return false; } // GraveStone Doji criteria: // 1. Small body (open ≈ close) - doji characteristic // 2. Open and close should be near the low (at the bottom of the range) // 3. Long upper shadow - should dominate the candle // 4. Lower shadow should be small relative to upper shadow // 5. Upper shadow must be meaningful (not just noise) // Check if it's a doji (small body) // Note: approximateEqual now uses fixed thresholds instead of scale let isSmallBody = this.approximateEqual(daysOpen, daysClose); // Check if open/close are near the low (within 20% of total range from low) let openDistanceFromLow = Math.abs(daysOpen - daysLow); let closeDistanceFromLow = Math.abs(daysClose - daysLow); let maxDistanceFromLow = Math.max(openDistanceFromLow, closeDistanceFromLow); let isNearLow = maxDistanceFromLow <= totalRange * 0.2; // Upper shadow should be significant - at least 60% of total range let hasSignificantUpperShadow = upperShadow >= totalRange * 0.6; // Upper shadow must be meaningful - at least 2x the body size or a minimum threshold // Use direct threshold calculation instead of utility function let minUpperShadowThreshold = Math.max(bodySize * 2, totalRange * 0.1); let minAbsoluteThreshold = this.minAbsoluteUpperShadowThreshold; let hasMeaningfulUpperShadow = upperShadow >= minUpperShadowThreshold && upperShadow >= minAbsoluteThreshold; // Lower shadow should be minimal - less than 20% of total range // Handle negative lower shadow (when low is between open and close) let effectiveLowerShadow = Math.max(0, lowerShadow); let hasMinimalLowerShadow = effectiveLowerShadow <= totalRange * 0.2; // Body should be small relative to total range - less than 15% of total range let hasSmallBodyRelativeToRange = bodySize <= totalRange * 0.15; return isSmallBody && isNearLow && hasSignificantUpperShadow && hasMeaningfulUpperShadow && hasMinimalLowerShadow && hasSmallBodyRelativeToRange; } } exports.default = GraveStoneDoji; function gravestonedoji(data, config = DEFAULT_GRAVESTONE_DOJI_CONFIG) { return new GraveStoneDoji(config).hasPattern(data); } //# sourceMappingURL=GraveStoneDoji.js.map