import type { Candle, CandlestickPattern } from './types' function bodySize(c: Candle) { return Math.abs(c.close - c.open) } function totalRange(c: Candle) { return c.high - c.low } function upperWick(c: Candle) { return c.high - Math.max(c.open, c.close) } function lowerWick(c: Candle) { return Math.min(c.open, c.close) - c.low } function isBullish(c: Candle) { return c.close > c.open } function isBearish(c: Candle) { return c.close < c.open } export function detectCandlestickPatterns(candles: Candle[]): CandlestickPattern[] { const patterns: CandlestickPattern[] = [] if (candles.length < 3) return patterns // Only check last 30 candles for recency const start = Math.max(0, candles.length - 30) for (let i = start; i < candles.length; i++) { const c = candles[i] const body = bodySize(c) const range = totalRange(c) const uWick = upperWick(c) const lWick = lowerWick(c) const avgRange = candles.slice(Math.max(0, i - 10), i).reduce((s, x) => s + totalRange(x), 0) / Math.min(10, i || 1) // Doji if (range > 0 && body / range < 0.1 && range > avgRange * 0.5) { patterns.push({ index: i, date: c.date, name: 'Doji', nameEn: 'Doji', type: 'neutral', reliability: 'medium', description: 'Açılış ve kapanış fiyatı neredeyse eşit. Piyasada kararsızlık sinyali verir. Trend dönüşü olabilir.', }) } // Hammer (bullish) if (lWick > body * 2 && uWick < body * 0.5 && body > 0 && range > avgRange * 0.5) { patterns.push({ index: i, date: c.date, name: 'Çekiç', nameEn: 'Hammer', type: 'bullish', reliability: 'high', description: 'Düşüş trendinde güçlü alıcı tepkisi. Uzun alt gölge, satıcıların geri püskürtüldüğünü gösterir. Yükseliş dönüş sinyali.', }) } // Inverted Hammer if (uWick > body * 2 && lWick < body * 0.5 && body > 0 && range > avgRange * 0.5) { patterns.push({ index: i, date: c.date, name: 'Ters Çekiç', nameEn: 'Inverted Hammer', type: 'bullish', reliability: 'medium', description: 'Düşüş trendinde potansiyel dönüş. Alıcılar fiyatı yukarı itmeye çalışıyor.', }) } // Shooting Star (bearish) if (uWick > body * 2 && lWick < body * 0.3 && isBearish(c) && range > avgRange * 0.5 && i > 0 && candles[i - 1].close < c.high) { patterns.push({ index: i, date: c.date, name: 'Kayan Yıldız', nameEn: 'Shooting Star', type: 'bearish', reliability: 'high', description: 'Yükseliş trendinde satıcı baskısı. Fiyat yukarı gidip geri dönmüş. Düşüş dönüş sinyali.', }) } // Marubozu (strong trend candle) if (body > avgRange * 1.5 && uWick < body * 0.05 && lWick < body * 0.05) { patterns.push({ index: i, date: c.date, name: isBullish(c) ? 'Boğa Marubozu' : 'Ayı Marubozu', nameEn: isBullish(c) ? 'Bullish Marubozu' : 'Bearish Marubozu', type: isBullish(c) ? 'bullish' : 'bearish', reliability: 'high', description: isBullish(c) ? 'Gölgesiz güçlü yükseliş mumu. Alıcılar tam kontrol. Güçlü yükseliş momentumu.' : 'Gölgesiz güçlü düşüş mumu. Satıcılar tam kontrol. Güçlü düşüş momentumu.', }) } // Two-candle patterns if (i > 0) { const prev = candles[i - 1] // Bullish Engulfing if (isBearish(prev) && isBullish(c) && c.open <= prev.close && c.close >= prev.open && bodySize(c) > bodySize(prev) * 1.2) { patterns.push({ index: i, date: c.date, name: 'Boğa Yutma', nameEn: 'Bullish Engulfing', type: 'bullish', reliability: 'high', description: 'Önceki düşüş mumunu tamamen yutan yükseliş mumu. Güçlü trend dönüş sinyali. Alıcılar kontrolü ele aldı.', }) } // Bearish Engulfing if (isBullish(prev) && isBearish(c) && c.open >= prev.close && c.close <= prev.open && bodySize(c) > bodySize(prev) * 1.2) { patterns.push({ index: i, date: c.date, name: 'Ayı Yutma', nameEn: 'Bearish Engulfing', type: 'bearish', reliability: 'high', description: 'Önceki yükseliş mumunu tamamen yutan düşüş mumu. Güçlü trend dönüş sinyali. Satıcılar kontrolü ele aldı.', }) } // Piercing Line if (isBearish(prev) && isBullish(c) && c.open < prev.low && c.close > (prev.open + prev.close) / 2 && c.close < prev.open) { patterns.push({ index: i, date: c.date, name: 'Delici Çizgi', nameEn: 'Piercing Line', type: 'bullish', reliability: 'medium', description: 'Boşluk aşağı açılıp önceki mumun ortasının üstünde kapandı. Alıcılar güç kazanıyor.', }) } // Dark Cloud Cover if (isBullish(prev) && isBearish(c) && c.open > prev.high && c.close < (prev.open + prev.close) / 2 && c.close > prev.open) { patterns.push({ index: i, date: c.date, name: 'Kara Bulut', nameEn: 'Dark Cloud Cover', type: 'bearish', reliability: 'medium', description: 'Boşluk yukarı açılıp önceki mumun ortasının altında kapandı. Satıcılar güç kazanıyor.', }) } // Tweezer Bottom if (Math.abs(c.low - prev.low) / c.low < 0.002 && isBearish(prev) && isBullish(c)) { patterns.push({ index: i, date: c.date, name: 'Cımbız Dibi', nameEn: 'Tweezer Bottom', type: 'bullish', reliability: 'medium', description: 'İki ardışık mum aynı dip seviyesine dokundu. Güçlü destek ve potansiyel dönüş noktası.', }) } // Tweezer Top if (Math.abs(c.high - prev.high) / c.high < 0.002 && isBullish(prev) && isBearish(c)) { patterns.push({ index: i, date: c.date, name: 'Cımbız Tepe', nameEn: 'Tweezer Top', type: 'bearish', reliability: 'medium', description: 'İki ardışık mum aynı tepe seviyesine dokundu. Güçlü direnç ve potansiyel dönüş noktası.', }) } } // Three-candle patterns if (i >= 2) { const c2 = candles[i - 1] const c1 = candles[i - 2] // Morning Star if (isBearish(c1) && bodySize(c2) < bodySize(c1) * 0.3 && isBullish(c) && c.close > (c1.open + c1.close) / 2 && bodySize(c) > bodySize(c1) * 0.5) { patterns.push({ index: i, date: c.date, name: 'Sabah Yıldızı', nameEn: 'Morning Star', type: 'bullish', reliability: 'high', description: 'Üç mumlu güçlü yükseliş dönüş formasyonu. Düşüşten sonra kararsızlık, ardından güçlü alım. Güvenilir dönüş sinyali.', }) } // Evening Star if (isBullish(c1) && bodySize(c2) < bodySize(c1) * 0.3 && isBearish(c) && c.close < (c1.open + c1.close) / 2 && bodySize(c) > bodySize(c1) * 0.5) { patterns.push({ index: i, date: c.date, name: 'Akşam Yıldızı', nameEn: 'Evening Star', type: 'bearish', reliability: 'high', description: 'Üç mumlu güçlü düşüş dönüş formasyonu. Yükselişten sonra kararsızlık, ardından güçlü satış. Güvenilir dönüş sinyali.', }) } // Three White Soldiers if (isBullish(c1) && isBullish(c2) && isBullish(c) && c2.close > c1.close && c.close > c2.close && bodySize(c1) > avgRange * 0.3 && bodySize(c2) > avgRange * 0.3 && bodySize(c) > avgRange * 0.3) { patterns.push({ index: i, date: c.date, name: 'Üç Beyaz Asker', nameEn: 'Three White Soldiers', type: 'bullish', reliability: 'high', description: 'Art arda üç güçlü yükseliş mumu. Alıcılar tam kontrol, güçlü devam sinyali.', }) } // Three Black Crows if (isBearish(c1) && isBearish(c2) && isBearish(c) && c2.close < c1.close && c.close < c2.close && bodySize(c1) > avgRange * 0.3 && bodySize(c2) > avgRange * 0.3 && bodySize(c) > avgRange * 0.3) { patterns.push({ index: i, date: c.date, name: 'Üç Kara Karga', nameEn: 'Three Black Crows', type: 'bearish', reliability: 'high', description: 'Art arda üç güçlü düşüş mumu. Satıcılar tam kontrol, güçlü düşüş devam sinyali.', }) } } } return patterns }