File size: 8,435 Bytes
656ac31 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | 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
}
|