UNPKG

@thuantan2060/technicalindicators

Version:
163 lines (153 loc) 4.92 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.DEFAULT_CANDLESTICK_CONFIG = void 0; /** * Basic configuration interface for CandlestickFinder base class. * Only contains the scale parameter used by approximateEqual function. */ /** * Default configuration for CandlestickFinder base class. */ const DEFAULT_CANDLESTICK_CONFIG = exports.DEFAULT_CANDLESTICK_CONFIG = { scale: 0.1 }; class CandlestickFinder { requiredCount; name; /** * Scale parameter for price comparison precision in approximateEqual function. * This should ONLY be used in the approximateEqual method, not in other pattern calculations. */ scale; constructor(config = DEFAULT_CANDLESTICK_CONFIG) { // Apply configuration with defaults const finalConfig = { ...DEFAULT_CANDLESTICK_CONFIG, ...config }; this.scale = finalConfig.scale; } /** * Compares two numbers for approximate equality using scale-dependent threshold. * This is the ONLY place where this.scale should be used in pattern detection. * * @param a First number to compare * @param b Second number to compare * @returns true if the numbers are approximately equal, false otherwise */ approximateEqual(a, b) { // Handle edge cases if (a === b) return true; if (isNaN(a) || isNaN(b) || !isFinite(a) || !isFinite(b)) return false; let left = parseFloat(Math.abs(a - b).toPrecision(4)) * 1; return left <= this.scale; } /** * Helper method to validate OHLC data integrity */ validateOHLC(open, high, low, close) { // Check for NaN or infinite values if (!isFinite(open) || !isFinite(high) || !isFinite(low) || !isFinite(close)) { return false; } // Check basic OHLC constraints if (high < Math.max(open, close) || low > Math.min(open, close)) { return false; } // Check for negative prices (optional, depends on use case) if (open < 0 || high < 0 || low < 0 || close < 0) { return false; } return true; } logic(data) { throw "this has to be implemented"; } getAllPatternIndex(data) { if (!data || !data.close || data.close.length < this.requiredCount) { return []; } // Validate data arrays have same length if (data.open.length !== data.close.length || data.high.length !== data.close.length || data.low.length !== data.close.length) { return []; } if (data.reversedInput) { data.open.reverse(); data.high.reverse(); data.low.reverse(); data.close.reverse(); } let strategyFn = this.logic; return this._generateDataForCandleStick(data).map((current, index) => { return strategyFn.call(this, current) ? index : undefined; }).filter(hasIndex => { return hasIndex !== undefined; }); } hasPattern(data) { if (!data || !data.close || data.close.length < this.requiredCount) { return false; } // Validate data arrays have same length if (data.open.length !== data.close.length || data.high.length !== data.close.length || data.low.length !== data.close.length) { return false; } if (data.reversedInput) { data.open.reverse(); data.high.reverse(); data.low.reverse(); data.close.reverse(); } let strategyFn = this.logic; return strategyFn.call(this, this._getLastDataForCandleStick(data)); } _getLastDataForCandleStick(data) { let requiredCount = this.requiredCount; if (data.close.length === requiredCount) { return data; } else { let returnVal = { open: [], high: [], low: [], close: [] }; let i = 0; // For ascending order data, get the last requiredCount elements let startIndex = data.close.length - requiredCount; while (i < requiredCount) { returnVal.open.push(data.open[startIndex + i]); returnVal.high.push(data.high[startIndex + i]); returnVal.low.push(data.low[startIndex + i]); returnVal.close.push(data.close[startIndex + i]); i++; } return returnVal; } } _generateDataForCandleStick(data) { let requiredCount = this.requiredCount; let generatedData = []; // Generate sliding windows for pattern detection for (let index = 0; index <= data.close.length - requiredCount; index++) { let returnVal = { open: [], high: [], low: [], close: [] }; for (let i = 0; i < requiredCount; i++) { returnVal.open.push(data.open[index + i]); returnVal.high.push(data.high[index + i]); returnVal.low.push(data.low[index + i]); returnVal.close.push(data.close[index + i]); } generatedData.push(returnVal); } return generatedData; } } exports.default = CandlestickFinder; //# sourceMappingURL=CandlestickFinder.js.map