MONEY TRADER PATTERN

MONEY TRADER PATTERN
 avatar
Destur
html
2 months ago
57 kB
6
Indexable
//@version=6
indicator(
    title              = "MONEY TRADER PATTERN + SUPER KIRILIM (EMA AL + PULSE UP)",
    shorttitle         = "MONEY TRADER PATTERN",
    overlay            = true,
    max_lines_count    = 500,
    max_labels_count   = 500,
    max_bars_back      = 5000)

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// (1) EMA FİLTRELİ AL SİNYALİ (İlk script)  — SADECE HESAP (etiket yok)
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
emaHizliPeriyot = input.int(9, "EMA Hizli Periyodu", group="Sinyal Ayarlari")
emaYavasPeriyot = input.int(21, "EMA Yavas Periyodu", group="Sinyal Ayarlari")
hacimFiltresi   = input.bool(true, "Hacim Onayi Kullan", group="Filtre Ayarlari")

emaHizli = ta.ema(close, emaHizliPeriyot)
emaYavas = ta.ema(close, emaYavasPeriyot)
hacimOrt = ta.sma(volume, 20)

hacimOnayi    = not hacimFiltresi or (volume > hacimOrt)
emaEgimYukari = emaHizli > emaHizli[1]
emaEgimAsagi  = emaHizli < emaHizli[1]

alSinyali  = ta.crossover(emaHizli, emaYavas) and hacimOnayi and emaEgimYukari
satSinyali = ta.crossunder(emaHizli, emaYavas) and hacimOnayi and emaEgimAsagi

plot(emaHizli, color=color.new(color.blue, 70), title="EMA Hizli")
plot(emaYavas, color=color.new(color.orange, 70), title="EMA Yavas")

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// (2) MONEY TRADER PATTERN (2. script) — ORİJİNAL KOD (AL/SAT etiketleri kapalı)
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

// ══════════════════════════════════════
// SABİTLER (CONSTANTS)
// ══════════════════════════════════════
GRP_MAIN   = "⚙️ Ana Ayarlar"
GRP_FILTER = "🔍 Filtreler"
GRP_VISUAL = "🎨 Görünüm"
GRP_RISK   = "🛡️ Risk Yönetimi"
GRP_LINES  = "📐 Kanal Çizgileri"
GRP_COLORS = "🎨 Renkler"
GRP_ADV    = "🔧 Gelişmiş"
GRP_ALERT  = "🔔 Alarmlar"

INDICATOR_VERSION = "v1.7.0"
int MAX_PIVOTS         = 60
int RESCAN_INTERVAL    = 10
int MAX_PIVOT_SCAN     = 15
int WARMUP_MINIMUM     = 50
float LINE_EPSILON     = 1e-10
float MAX_WIDTH_MULT   = 10.0
float VOL_CONTR_THRESH = 0.85
float BG_TRANSPARENCY  = 90.0
int MAX_HIST_LINES     = 400
int MAX_HIST_FILLS     = 200
int MAX_HIST_LABELS    = 200

// ══════════════════════════════════════
// GİRİŞLER (INPUTS)
// ══════════════════════════════════════
pivotLenInput = input.int(5, "Pivot Tespit Uzunluğu", minval = 2, maxval = 30, group = GRP_MAIN, tooltip = "Swing pivot algılama için sağ/sol bar sayısı.\n• Önerilen: 3–10")
minTouchesInput = input.int(2, "Min Dokunuş Sayısı", minval = 2, maxval = 6, group = GRP_MAIN, tooltip = "Her sınır çizgisi için minimum pivot dokunuşu.\n• Önerilen: 2–3")
maxChannelBarsInput = input.int(120, "Kanal Genişliği (Bar)", minval = 20, maxval = 500, step = 10, group = GRP_MAIN, tooltip = "Maksimum geriye bakış.\n• Önerilen: 60–150")
convergenceMinInput = input.float(0.02, "Min Daralma Hızı", minval = 0.0, maxval = 0.5, step = 0.01, group = GRP_MAIN, tooltip = "Minimum daralma oranı (0–1).\n• Önerilen: 0.02–0.15")
touchToleranceInput = input.float(0.15, "Dokunuş Toleransı (ATR)", minval = 0.01, maxval = 0.5, step = 0.01, group = GRP_ADV, tooltip = "Dokunma olarak sayılan pivot mesafesi.\n• Önerilen: 0.10–0.25")
deviationMaxInput = input.float(0.3, "Maks Sapma (ATR)", minval = 0.05, maxval = 1.0, step = 0.05, group = GRP_ADV, tooltip = "Maksimum pivot taşma miktarı.\n• Önerilen: 0.2–0.5")
minChannelWidthAtrInput = input.float(0.5, "Min Kanal Genişliği (ATR)", minval = 0.1, maxval = 3.0, step = 0.1, group = GRP_ADV, tooltip = "Minimum genişlik filtresi.\n• Önerilen: 0.3–1.0")

volConfirmInput = input.float(1.2, "Hacim Sinyali Çarpanı", minval = 0.5, maxval = 3.0, step = 0.1, group = GRP_FILTER, tooltip = "Hacim vs SMA(20).\n• Forex için 0.5'e ayarla devre dışı bırakmak için")
volContractionInput = input.bool(true, "Hacim Daralma Filtri", group = GRP_FILTER, tooltip = "Kanal içinde hacim düşüşü gerekli mi?")
momentumFilterInput = input.bool(true, "Momentum Onayı", group = GRP_FILTER, tooltip = "Boğa için RSI > 50, Ayı için < 50")

showPatternsInput    = input.bool(true, "Kanal Desenlerini Göster", group = GRP_VISUAL)
showSignalsInput     = input.bool(true, "Kırılım Sinyallerini Göster", group = GRP_VISUAL)
showBgInput          = input.bool(false, "Desen Arkaplanını Göster", group = GRP_VISUAL, tooltip = "Fiyat kanalda iken arkaplan rengi gösterir")
historyModeInput     = input.string("Sonuncu", "Desen Geçmişi", options = ["Tümü", "Sonuncu"], group = GRP_VISUAL, tooltip = "Tümü: tam geçmiş | Sonuncu: temiz grafik")
labelSizeInput       = input.string("Orta", "Etiket Boyutu", options = ["Küçük", "Orta", "Büyük"], group = GRP_VISUAL, tooltip = "▲ ▼ ✗ etiketlerinin boyutu")
showWatermarkInput   = input.bool(false, "Filigranı Göster", group = GRP_VISUAL)

showFillInput        = input.bool(true, "Kanal Dolgunluğunu Göster", group = GRP_LINES, tooltip = "Sınır çizgileri arasındaki gölgeli alanı göster/gizle")
lineColorInput       = input.color(#FFEB3B, "Çizgi Rengi", group = GRP_LINES, tooltip = "Kanal sınır çizgilerinin rengi (kırılım öncesi)")
lineWidthInput       = input.int(2, "Çizgi Kalınlığı", minval = 1, maxval = 4, group = GRP_LINES, tooltip = "Kanal sınır çizgilerinin kalınlığı.\n• 1 = ince\n• 2 = varsayılan\n• 3–4 = kalın")

showLevelsInput = input.bool(true, "İşlem Seviyelerini Göster", group = GRP_RISK, tooltip = "Giriş / SL / TP1 / TP2 / TP3 çizgilerini ve etiketlerini göster")
slPaddingInput = input.float(0, "SL Tamponu (ATR)", minval = 0.0, maxval = 1.0, step = 0.05, group = GRP_RISK, tooltip = "Karşı sınırın ötesinde ekstra tampon.\n• 0 = tam sınırdan\n• 0.2 = sınır + 0.2×ATR\n• Önerilen: 0.1–0.3")
labelOffsetInput = input.int(20, "Etiket Ofseti (bar)", minval = 5, maxval = 50, group = GRP_RISK, tooltip = "Son mumdan kaç bar sağa seviye etiketleri yerleştirilir.\n• Önerilen: 15–25")

themeInput = input.string("Auto", "Tema", options = ["Auto", "Koyu", "Açık"], group = GRP_VISUAL)

bullColorInput    = input.color(#00E676, "Yükseliş", inline = "colors", group = GRP_COLORS)
bearColorInput    = input.color(#FF5252, "Düşüş", inline = "colors", group = GRP_COLORS)
neutralColorInput = input.color(#FFEB3B, "Nötr", inline = "colors", group = GRP_COLORS)

webhookInput = input.bool(false, "Webhook JSON Formatı", group = GRP_ALERT)

// ══════════════════════════════════════
// TEMA TESPİTİ & RENKLER
// ══════════════════════════════════════
isDark = switch themeInput
    "Koyu"  => true
    "Açık" => false
    => color.r(chart.bg_color) < 128

TEXT_COLOR    = isDark ? #E0E0E0 : #1A1A1A
TEXT_MUTED    = isDark ? color.new(#9E9E9E, 0) : color.new(#757575, 0)
TEXT_BRIGHT   = isDark ? #FFFFFF : #000000
TABLE_BG      = isDark ? color.new(#131722, 5) : color.new(#FFFFFF, 5)
TABLE_BORDER  = isDark ? color.new(#2A2E39, 0) : color.new(#D0D0D0, 0)
TABLE_ROW_ALT = isDark ? color.new(#1C2030, 0) : color.new(#F0F4F8, 0)
HEADER_BG     = color.new(#2962FF, 0)
LINE_SUBTLE   = isDark ? color.new(#555555, 0) : color.new(#AAAAAA, 0)
WM_COLOR      = isDark ? color.new(#FFFFFF, 80) : color.new(#000000, 80)
INVALID_COLOR = isDark ? color.new(#FF9800, 0) : color.new(#E65100, 0)

BULL_BG = color.new(bullColorInput, 88)
BEAR_BG = color.new(bearColorInput, 88)
CHANNEL_LINE_COLOR = color.new(lineColorInput, 50)

SL_COLOR     = color.new(#FF1744, 0)
TP_COLOR     = color.new(#00E676, 0)
ENTRY_COLOR  = color.new(#2979FF, 0)
TP_HIT_COLOR = color.new(#40E0D0, 0)
CHANNEL_FILL_COLOR = showFillInput ? color.new(lineColorInput, 90) : color.new(lineColorInput, 100)

// ══════════════════════════════════════
// SOLVERLAR
// ══════════════════════════════════════
lblSize = switch labelSizeInput
    "Küçük"   => size.tiny
    "Büyük"   => size.normal
    => size.small

// ══════════════════════════════════════
// SAF FONKSİYONLAR (global bağımlılık yok)
// ══════════════════════════════════════
safeDiv(float num, float den, float fallback = 0.0) =>
    den != 0 and not na(num) and not na(den) ? num / den : fallback

lineAt(float x1, float y1, float x2, float y2, float x) =>
    float dx = x2 - x1
    math.abs(dx) > LINE_EPSILON ? y1 + (y2 - y1) * (x - x1) / dx : y1

// ══════════════════════════════════════
// TEMEL HESAPLAMALAR
// ══════════════════════════════════════
float atr20    = nz(ta.atr(20), syminfo.mintick * 10)
float rsiVal   = nz(ta.rsi(close, 14), 50.0)
float volSma   = nz(ta.sma(volume, 20), 0.0)
bool  hasVolume = nz(volume, 0) > 0
float cumVol   = ta.cum(nz(volume, 0))

int WARMUP_BARS = math.max(pivotLenInput * 2 + maxChannelBarsInput, WARMUP_MINIMUM)
bool isWarmedUp = bar_index >= WARMUP_BARS
bool showLastOnly = historyModeInput == "Sonuncu"

// ══════════════════════════════════════
// PİVOT TESPİTİ
// ══════════════════════════════════════
float pivHigh = ta.pivothigh(high, pivotLenInput, pivotLenInput)
float pivLow  = ta.pivotlow(low, pivotLenInput, pivotLenInput)

var array<float> hiPrices = array.new_float()
var array<int>   hiBars   = array.new_int()
var array<float> loPrices = array.new_float()
var array<int>   loBars   = array.new_int()

if not na(pivHigh)
    hiPrices.unshift(pivHigh)
    hiBars.unshift(bar_index - pivotLenInput)
if not na(pivLow)
    loPrices.unshift(pivLow)
    loBars.unshift(bar_index - pivotLenInput)

while hiPrices.size() > MAX_PIVOTS
    hiPrices.pop()
    hiBars.pop()
while loPrices.size() > MAX_PIVOTS
    loPrices.pop()
    loBars.pop()

// ══════════════════════════════════════
// KANAL DURUMU (orijinal)
// ══════════════════════════════════════
var bool     channelActive  = false
var float    hiX1 = 0.0
var float    hiY1 = 0.0
var float    hiX2 = 0.0
var float    hiY2 = 0.0
var float    loX1 = 0.0
var float    loY1 = 0.0
var float    loX2 = 0.0
var float    loY2 = 0.0
var int      chHiTouches   = 0
var int      chLoTouches   = 0
var float    chConvergence = 0.0
var float    chMaxWidth    = 0.0
var int      chDetectBar   = 0
var line     chHiLine      = na
var line     chLoLine      = na
var linefill chFill        = na

var int    breakoutDir     = 0
var int    breakoutBar     = 0
var float  targetPrice     = 0.0
var string breakStrength   = "—"
var bool   breakInvalid    = false
var float  volContraction  = 0.0
var float  entryPrice      = 0.0
var float  slPrice         = 0.0
var float  slPriceOrig     = 0.0
var float  tp1Price        = 0.0
var float  tp2Price        = 0.0
var float  tp3Price        = 0.0
var bool   tp1Hit = false
var bool   tp2Hit = false
var bool   tp3Hit = false
var bool   slHit  = false
var bool   tradeOpen = false

var int    totalPatterns   = 0
var int    bullBreaks      = 0
var int    bearBreaks      = 0
var int    invalidCount    = 0
var int    winCount        = 0
var int    lossCount       = 0
var int    lastSignalBar   = 0
var string lastSignalType  = "—"
var float  dirScore        = 50.0

var array<line>     histLines  = array.new<line>()
var array<linefill> histFills  = array.new<linefill>()
var array<label>    histLabels = array.new<label>()

var line lineEntry  = na
var line lineSL     = na
var line lineTP1    = na
var line lineTP2    = na
var line lineTP3    = na
var label lbEntry   = na
var label lbSL      = na
var label lbTP1     = na
var label lbTP2     = na
var label lbTP3     = na
var bool hasTradeDrawings = false

formatAlertMsg(string action, string emoji, string strLbl, float _entry, float _sl, float _tp1, float _tp2, float _tp3) =>
    string tickerStr = syminfo.tickerid
    string tfStr     = timeframe.period
    string priceStr  = str.tostring(close, format.mintick)
    string slAlStr   = str.tostring(_sl, format.mintick)
    string t1Str     = str.tostring(_tp1, format.mintick)
    string t2Str     = str.tostring(_tp2, format.mintick)
    string t3Str     = str.tostring(_tp3, format.mintick)
    string jsonMsg   = '{"action":"' + action + '","ticker":"' + tickerStr + '","price":' + priceStr + ',"sl":' + slAlStr + ',"tp1":' + t1Str + ',"tp2":' + t2Str + ',"tp3":' + t3Str + ',"strength":"' + strLbl + '","tf":"' + tfStr + '"}'
    string textMsg   = emoji + " " + str.upper(action) + " [" + strLbl + "] | " + tickerStr + " | " + tfStr + " | Giriş: " + priceStr + " | SL: " + slAlStr + " | TP1: " + t1Str + " | TP2: " + t2Str + " | TP3: " + t3Str
    webhookInput ? jsonMsg : textMsg

formatEventMsg(string eventName, string emoji) =>
    string p = str.tostring(close, format.mintick)
    webhookInput ? '{"event":"' + eventName + '","ticker":"' + syminfo.tickerid + '","price":' + p + '}' : emoji + " " + str.upper(eventName) + " | " + syminfo.tickerid + " | " + p

deleteTradeDrawings() =>
    line.delete(lineEntry)
    line.delete(lineSL)
    line.delete(lineTP1)
    line.delete(lineTP2)
    line.delete(lineTP3)
    label.delete(lbEntry)
    label.delete(lbSL)
    label.delete(lbTP1)
    label.delete(lbTP2)
    label.delete(lbTP3)

deleteTradeLabels() =>
    label.delete(lbEntry)
    label.delete(lbSL)
    label.delete(lbTP1)
    label.delete(lbTP2)
    label.delete(lbTP3)

// ─────────────────────────────────────────────────────────────────────
// (A) Kanal tespiti + çizimler + kırılım işlemleri
// ─────────────────────────────────────────────────────────────────────
// >>> Buradan itibaren sizin verdiğiniz MTP kodu AYNI mantıkla devam eder.
// >>> Sadece "SİNYAL GÖRSELLEŞTİRME" kısmında AL/SAT label basımı iptal edildi.
// ─────────────────────────────────────────────────────────────────────

// ══════════════════════════════════════
// SINIR UYGUNLUK KANAL TESPİTİ
// ══════════════════════════════════════
bool newPivot = not na(pivHigh) or not na(pivLow)
bool rescanDue = bar_index % RESCAN_INTERVAL == 0
bool shouldScan = (newPivot or rescanDue) and not channelActive and not tradeOpen and isWarmedUp and hiPrices.size() >= minTouchesInput and loPrices.size() >= minTouchesInput

bool channelJustDetected = false

if shouldScan
    var array<float> hX = array.new_float()
    var array<float> hY = array.new_float()
    var array<float> lX = array.new_float()
    var array<float> lY = array.new_float()
    hX.clear(), hY.clear(), lX.clear(), lY.clear()

    for i = 0 to math.min(hiPrices.size() - 1, MAX_PIVOT_SCAN)
        if bar_index - hiBars.get(i) <= maxChannelBarsInput
            hX.push(float(hiBars.get(i)))
            hY.push(hiPrices.get(i))
    for i = 0 to math.min(loPrices.size() - 1, MAX_PIVOT_SCAN)
        if bar_index - loBars.get(i) <= maxChannelBarsInput
            lX.push(float(loBars.get(i)))
            lY.push(loPrices.get(i))

    int hCnt = hX.size()
    int lCnt = lX.size()
    float devTol   = atr20 * deviationMaxInput
    float touchTol = atr20 * touchToleranceInput

    float bestHiX1 = 0.0, bestHiY1 = 0.0, bestHiX2 = 0.0, bestHiY2 = 0.0
    int   bestHiTouches = 0
    bool  foundHi = false

    if hCnt >= minTouchesInput
        for a = 0 to hCnt - 2
            for b = a + 1 to hCnt - 1
                float ax = hX.get(a), ay = hY.get(a)
                float bx = hX.get(b), bPy = hY.get(b)
                if math.abs(bx - ax) >= 1.0
                    bool allBelow = true
                    int  touches = 0
                    for k = 0 to hCnt - 1
                        float projY = lineAt(ax, ay, bx, bPy, hX.get(k))
                        float diff = hY.get(k) - projY
                        if diff > devTol
                            allBelow := false
                            break
                        if math.abs(diff) <= touchTol
                            touches += 1
                    if allBelow and touches >= minTouchesInput and touches > bestHiTouches
                        bestHiTouches := touches
                        bestHiX1 := ax, bestHiY1 := ay, bestHiX2 := bx, bestHiY2 := bPy
                        foundHi  := true

    float bestLoX1 = 0.0, bestLoY1 = 0.0, bestLoX2 = 0.0, bestLoY2 = 0.0
    int   bestLoTouches = 0
    bool  foundLo = false

    if lCnt >= minTouchesInput
        for a = 0 to lCnt - 2
            for b = a + 1 to lCnt - 1
                float ax = lX.get(a), ay = lY.get(a)
                float bx = lX.get(b), bPy = lY.get(b)
                if math.abs(bx - ax) >= 1.0
                    bool allAbove = true
                    int  touches = 0
                    for k = 0 to lCnt - 1
                        float projY = lineAt(ax, ay, bx, bPy, lX.get(k))
                        float diff = lY.get(k) - projY
                        if diff < -devTol
                            allAbove := false
                            break
                        if math.abs(diff) <= touchTol
                            touches += 1
                    if allAbove and touches >= minTouchesInput and touches > bestLoTouches
                        bestLoTouches := touches
                        bestLoX1 := ax, bestLoY1 := ay, bestLoX2 := bx, bestLoY2 := bPy
                        foundLo  := true

    if foundHi and foundLo
        float hiMinX = math.min(bestHiX1, bestHiX2)
        float hiMaxX = math.max(bestHiX1, bestHiX2)
        float loMinX = math.min(bestLoX1, bestLoX2)
        float loMaxX = math.max(bestLoX1, bestLoX2)
        float overlapStart = math.max(hiMinX, loMinX)
        float overlapEnd   = math.min(hiMaxX, loMaxX)
        float maxH = 0.0
        if overlapEnd > overlapStart
            int samples = math.max(int((overlapEnd - overlapStart) / 5.0), 2)
            for s = 0 to samples
                float sx = overlapStart + (overlapEnd - overlapStart) * float(s) / float(samples)
                float hu = lineAt(bestHiX1, bestHiY1, bestHiX2, bestHiY2, sx)
                float lo = lineAt(bestLoX1, bestLoY1, bestLoX2, bestLoY2, sx)
                if hu - lo > maxH
                    maxH := hu - lo
        else
            float midX = (hiMinX + hiMaxX + loMinX + loMaxX) / 4.0
            maxH := math.abs(lineAt(bestHiX1, bestHiY1, bestHiX2, bestHiY2, midX) - lineAt(bestLoX1, bestLoY1, bestLoX2, bestLoY2, midX))

        float startX     = math.min(math.min(bestHiX1, bestHiX2), math.min(bestLoX1, bestLoX2))
        float endX       = float(bar_index)
        float upperNow   = lineAt(bestHiX1, bestHiY1, bestHiX2, bestHiY2, endX)
        float lowerNow   = lineAt(bestLoX1, bestLoY1, bestLoX2, bestLoY2, endX)
        float widthNow   = upperNow - lowerNow
        float upperStart = lineAt(bestHiX1, bestHiY1, bestHiX2, bestHiY2, startX)
        float lowerStart = lineAt(bestLoX1, bestLoY1, bestLoX2, bestLoY2, startX)
        float widthStart = upperStart - lowerStart
        float convRate   = widthStart > 0 ? 1.0 - safeDiv(widthNow, widthStart, 1.0) : 0.0
        bool  notInv     = widthNow > 0
        bool  isConv     = convRate >= convergenceMinInput
        bool  widthOk    = widthNow >= atr20 * minChannelWidthAtrInput and widthNow < atr20 * MAX_WIDTH_MULT
        bool  isInside   = notInv and close[1] <= upperNow and close[1] >= lowerNow

        int patStartIdx = int(startX)
        int patBars     = math.max(bar_index - patStartIdx, 1)

        int safPatBars  = math.min(patBars, bar_index)
        int preBars     = math.min(safPatBars, patStartIdx)
        float volInPat  = hasVolume and safPatBars > 0 ? safeDiv(cumVol - nz(cumVol[safPatBars], 0.0), float(safPatBars), volSma) : volSma
        float volPrePat = hasVolume and preBars > 0 ? safeDiv(nz(cumVol[safPatBars], 0.0) - nz(cumVol[safPatBars + preBars], 0.0), float(preBars), volSma) : volSma
        float volContRatio = safeDiv(volInPat, volPrePat, 1.0)
        bool  volContOk = volContractionInput ? (not hasVolume or volContRatio < VOL_CONTR_THRESH) : true

        if notInv and isConv and widthOk and isInside and volContOk
            if showLastOnly
                for ln in histLines
                    line.delete(ln)
                histLines.clear()
                for fl in histFills
                    linefill.delete(fl)
                histFills.clear()
                for lb in histLabels
                    label.delete(lb)
                histLabels.clear()
                hasTradeDrawings := false

            channelActive  := true
            hiX1 := bestHiX1, hiY1 := bestHiY1, hiX2 := bestHiX2, hiY2 := bestHiY2
            loX1 := bestLoX1, loY1 := bestLoY1, loX2 := bestLoX2, loY2 := bestLoY2
            chHiTouches   := bestHiTouches
            chLoTouches   := bestLoTouches
            chConvergence := convRate
            chMaxWidth    := maxH
            chDetectBar   := bar_index
            breakoutDir   := 0
            breakInvalid  := false
            breakStrength := "—"
            volContraction := volContRatio
            channelJustDetected := true
            totalPatterns += 1

while histLines.size() > MAX_HIST_LINES
    line.delete(histLines.shift())
while histFills.size() > MAX_HIST_FILLS
    linefill.delete(histFills.shift())
while histLabels.size() > MAX_HIST_LABELS
    label.delete(histLabels.shift())

bool channelJustDetected_local = channelJustDetected

if channelActive and showPatternsInput
    float hiProjNow = lineAt(hiX1, hiY1, hiX2, hiY2, float(bar_index))
    float loProjNow = lineAt(loX1, loY1, loX2, loY2, float(bar_index))

    if channelJustDetected_local
        int drawStart  = int(math.min(math.min(hiX1, hiX2), math.min(loX1, loX2)))
        float hiStartY = lineAt(hiX1, hiY1, hiX2, hiY2, float(drawStart))
        float loStartY = lineAt(loX1, loY1, loX2, loY2, float(drawStart))
        if not na(chHiLine)
            line.delete(chHiLine)
        if not na(chLoLine)
            line.delete(chLoLine)
        if not na(chFill)
            linefill.delete(chFill)
        chHiLine := line.new(drawStart, hiStartY, bar_index, hiProjNow, color = CHANNEL_LINE_COLOR, width = lineWidthInput)
        chLoLine := line.new(drawStart, loStartY, bar_index, loProjNow, color = CHANNEL_LINE_COLOR, width = lineWidthInput)
        chFill   := linefill.new(chHiLine, chLoLine, CHANNEL_FILL_COLOR)
        histLines.push(chHiLine), histLines.push(chLoLine)
        histFills.push(chFill)
    else
        if not na(chHiLine)
            line.set_x2(chHiLine, bar_index), line.set_y2(chHiLine, hiProjNow)
        if not na(chLoLine)
            line.set_x2(chLoLine, bar_index), line.set_y2(chLoLine, loProjNow)

// ══════════════════════════════════════
// KRILIM TESPİTİ + GÜÇ
// ══════════════════════════════════════
bool rawBullBreak = false
bool rawBearBreak = false
float strengthScore = 0.0
float breakBoundary = 0.0
float oppBoundary   = 0.0

bool channelMature = channelActive and breakoutDir == 0

if channelMature and barstate.isconfirmed and isWarmedUp
    float upper     = lineAt(hiX1, hiY1, hiX2, hiY2, float(bar_index))
    float lower     = lineAt(loX1, loY1, loX2, loY2, float(bar_index))
    float bodyLen   = math.abs(close - open)
    float candleLen = high - low
    float bodyRatio = candleLen > 0 ? bodyLen / candleLen : 0.0
    float bodyMid   = (open + close) / 2.0
    bool  volOk     = hasVolume ? volume > volSma * volConfirmInput : true
    bool  momOk     = momentumFilterInput ? (close > upper ? rsiVal > 50 : rsiVal < 50) : true

    if close > upper
        rawBullBreak := true
        breakBoundary := upper
        oppBoundary   := lower
        float penetration = atr20 > 0 ? math.min((close - upper) / atr20, 2.0) / 2.0 : 0.5
        float bodyCommit  = bodyMid > upper ? 1.0 : 0.3
        float volBonus    = volOk ? 1.0 : 0.4
        float momBonus    = momOk ? 1.0 : 0.4
        strengthScore := (penetration * 0.25 + bodyRatio * 0.15 + bodyCommit * 0.15 + volBonus * 0.25 + momBonus * 0.20) * 100

    if close < lower
        rawBearBreak := true
        breakBoundary := lower
        oppBoundary   := upper
        float penetration = atr20 > 0 ? math.min((lower - close) / atr20, 2.0) / 2.0 : 0.5
        float bodyCommit  = bodyMid < lower ? 1.0 : 0.3
        float volBonus    = volOk ? 1.0 : 0.4
        float momBonus    = momOk ? 1.0 : 0.4
        strengthScore := (penetration * 0.25 + bodyRatio * 0.15 + bodyCommit * 0.15 + volBonus * 0.25 + momBonus * 0.20) * 100

// ══════════════════════════════════════
// SİNYAL İŞLEME + HEDEF
// ══════════════════════════════════════
bool confirmedBullBreak = rawBullBreak
bool confirmedBearBreak = rawBearBreak

if confirmedBullBreak
    breakoutDir   := 1
    breakoutBar   := bar_index
    entryPrice    := close
    slPrice       := oppBoundary - atr20 * slPaddingInput
    slPriceOrig   := slPrice
    targetPrice   := breakBoundary + chMaxWidth
    float fullMove = math.abs(targetPrice - entryPrice)
    tp1Price      := entryPrice + fullMove / 3.0
    tp2Price      := entryPrice + fullMove * 2.0 / 3.0
    tp3Price      := entryPrice + fullMove
    tp1Hit := false, tp2Hit := false, tp3Hit := false, slHit := false
    tradeOpen := true
    breakInvalid  := false
    breakStrength := strengthScore >= 65 ? "Güçlü" : strengthScore >= 35 ? "Orta" : "Zayıf"
    bullBreaks    += 1
    lastSignalBar  := bar_index
    lastSignalType := "Yükseliş Kırılımı"
    if not na(chHiLine)
        line.set_color(chHiLine, color.new(bullColorInput, 40)), line.set_width(chHiLine, lineWidthInput)
    if not na(chLoLine)
        line.set_color(chLoLine, color.new(bullColorInput, 40)), line.set_width(chLoLine, lineWidthInput)
    if not na(chFill)
        linefill.set_color(chFill, showFillInput ? BULL_BG : color.new(bullColorInput, 100))

if confirmedBearBreak
    breakoutDir   := -1
    breakoutBar   := bar_index
    entryPrice    := close
    slPrice       := oppBoundary + atr20 * slPaddingInput
    slPriceOrig   := slPrice
    targetPrice   := breakBoundary - chMaxWidth
    float fullMove = math.abs(entryPrice - targetPrice)
    tp1Price      := entryPrice - fullMove / 3.0
    tp2Price      := entryPrice - fullMove * 2.0 / 3.0
    tp3Price      := entryPrice - fullMove
    tp1Hit := false, tp2Hit := false, tp3Hit := false, slHit := false
    tradeOpen := true
    breakInvalid  := false
    breakStrength := strengthScore >= 65 ? "Güçlü" : strengthScore >= 35 ? "Orta" : "Zayıf"
    bearBreaks    += 1
    lastSignalBar  := bar_index
    lastSignalType := "Düşüş Kırılımı"
    if not na(chHiLine)
        line.set_color(chHiLine, color.new(bearColorInput, 40)), line.set_width(chHiLine, lineWidthInput)
    if not na(chLoLine)
        line.set_color(chLoLine, color.new(bearColorInput, 40)), line.set_width(chLoLine, lineWidthInput)
    if not na(chFill)
        linefill.set_color(chFill, showFillInput ? BEAR_BG : color.new(bearColorInput, 100))

if channelActive and breakoutDir == 0 and bar_index - chDetectBar > maxChannelBarsInput
    channelActive := false

if tradeOpen and breakoutDir != 0 and not slHit and bar_index > breakoutBar
    bool tpSide   = breakoutDir == 1 ? high >= tp1Price : low <= tp1Price
    bool tp2Side  = breakoutDir == 1 ? high >= tp2Price : low <= tp2Price
    bool tp3Side  = breakoutDir == 1 ? high >= tp3Price : low <= tp3Price
    bool slSide   = breakoutDir == 1 ? low <= slPrice  : high >= slPrice

    if slSide
        slHit := true
        if not tp1Hit
            lossCount += 1
    else
        if tpSide and not tp1Hit
            tp1Hit := true
            winCount += 1
            slPrice := entryPrice
            if not na(lbEntry)
                label.set_text(lbEntry, "GİRİŞ " + str.tostring(entryPrice, format.mintick) + " (SL → BE)")
            if not na(lbSL)
                string slPctUpd = str.tostring(math.abs(slPriceOrig - entryPrice) / entryPrice * 100, "#.##") + "%"
                label.set_text(lbSL, "SL orig " + str.tostring(slPriceOrig, format.mintick) + " (−" + slPctUpd + ")")
                label.set_color(lbSL, color.new(SL_COLOR, 75))
        if tp2Side and not tp2Hit
            tp2Hit := true
        if tp3Side and not tp3Hit
            tp3Hit := true

var int lastBreakoutDir = 0
if tradeOpen and (tp3Hit or slHit)
    lastBreakoutDir := breakoutDir
    tradeOpen := false
    channelActive := false
    breakoutDir   := 0
    if not showLastOnly
        deleteTradeLabels()
        hasTradeDrawings := false

// İşlem seviyeleri (orijinal)
if (confirmedBullBreak or confirmedBearBreak) and showLevelsInput
    if showLastOnly
        deleteTradeDrawings()
    else
        deleteTradeLabels()

    int lineEnd  = bar_index + labelOffsetInput
    int labelPos = bar_index + labelOffsetInput + 2

    lineEntry := line.new(bar_index, entryPrice, lineEnd, entryPrice, color = ENTRY_COLOR, width = 2, style = line.style_solid)
    lineSL    := line.new(bar_index, slPrice, lineEnd, slPrice, color = SL_COLOR, width = 2, style = line.style_solid)
    lineTP1   := line.new(bar_index, tp1Price, lineEnd, tp1Price, color = TP_COLOR, width = 1, style = line.style_dashed)
    lineTP2   := line.new(bar_index, tp2Price, lineEnd, tp2Price, color = TP_COLOR, width = 1, style = line.style_dashed)
    lineTP3   := line.new(bar_index, tp3Price, lineEnd, tp3Price, color = TP_COLOR, width = 2, style = line.style_dashed)

    string slPctStr  = str.tostring(math.abs(slPrice - entryPrice) / entryPrice * 100, "#.##") + "%"
    string tp1PctStr = str.tostring(math.abs(tp1Price - entryPrice) / entryPrice * 100, "#.##") + "%"
    string tp2PctStr = str.tostring(math.abs(tp2Price - entryPrice) / entryPrice * 100, "#.##") + "%"
    string tp3PctStr = str.tostring(math.abs(tp3Price - entryPrice) / entryPrice * 100, "#.##") + "%"

    lbEntry := label.new(labelPos, entryPrice, "GİRİŞ " + str.tostring(entryPrice, format.mintick), color = color.new(ENTRY_COLOR, 60), textcolor = TEXT_BRIGHT, style = label.style_label_left, size = lblSize)
    lbSL    := label.new(labelPos, slPrice, "SL " + str.tostring(slPrice, format.mintick) + " (−" + slPctStr + ")", color = color.new(SL_COLOR, 60), textcolor = TEXT_BRIGHT, style = label.style_label_left, size = lblSize)
    lbTP1   := label.new(labelPos, tp1Price, "TP1 " + str.tostring(tp1Price, format.mintick) + " (+" + tp1PctStr + ")", color = color.new(TP_COLOR, 60), textcolor = TEXT_BRIGHT, style = label.style_label_left, size = lblSize)
    lbTP2   := label.new(labelPos, tp2Price, "TP2 " + str.tostring(tp2Price, format.mintick) + " (+" + tp2PctStr + ")", color = color.new(TP_COLOR, 60), textcolor = TEXT_BRIGHT, style = label.style_label_left, size = lblSize)
    lbTP3   := label.new(labelPos, tp3Price, "TP3 " + str.tostring(tp3Price, format.mintick) + " (+" + tp3PctStr + ")", color = color.new(TP_COLOR, 60), textcolor = TEXT_BRIGHT, style = label.style_label_left, size = lblSize)
    hasTradeDrawings := true

    if showLastOnly
        histLines.push(lineEntry), histLines.push(lineSL), histLines.push(lineTP1), histLines.push(lineTP2), histLines.push(lineTP3)
        histLabels.push(lbEntry), histLabels.push(lbSL), histLabels.push(lbTP1), histLabels.push(lbTP2), histLabels.push(lbTP3)

if showLevelsInput and hasTradeDrawings and not (confirmedBullBreak or confirmedBearBreak)
    bool shouldExtend = tradeOpen
    if shouldExtend
        int newLineEnd  = bar_index + labelOffsetInput
        int newLabelPos = bar_index + labelOffsetInput + 2
        if not na(lineEntry)
            line.set_x2(lineEntry, newLineEnd)
        if not na(lineSL)
            line.set_x2(lineSL, newLineEnd)
        if not na(lineTP1)
            line.set_x2(lineTP1, newLineEnd)
        if not na(lineTP2)
            line.set_x2(lineTP2, newLineEnd)
        if not na(lineTP3)
            line.set_x2(lineTP3, newLineEnd)
        if not na(lbEntry)
            label.set_x(lbEntry, newLabelPos)
        if not na(lbSL)
            label.set_x(lbSL, newLabelPos)
        if not na(lbTP1)
            label.set_x(lbTP1, newLabelPos)
        if not na(lbTP2)
            label.set_x(lbTP2, newLabelPos)
        if not na(lbTP3)
            label.set_x(lbTP3, newLabelPos)

// TP/SL label güncellemeleri (orijinal)
if showLevelsInput and not na(lineTP1) and tp1Hit
    line.set_color(lineTP1, TP_HIT_COLOR)
    line.set_style(lineTP1, line.style_solid)
    if not na(lbTP1) and tp1Hit and not tp1Hit[1]
        string tp1PctUpd = str.tostring(math.abs(tp1Price - entryPrice) / entryPrice * 100, "#.##") + "%"
        label.set_text(lbTP1, "TP1 ✓ " + str.tostring(tp1Price, format.mintick) + " (+" + tp1PctUpd + ")")
        label.set_color(lbTP1, color.new(TP_HIT_COLOR, 60))
if showLevelsInput and not na(lineTP2) and tp2Hit
    line.set_color(lineTP2, TP_HIT_COLOR)
    line.set_style(lineTP2, line.style_solid)
    if not na(lbTP2) and tp2Hit and not tp2Hit[1]
        string tp2PctUpd = str.tostring(math.abs(tp2Price - entryPrice) / entryPrice * 100, "#.##") + "%"
        label.set_text(lbTP2, "TP2 ✓ " + str.tostring(tp2Price, format.mintick) + " (+" + tp2PctUpd + ")")
        label.set_color(lbTP2, color.new(TP_HIT_COLOR, 60))
if showLevelsInput and not na(lineTP3) and tp3Hit
    line.set_color(lineTP3, TP_HIT_COLOR)
    line.set_style(lineTP3, line.style_solid)
    if not na(lbTP3) and tp3Hit and not tp3Hit[1]
        string tp3PctUpd = str.tostring(math.abs(tp3Price - entryPrice) / entryPrice * 100, "#.##") + "%"
        label.set_text(lbTP3, "TP3 ✓ " + str.tostring(tp3Price, format.mintick) + " (+" + tp3PctUpd + ")")
        label.set_color(lbTP3, color.new(TP_HIT_COLOR, 60))
if showLevelsInput and not na(lbSL) and slHit and not slHit[1]
    string slPctUpd = str.tostring(math.abs(slPriceOrig - entryPrice) / entryPrice * 100, "#.##") + "%"
    label.set_text(lbSL, "SL ✗ " + str.tostring(slPriceOrig, format.mintick) + " (−" + slPctUpd + ")")

// ══════════════════════════════════════
// SİNYAL GÖRSELLEŞTİRME  (DEĞİŞTİRİLDİ: MTP AL/SAT ETİKETLERİ SİLİNDİ)
// ══════════════════════════════════════
// if showSignalsInput and confirmedBullBreak
//     label sigLbl = label.new(bar_index, low, "AL", ...)
// if showSignalsInput and confirmedBearBreak
//     label sigLbl = label.new(bar_index, high, "SAT", ...)

bgcolor(showBgInput and channelActive and breakoutDir == 0 ? color.new(lineColorInput, BG_TRANSPARENCY) : na, title = "Aktif Desen Arkaplanı")

// Filigran (orijinal)
if barstate.islast and showWatermarkInput
    var wmTable = table.new(position = position.bottom_center, columns = 1, rows = 1, bgcolor = color.new(color.black, 100), border_color = color.new(color.black, 100), border_width = 0, frame_color = color.new(color.black, 100), frame_width = 0)
    table.cell(wmTable, 0, 0, "MONEY TRADER PATTERN", text_color = WM_COLOR, text_size = size.normal, text_halign = text.align_center, bgcolor = color.new(color.black, 100))

// Alarmlar (orijinal)
if confirmedBullBreak
    alert(formatAlertMsg("buy", "🟢", breakStrength, entryPrice, slPrice, tp1Price, tp2Price, tp3Price), alert.freq_once_per_bar_close)
if confirmedBearBreak
    alert(formatAlertMsg("sell", "🔴", breakStrength, entryPrice, slPrice, tp1Price, tp2Price, tp3Price), alert.freq_once_per_bar_close)
if channelJustDetected_local
    string tickerStr = syminfo.tickerid
    string tfStr = timeframe.period
    string priceStr = str.tostring(close, format.mintick)
    string jsonMsg = '{"action":"pattern","ticker":"' + tickerStr + '","price":' + priceStr + ',"tf":"' + tfStr + '"}'
    string textMsg = "🟡 DESEN TESPİT EDİLDİ | " + tickerStr + " | TF: " + tfStr + " | Fiyat: " + priceStr
    alert(webhookInput ? jsonMsg : textMsg, alert.freq_once_per_bar_close)

if tp1Hit and not tp1Hit[1]
    alert(formatEventMsg("tp1_hit", "🎯"), alert.freq_once_per_bar_close)
if tp2Hit and not tp2Hit[1]
    alert(formatEventMsg("tp2_hit", "🎯"), alert.freq_once_per_bar_close)
if tp3Hit and not tp3Hit[1]
    alert(formatEventMsg("tp3_hit", "🏆"), alert.freq_once_per_bar_close)
if slHit and not slHit[1]
    alert(formatEventMsg("sl_hit", "🛑"), alert.freq_once_per_bar_close)

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// (3) ATOMIC PULSE (2. scriptin alt kısımları) — ORİJİNAL (PULSE UP/DOWN durur)
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

// --- GELİŞTİRİLMİŞ AYARLAR ---
volLength = input.int(20, "Hacim Periyodu")
volMult = input.float(2.5, "Hacim Çarpanı (Min. 2.0 önerilir)")

atrLength = input.int(14, "ATR Periyodu")
atrMult = input.float(1.8, "Volatilite Çarpanı (1.5 - 2.0)")

minBodyRatio = input.float(0.6, "Min. Gövde Oranı (0.6 = %60 doluluk)")
cooldownBars = input.int(10, "Sinyal Soğuma Süresi (Mum Sayısı)")

VolSma = ta.sma(volume, volLength)
isVolumeSpike = volume > VolSma * volMult

atrVal = ta.atr(atrLength)
bodyRange = math.abs(close - open)
isVolatilitySpike = bodyRange > atrVal * atrMult

totalRange = high - low
isStrongBody = totalRange != 0 and (bodyRange / totalRange) > minBodyRatio

rsiFast = ta.rsi(close, 5)
rsiSlow = ta.rsi(close, 14)
isMomentumUp = rsiFast > rsiSlow and rsiFast > rsiFast[1]
isMomentumDown = rsiFast < rsiSlow and rsiFast < rsiFast[1]

isNewHigh = close > ta.highest(high[1], 5)
isNewLow = close < ta.lowest(low[1], 5)

var int LastSignalBar = 0
isCooldown = (bar_index - LastSignalBar) < cooldownBars

longPulse  = isVolumeSpike and isVolatilitySpike and isStrongBody and isMomentumUp and isNewHigh and not isCooldown and close > open
shortPulse = isVolumeSpike and isVolatilitySpike and isStrongBody and isMomentumDown and isNewLow and not isCooldown and close < open

if longPulse or shortPulse
    LastSignalBar := bar_index

plotshape(longPulse, title="ATOMIC LONG", style=shape.labelup, location=location.belowbar, color=color.green, textcolor=color.white, text="PULSE UP", size=size.small)
plotshape(shortPulse, title="ATOMIC SHORT", style=shape.labeldown, location=location.abovebar, color=color.red, textcolor=color.white, text="PULSE DOWN", size=size.small)

plot(volume, color=color.new(#003af7, 0), style=plot.style_columns, title="Volume")
plot(VolSma, color=color.rgb(255, 51, 0), linewidth=1, title="Vol SMA")

alertcondition(longPulse, title="Atomic V2 Long Alert", message="ATOMIC PULSE: YUKARI KIRILIM TESPİT EDİLDİ!")
alertcondition(shortPulse, title="Atomic V2 Short Alert", message="ATOMIC PULSE: AŞAĞI KIRILIM TESPİT EDİLDİ!")

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// (4) SÜPER KIRILIM — SADECE (EMA AL) + (PULSE UP) birlikteyse
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
superKirilim = alSinyali and longPulse

if superKirilim
    label.new(
         bar_index, low,
         "SÜPER KIRILIM\n" + str.tostring(low, "#.##"),
         color=color.new(color.lime, 0),
         textcolor=color.black,
         style=label.style_label_up,
         yloc=yloc.belowbar,
         size=size.normal
    )

alertcondition(superKirilim, title="SÜPER KIRILIM", message="SÜPER KIRILIM: EMA AL + PULSE UP aynı mumda!")

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// (5) KLASİK FORMASYONLAR — İKİLİ/ÜÇLÜ TEPE ve DİP
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

GRP_CLASSIC = "📊 Klasik Formasyonlar"

classicShowInput = input.bool(true, "Klasik Formasyonları Göster", group=GRP_CLASSIC)
classicTolAtr    = input.float(0.80, "Tepe/Dip Toleransı ATR", minval=0.10, maxval=3.00, step=0.10, group=GRP_CLASSIC)
classicMinBars   = input.int(10, "Min Formasyon Barı", minval=3, maxval=100, group=GRP_CLASSIC)
classicMaxAge    = input.int(80, "Çizgi Uzatma Barı", minval=20, maxval=300, group=GRP_CLASSIC)
classicAlerts    = input.bool(true, "Formasyon Alarmı", group=GRP_CLASSIC)

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// FORMASYON DURUM DEĞİŞKENLERİ
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

var bool  clsActive = false
var int   clsAge    = 0
var int   clsType   = 0
var line  clsNeckLine = na
var label clsLbl1 = na
var label clsLbl2 = na
var label clsLbl3 = na
var label clsSigLbl = na

clsAge := clsActive ? clsAge + 1 : 0

// Her bar sıfırlanan tespit değişkenleri
int   clsDet       = 0        // 2 double top, 3 triple top, -2 double bottom, -3 triple bottom
float clsNeck      = na
float clsP1        = na
float clsP2        = na
float clsP3        = na
int   clsB1        = na
int   clsB2        = na
int   clsB3        = na

float clsTol = atr20 * classicTolAtr

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ÜÇLÜ TEPE TESPİTİ
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

if classicShowInput and not clsActive and hiPrices.size() >= 3 and loPrices.size() >= 2
    float t1 = hiPrices.get(0)
    float t2 = hiPrices.get(1)
    float t3 = hiPrices.get(2)

    int b1 = hiBars.get(0)
    int b2 = hiBars.get(1)
    int b3 = hiBars.get(2)

    int leftB  = math.min(math.min(b1, b2), b3)
    int rightB = math.max(math.max(b1, b2), b3)

    bool topsSimilar = math.abs(t1 - t2) <= clsTol and math.abs(t2 - t3) <= clsTol
    bool enoughBars  = rightB - leftB >= classicMinBars

    if topsSimilar and enoughBars
        float neckLow = na
        int neckCount = 0

        for i = 0 to loPrices.size() - 1
            float lp = loPrices.get(i)
            int lb = loBars.get(i)

            if lb > leftB and lb < rightB
                neckLow := na(neckLow) ? lp : math.min(neckLow, lp)
                neckCount += 1

        if neckCount >= 2 and not na(neckLow) and close < neckLow and barstate.isconfirmed
            clsDet  := 3
            clsNeck := neckLow
            clsP1   := t1
            clsP2   := t2
            clsP3   := t3
            clsB1   := b1
            clsB2   := b2
            clsB3   := b3

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// İKİLİ TEPE TESPİTİ
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

if classicShowInput and not clsActive and clsDet == 0 and hiPrices.size() >= 2 and loPrices.size() >= 1
    float t1 = hiPrices.get(0)
    float t2 = hiPrices.get(1)

    int b1 = hiBars.get(0)
    int b2 = hiBars.get(1)

    int leftB  = math.min(b1, b2)
    int rightB = math.max(b1, b2)

    bool topsSimilar = math.abs(t1 - t2) <= clsTol
    bool enoughBars  = rightB - leftB >= classicMinBars

    if topsSimilar and enoughBars
        float neckLow = na
        int neckCount = 0

        for i = 0 to loPrices.size() - 1
            float lp = loPrices.get(i)
            int lb = loBars.get(i)

            if lb > leftB and lb < rightB
                neckLow := na(neckLow) ? lp : math.min(neckLow, lp)
                neckCount += 1

        if neckCount >= 1 and not na(neckLow) and close < neckLow and barstate.isconfirmed
            clsDet  := 2
            clsNeck := neckLow
            clsP1   := t1
            clsP2   := t2
            clsB1   := b1
            clsB2   := b2

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ÜÇLÜ DİP TESPİTİ
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

if classicShowInput and not clsActive and clsDet == 0 and loPrices.size() >= 3 and hiPrices.size() >= 2
    float d1 = loPrices.get(0)
    float d2 = loPrices.get(1)
    float d3 = loPrices.get(2)

    int b1 = loBars.get(0)
    int b2 = loBars.get(1)
    int b3 = loBars.get(2)

    int leftB  = math.min(math.min(b1, b2), b3)
    int rightB = math.max(math.max(b1, b2), b3)

    bool bottomsSimilar = math.abs(d1 - d2) <= clsTol and math.abs(d2 - d3) <= clsTol
    bool enoughBars     = rightB - leftB >= classicMinBars

    if bottomsSimilar and enoughBars
        float neckHigh = na
        int neckCount = 0

        for i = 0 to hiPrices.size() - 1
            float hp = hiPrices.get(i)
            int hb = hiBars.get(i)

            if hb > leftB and hb < rightB
                neckHigh := na(neckHigh) ? hp : math.max(neckHigh, hp)
                neckCount += 1

        if neckCount >= 2 and not na(neckHigh) and close > neckHigh and barstate.isconfirmed
            clsDet  := -3
            clsNeck := neckHigh
            clsP1   := d1
            clsP2   := d2
            clsP3   := d3
            clsB1   := b1
            clsB2   := b2
            clsB3   := b3

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// İKİLİ DİP TESPİTİ
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

if classicShowInput and not clsActive and clsDet == 0 and loPrices.size() >= 2 and hiPrices.size() >= 1
    float d1 = loPrices.get(0)
    float d2 = loPrices.get(1)

    int b1 = loBars.get(0)
    int b2 = loBars.get(1)

    int leftB  = math.min(b1, b2)
    int rightB = math.max(b1, b2)

    bool bottomsSimilar = math.abs(d1 - d2) <= clsTol
    bool enoughBars     = rightB - leftB >= classicMinBars

    if bottomsSimilar and enoughBars
        float neckHigh = na
        int neckCount = 0

        for i = 0 to hiPrices.size() - 1
            float hp = hiPrices.get(i)
            int hb = hiBars.get(i)

            if hb > leftB and hb < rightB
                neckHigh := na(neckHigh) ? hp : math.max(neckHigh, hp)
                neckCount += 1

        if neckCount >= 1 and not na(neckHigh) and close > neckHigh and barstate.isconfirmed
            clsDet  := -2
            clsNeck := neckHigh
            clsP1   := d1
            clsP2   := d2
            clsB1   := b1
            clsB2   := b2

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ÇİZİM TEMİZLEME
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

if clsDet != 0
    label.delete(clsLbl1)
    label.delete(clsLbl2)
    label.delete(clsLbl3)
    label.delete(clsSigLbl)
    line.delete(clsNeckLine)

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// FORMASYON ÇİZİMLERİ
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

// ÜÇLÜ TEPE
if clsDet == 3
    clsActive := true
    clsAge := 0
    clsType := 3

    clsNeckLine := line.new(clsB3, clsNeck, bar_index + 30, clsNeck, color=color.new(color.red, 20), width=2, style=line.style_dashed)

    clsLbl1 := label.new(clsB1, clsP1, "3T", color=color.new(color.red, 0), textcolor=color.white, style=label.style_label_down, size=size.tiny)
    clsLbl2 := label.new(clsB2, clsP2, "3T", color=color.new(color.red, 0), textcolor=color.white, style=label.style_label_down, size=size.tiny)
    clsLbl3 := label.new(clsB3, clsP3, "3T", color=color.new(color.red, 0), textcolor=color.white, style=label.style_label_down, size=size.tiny)

    clsSigLbl := label.new(bar_index, high, "ÜÇLÜ\nTEPE\nSAT", color=color.new(color.red, 10), textcolor=color.white, style=label.style_label_down, yloc=yloc.abovebar, size=size.normal)

    if classicAlerts
        alert("ÜÇLÜ TEPE SAT | " + syminfo.tickerid + " | Boyun: " + str.tostring(clsNeck, format.mintick), alert.freq_once_per_bar_close)

// İKİLİ TEPE
if clsDet == 2
    clsActive := true
    clsAge := 0
    clsType := 2

    clsNeckLine := line.new(clsB2, clsNeck, bar_index + 30, clsNeck, color=color.new(color.red, 30), width=2, style=line.style_dashed)

    clsLbl1 := label.new(clsB1, clsP1, "2T", color=color.new(color.red, 0), textcolor=color.white, style=label.style_label_down, size=size.tiny)
    clsLbl2 := label.new(clsB2, clsP2, "2T", color=color.new(color.red, 0), textcolor=color.white, style=label.style_label_down, size=size.tiny)

    clsSigLbl := label.new(bar_index, high, "İKİLİ\nTEPE\nSAT", color=color.new(color.red, 10), textcolor=color.white, style=label.style_label_down, yloc=yloc.abovebar, size=size.normal)

    if classicAlerts
        alert("İKİLİ TEPE SAT | " + syminfo.tickerid + " | Boyun: " + str.tostring(clsNeck, format.mintick), alert.freq_once_per_bar_close)

// ÜÇLÜ DİP
if clsDet == -3
    clsActive := true
    clsAge := 0
    clsType := -3

    clsNeckLine := line.new(clsB3, clsNeck, bar_index + 30, clsNeck, color=color.new(color.green, 20), width=2, style=line.style_dashed)

    clsLbl1 := label.new(clsB1, clsP1, "3D", color=color.new(color.green, 0), textcolor=color.white, style=label.style_label_up, size=size.tiny)
    clsLbl2 := label.new(clsB2, clsP2, "3D", color=color.new(color.green, 0), textcolor=color.white, style=label.style_label_up, size=size.tiny)
    clsLbl3 := label.new(clsB3, clsP3, "3D", color=color.new(color.green, 0), textcolor=color.white, style=label.style_label_up, size=size.tiny)

    clsSigLbl := label.new(bar_index, low, "ÜÇLÜ\nDİP\nAL", color=color.new(color.green, 10), textcolor=color.white, style=label.style_label_up, yloc=yloc.belowbar, size=size.normal)

    if classicAlerts
        alert("ÜÇLÜ DİP AL | " + syminfo.tickerid + " | Boyun: " + str.tostring(clsNeck, format.mintick), alert.freq_once_per_bar_close)

// İKİLİ DİP
if clsDet == -2
    clsActive := true
    clsAge := 0
    clsType := -2

    clsNeckLine := line.new(clsB2, clsNeck, bar_index + 30, clsNeck, color=color.new(color.green, 30), width=2, style=line.style_dashed)

    clsLbl1 := label.new(clsB1, clsP1, "2D", color=color.new(color.green, 0), textcolor=color.white, style=label.style_label_up, size=size.tiny)
    clsLbl2 := label.new(clsB2, clsP2, "2D", color=color.new(color.green, 0), textcolor=color.white, style=label.style_label_up, size=size.tiny)

    clsSigLbl := label.new(bar_index, low, "İKİLİ\nDİP\nAL", color=color.new(color.green, 10), textcolor=color.white, style=label.style_label_up, yloc=yloc.belowbar, size=size.normal)

    if classicAlerts
        alert("İKİLİ DİP AL | " + syminfo.tickerid + " | Boyun: " + str.tostring(clsNeck, format.mintick), alert.freq_once_per_bar_close)

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// AKTİF FORMASYON ÇİZGİ UZATMA
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

if clsActive and not na(clsNeckLine) and clsAge < classicMaxAge
    line.set_x2(clsNeckLine, bar_index + 5)

if clsActive and clsAge >= classicMaxAge
    clsActive := false
    clsType := 0

Editor is loading...
Leave a Comment