@cmike444/supply-and-demand-zones
Version:
A library for identifying supply and demand zones in candlestick data.
57 lines (56 loc) • 3.13 kB
JavaScript
;
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),
};
}
;