| 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 |
|
|
| |
| 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) |
|
|
| |
| 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.', |
| }) |
| } |
|
|
| |
| 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.', |
| }) |
| } |
|
|
| |
| 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.', |
| }) |
| } |
|
|
| |
| 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.', |
| }) |
| } |
|
|
| |
| 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.', |
| }) |
| } |
|
|
| |
| if (i > 0) { |
| const prev = candles[i - 1] |
|
|
| |
| 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ı.', |
| }) |
| } |
|
|
| |
| 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ı.', |
| }) |
| } |
|
|
| |
| 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.', |
| }) |
| } |
|
|
| |
| 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.', |
| }) |
| } |
|
|
| |
| 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ı.', |
| }) |
| } |
|
|
| |
| 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ı.', |
| }) |
| } |
| } |
|
|
| |
| if (i >= 2) { |
| const c2 = candles[i - 1] |
| const c1 = candles[i - 2] |
|
|
| |
| 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.', |
| }) |
| } |
|
|
| |
| 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.', |
| }) |
| } |
|
|
| |
| 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.', |
| }) |
| } |
|
|
| |
| 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 |
| } |
|
|