UNPKG

@cmike444/supply-and-demand-zones

Version:

A library for identifying supply and demand zones in candlestick data.

57 lines (56 loc) 3.13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.rallyBaseRally = rallyBaseRally; const enums_1 = require("../enums"); const constants_1 = require("../constants"); const isBullishDecisiveCandle_1 = require("./isBullishDecisiveCandle"); const isIndecisiveCandle_1 = require("./isIndecisiveCandle"); const findPatternEnd_1 = require("./findPatternEnd"); const isBullishCandle_1 = require("./isBullishCandle"); const isBearishCandle_1 = require("./isBearishCandle"); const isExplosiveCandle_1 = require("./isExplosiveCandle"); const isValidBase_1 = require("./isValidBase"); const calculateConfidence_1 = require("./calculateConfidence"); /** * Identifies a rally-base-rally pattern in a series of candlestick data. * * @param candles - Array of Candle objects to evaluate. * @returns A DemandZone object if the pattern is identified, otherwise `null`. */ function rallyBaseRally(candles, localATR = 0) { if (candles.length < constants_1.MIN_ZONE_CANDLES) return null; // Identify the rally const rallyEndIndex = (0, findPatternEnd_1.findPatternEnd)(candles, 0, isBullishDecisiveCandle_1.isBullishDecisiveCandle); if (rallyEndIndex === 0) return null; // Identify the base const baseEndIndex = (0, findPatternEnd_1.findPatternEnd)(candles, rallyEndIndex, isIndecisiveCandle_1.isIndecisiveCandle, constants_1.MAX_BASE_CANDLES); const baseCandleCount = baseEndIndex - rallyEndIndex; if (baseCandleCount < constants_1.MIN_BASE_CANDLES) return null; // Identify the second rally (ERC bullish departure, with ATR magnitude check) const rallyZoneStartIndex = (0, findPatternEnd_1.findPatternEnd)(candles, baseEndIndex, c => (0, isExplosiveCandle_1.isExplosiveCandle)(c, constants_1.DEFAULT_EXPLOSIVE_THRESHOLD, constants_1.MIN_EXPLOSIVE_ATR_MULTIPLIER * localATR) && (0, isBullishCandle_1.isBullishCandle)(c)); if (rallyZoneStartIndex === baseEndIndex) return null; // Return the identified rally-base-rally pattern as a DemandZone const baseCandles = candles.slice(rallyEndIndex, baseEndIndex); if (!(0, isValidBase_1.isValidBase)(baseCandles, candles[rallyEndIndex - 1], localATR)) return null; // Follow-through check: first candle of the second rally (after the base) must not be bearish const firstRallyCandle = candles[baseEndIndex]; if (firstRallyCandle && (0, isBearishCandle_1.isBearishCandle)(firstRallyCandle)) return null; const departureCandles = candles.slice(baseEndIndex, rallyZoneStartIndex); const fullFormation = candles.slice(0, rallyZoneStartIndex); return { direction: enums_1.ZONE_DIRECTION.DEMAND, type: enums_1.ZONE_TYPE.RALLY_BASE_RALLY, proximalLine: Math.max(...baseCandles.map(c => Math.max(c.open, c.close))), distalLine: Math.min(...fullFormation.map(c => c.low)), startTimestamp: candles[0].timestamp, endTimestamp: candles[rallyZoneStartIndex - 1].timestamp, confidence: (0, calculateConfidence_1.calculateConfidence)(departureCandles, baseCandles, localATR, true), }; } ;