borsa / nextjs-app /src /lib /technical /candlestick-patterns.ts
veteroner's picture
feat: live position monitoring with charts + trading system production ready
656ac31
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
}