import type { Candle } from '../types'; /** Wilder ADX: +DM/−DM → Wilder-geglättet → DI± → DX → ADX. NaN vor Index 2×period−1. */ export function adx(candles: Candle[], period: number): number[] { const n = candles.length; const out = new Array(n).fill(NaN); if (n < 2 * period) return out; const plusDM = [0]; const minusDM = [0]; const tr = [candles[0].high - candles[0].low]; for (let i = 1; i < n; i++) { const up = candles[i].high - candles[i - 1].high; const down = candles[i - 1].low - candles[i].low; plusDM.push(up > down && up > 0 ? up : 0); minusDM.push(down > up && down > 0 ? down : 0); tr.push(Math.max( candles[i].high - candles[i].low, Math.abs(candles[i].high - candles[i - 1].close), Math.abs(candles[i].low - candles[i - 1].close), )); } let sTR = 0, sPlus = 0, sMinus = 0; for (let i = 1; i <= period; i++) { sTR += tr[i]; sPlus += plusDM[i]; sMinus += minusDM[i]; } const dx = new Array(n).fill(NaN); const computeDx = () => { if (sTR === 0) return 0; // völlig flacher Markt const plusDI = (100 * sPlus) / sTR; const minusDI = (100 * sMinus) / sTR; const sum = plusDI + minusDI; return sum === 0 ? 0 : (100 * Math.abs(plusDI - minusDI)) / sum; }; dx[period] = computeDx(); for (let i = period + 1; i < n; i++) { sTR = sTR - sTR / period + tr[i]; sPlus = sPlus - sPlus / period + plusDM[i]; sMinus = sMinus - sMinus / period + minusDM[i]; dx[i] = computeDx(); } let sum = 0; for (let i = period; i < 2 * period; i++) sum += dx[i]; out[2 * period - 1] = sum / period; for (let i = 2 * period; i < n; i++) out[i] = (out[i - 1] * (period - 1) + dx[i]) / period; return out; }