Bank Index Two-Way Momentum Strategy

KERNEL VWAP CVD RSI ATR
Erstellungsdatum: 2025-10-29 15:57:59 zuletzt geändert: 2025-10-29 15:57:59
Kopie: 0 Klicks: 151
2
konzentrieren Sie sich auf
319
Anhänger

Bank Index Two-Way Momentum Strategy Bank Index Two-Way Momentum Strategy

Was soll das für eine Strategie?

Die Strategie ist wie ein superflexibler “Changing Dragon Trader”. Sie ist nicht wie die starren, einseitigen Strategien, sondern kann jederzeit in verschiedene Richtungen wechseln, je nachdem, wie der Markt aussieht. Stellen Sie sich vor, Sie hätten einen alten Fahrer, der sowohl fahren als auch rückwärts fahren kann und den Markt stetig mitreiten kann, egal in welche Richtung der Markt geht!

Kerntechnologie-Indikatoren-Palette

Die Strategie basiert auf einer Kombination von fünf überragenden Indikatoren:

  • Kernel zurück“Wenn wir einen Preis für ein Produkt festlegen, ist es wie eine GPS-Navigation, die die Richtung der Preise anzeigt”.
  • VWAPDie Zahlen zeigen, wo sich das “große Geld” befindet.
  • CVD-KonjunktivitätsschwächeDas ist die Wahrheit über die Macht der Kauf- und Verkaufsposition.
  • Relative Stärke und Schwäche des RSIDas ist die einzige Möglichkeit, die es gibt, um zu verhindern, dass man in extremen Positionen aufgeht.
  • ATR tatsächliche SchwankungsbreiteDas ist eine sehr wichtige Frage, die ich mir stellen möchte.

Mehrfache Bestätigung

Das klügste an dieser Strategie ist die “Mehrfachbestätigung”, die, wie beim Kauf eines Hauses, nach dem Grundstück, nach dem Wohnungsbau und nach dem Preis fragt:

  • Gleichgewicht der Trends ((Kernel + VWAP doppelte Bestätigung)
  • (Entweder eine Ausdehnung oder eine kontinuierliche Zunahme)
  • K-Linien-Form-Übergang (≥ 60% der Einheiten, um die Kreuzstern-Falle zu vermeiden)
  • Zeitfensterbeschränkung (Handel nur zwischen 9:15 und 15:15 Uhr, um die Chaos von Börsenöffnungen und -schließungen zu vermeiden)

️ Intelligentes Risikomanagement

Die Risikokontrolle dieser Strategie ist auf Lehrbuch-Ebene!

  • Dynamische VerlustminderungATR, Festpunktzahl, Schwingung der Höhen und Tiefen, drei Modi zur Auswahl
  • Abgabe von SchrottDas erste Ziel ist es, 50% der Positionen zu beseitigen, damit die Gewinne laufen können.
  • VerlustverfolgungDas ist ein sehr schwieriger Prozess.
  • Tägliche BegrenzungEs gibt nur zwei Geschäfte, bei denen es zu einem Verlust von bis zu fünf Dollar kommt.
  • VermögensverwaltungDas Risiko pro Transaktion ist unter 1%.

Empfehlungen für Einsatz in der Praxis

Wenn Sie diese Strategie nutzen möchten, sollten Sie sich folgende Punkte merken:

  1. Die beste PeriodeDie 5:5-Minuten-Charts sind am besten geeignet, um kurzfristige Schwankungen zu erfassen, aber nicht zu häufig.
  2. Anwendbare Sorten: Speziell für Bankindex-Futures konzipiert, aber auch für andere Indizes
  3. Zeit der TransaktionEs gibt keine anderen Möglichkeiten, wie man sich die K-Strahl-Linien vor dem Schalter anpassen kann.
  4. PositionsregelungEs wird empfohlen, 25 bis 75 Verträge pro Hand zu vergeben, maximal nicht mehr als 200.

Die größte Eigenschaft dieser Strategie ist, dass man “angreifen und zurückschrecken kann”, dass der Bullenmarkt mehr kann, der Bärenmarkt leer, und der Schaukelmarkt ist nicht zu fürchten!

Strategiequellcode
/*backtest
start: 2025-01-01 00:00:00
end: 2025-10-28 00:00:00
period: 10m
basePeriod: 10m
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/

//@version=5
strategy("BankNifty LONG & SHORT Multi-Confluence", 
     shorttitle="BN Long-Short",
     overlay=true)

// ═══════════════════════════════════════════════════════════
// 📊 STRATEGY INFO
// ═══════════════════════════════════════════════════════════
// Timeframe: 5-MINUTE CHART (Recommended)
// Direction: LONG & SHORT (Both directions)
// Asset: BankNifty Futures
// Style: Intraday Momentum Trading
// ═══════════════════════════════════════════════════════════

// ═══════════════════════════════════════════════════════════
// ⚙️ INPUT PARAMETERS
// ═══════════════════════════════════════════════════════════

// Trading Direction
tradingDirection = input.string("Both", "Trading Direction", 
     options=["Long Only", "Short Only", "Both"], group="🎯 Strategy Type")

// Trading Hours (IST)
startHour = input.int(9, "Start Hour", minval=0, maxval=23, group="⏰ Trading Session")
startMinute = input.int(15, "Start Minute", minval=0, maxval=59, group="⏰ Trading Session")
endHour = input.int(15, "End Hour", minval=0, maxval=23, group="⏰ Trading Session")
endMinute = input.int(15, "End Minute", minval=0, maxval=59, group="⏰ Trading Session")
avoidFirstCandles = input.int(2, "Skip First N Candles", minval=0, maxval=10, group="⏰ Trading Session")

// Position Sizing
lotSize = input.int(25, "Lot Size", minval=15, maxval=75, group="💰 Position Management")
maxContracts = input.int(75, "Max Contracts", minval=25, maxval=200, step=25, group="💰 Position Management")
riskPercent = input.float(1.0, "Risk % Per Trade", minval=0.5, maxval=3.0, step=0.1, group="💰 Position Management")

// Kernel Regression
kernelLength = input.int(20, "Kernel Length", minval=10, maxval=50, group="📈 Indicators")

// VWAP
vwapSource = input.string("Session", "VWAP Type", options=["Session", "Rolling"], group="📈 Indicators")
vwapRollingLength = input.int(20, "Rolling VWAP Length", minval=10, maxval=100, group="📈 Indicators")

// Volume
volumeLength = input.int(20, "Volume MA Length", minval=10, maxval=50, group="📊 Volume")
volumeMultiplier = input.float(1.5, "Volume Spike", minval=1.1, maxval=3.0, step=0.1, group="📊 Volume")

// CVD
useCVD = input.bool(true, "Use CVD Filter", group="📊 Volume")
cvdLength = input.int(10, "CVD Smoothing", minval=5, maxval=30, group="📊 Volume")

// RSI
useRSI = input.bool(true, "Use RSI Filter", group="🎯 Filters")
rsiLength = input.int(14, "RSI Length", minval=7, maxval=30, group="🎯 Filters")
rsiOverbought = input.int(70, "RSI Overbought", minval=60, maxval=85, group="🎯 Filters")
rsiOversold = input.int(30, "RSI Oversold", minval=15, maxval=40, group="🎯 Filters")

// Price Action
candleBodyPercent = input.float(0.6, "Min Body %", minval=0.4, maxval=0.9, step=0.05, group="🎯 Filters")
minCandlePoints = input.float(20.0, "Min Candle Size", minval=10.0, maxval=100.0, step=5.0, group="🎯 Filters")

// Stop Loss
stopLossType = input.string("ATR", "Stop Loss Type", options=["Fixed", "ATR", "Swing"], group="🛡️ Exits")
atrLength = input.int(14, "ATR Length", minval=7, maxval=30, group="🛡️ Exits")
atrMultiplier = input.float(1.5, "ATR Multiplier", minval=0.5, maxval=3.0, step=0.1, group="🛡️ Exits")
fixedStopLoss = input.float(50.0, "Fixed SL (points)", minval=20.0, maxval=200.0, step=10.0, group="🛡️ Exits")
swingLookback = input.int(10, "Swing Lookback", minval=5, maxval=30, group="🛡️ Exits")

// Targets
rrTarget1 = input.float(1.5, "Target 1 R:R", minval=0.5, maxval=3.0, step=0.1, group="🛡️ Exits")
rrTarget2 = input.float(2.5, "Target 2 R:R", minval=1.0, maxval=5.0, step=0.5, group="🛡️ Exits")
partialExitPercent = input.int(50, "Partial Exit %", minval=25, maxval=75, step=5, group="🛡️ Exits")

// Trailing
useTrailing = input.bool(true, "Trailing Stop", group="🛡️ Exits")
trailActivationRR = input.float(1.2, "Activate at R:R", minval=0.5, maxval=2.0, step=0.1, group="🛡️ Exits")
trailStopRR = input.float(0.8, "Trail Stop R:R", minval=0.3, maxval=1.5, step=0.1, group="🛡️ Exits")

// Risk Management
maxTradesPerDay = input.int(5, "Max Trades/Day", minval=1, maxval=20, group="🚨 Risk")
maxConsecutiveLosses = input.int(2, "Stop After Losses", minval=1, maxval=5, group="🚨 Risk")
dailyLossLimit = input.float(2.5, "Daily Loss %", minval=1.0, maxval=10.0, step=0.5, group="🚨 Risk")
dailyProfitTarget = input.float(5.0, "Daily Target %", minval=2.0, maxval=20.0, step=0.5, group="🚨 Risk")

// ═══════════════════════════════════════════════════════════
// 📊 INDICATORS
// ═══════════════════════════════════════════════════════════

// Kernel Regression
kernel = ta.linreg(close, kernelLength, 0)
kernelSlope = kernel - kernel[1]

// VWAP
vwapValue = vwapSource == "Session" ? ta.vwap(close) : ta.sma(hlc3, vwapRollingLength)
vwapSlope = vwapValue - vwapValue[1]

// Volume
volumeMA = ta.sma(volume, volumeLength)
highVolume = volume > volumeMA * volumeMultiplier
volumeIncreasing = volume > volume[1] and volume[1] > volume[2]

// CVD
buyVolume = close > open ? volume : 0
sellVolume = close < open ? volume : 0
volumeDelta = buyVolume - sellVolume
cvd = ta.cum(volumeDelta)
cvdMA = ta.sma(cvd, cvdLength)

// RSI
rsi = ta.rsi(close, rsiLength)

// ATR
atr = ta.atr(atrLength)

// Price Action
candleRange = high - low
candleBody = math.abs(close - open)
bodyPercent = candleRange > 0 ? candleBody / candleRange : 0

// Swing High/Low
swingHigh = ta.highest(high, swingLookback)
swingLow = ta.lowest(low, swingLookback)

// ═══════════════════════════════════════════════════════════
// ⏰ TIME MANAGEMENT
// ═══════════════════════════════════════════════════════════

currentMinutes = hour * 60 + minute
startMinutes = startHour * 60 + startMinute
endMinutes = endHour * 60 + endMinute
tradingTime = currentMinutes >= startMinutes and currentMinutes <= endMinutes

var int barsToday = 0
newDay = ta.change(dayofweek)
if newDay
    barsToday := 0
if tradingTime
    barsToday += 1

skipInitialBars = barsToday <= avoidFirstCandles
forceExitTime = currentMinutes >= (endMinutes - 5)

// ═══════════════════════════════════════════════════════════
// 💼 POSITION TRACKING
// ═══════════════════════════════════════════════════════════

var int todayTrades = 0
var int consecutiveLosses = 0
var float todayPnL = 0.0
var float entryPrice = na
var int entryBar = 0
var float stopLoss = na
var float target1 = na
var float target2 = na
var float trailStop = na
var bool target1Hit = false
var bool trailActive = false

// Daily Reset
if newDay
    todayTrades := 0
    consecutiveLosses := 0
    todayPnL := 0.0

// Track P&L
if strategy.closedtrades > 0 and strategy.closedtrades != strategy.closedtrades[1]
    lastPnL = strategy.closedtrades.profit(strategy.closedtrades - 1)
    todayPnL += lastPnL
    if lastPnL < 0
        consecutiveLosses += 1
    else
        consecutiveLosses := 0

// Risk Limits
lossLimit = strategy.initial_capital * (dailyLossLimit / 100)
profitTarget = strategy.initial_capital * (dailyProfitTarget / 100)
hitDailyTarget = todayPnL >= profitTarget
hitLossLimit = math.abs(todayPnL) >= lossLimit

canTrade = todayTrades < maxTradesPerDay and
     consecutiveLosses < maxConsecutiveLosses and
     not hitDailyTarget and
     not hitLossLimit and
     tradingTime and
     not skipInitialBars and
     strategy.position_size == 0

// ═══════════════════════════════════════════════════════════
// 🎯 LONG ENTRY CONDITIONS
// ═══════════════════════════════════════════════════════════

// Bullish Trend
longTrend = kernelSlope > 0 and close > kernel
longVWAP = close > vwapValue and vwapSlope > 0
longCVD = useCVD ? cvd > cvdMA and ta.rising(cvd, 2) : true
longRSI = useRSI ? rsi > rsiOversold and rsi < rsiOverbought : true
longVolume = highVolume or volumeIncreasing
longCandle = close > open and bodyPercent >= candleBodyPercent and 
     candleRange >= minCandlePoints and close >= (high - (candleRange * 0.25))

longSignal = longTrend and longVWAP and longCVD and longRSI and longVolume and longCandle and canTrade and
     (tradingDirection == "Long Only" or tradingDirection == "Both")

// ═══════════════════════════════════════════════════════════
// 🎯 SHORT ENTRY CONDITIONS
// ═══════════════════════════════════════════════════════════

// Bearish Trend
shortTrend = kernelSlope < 0 and close < kernel
shortVWAP = close < vwapValue and vwapSlope < 0
shortCVD = useCVD ? cvd < cvdMA and ta.falling(cvd, 2) : true
shortRSI = useRSI ? rsi < rsiOverbought and rsi > rsiOversold : true
shortVolume = highVolume or volumeIncreasing
shortCandle = close < open and bodyPercent >= candleBodyPercent and 
     candleRange >= minCandlePoints and close <= (low + (candleRange * 0.25))

shortSignal = shortTrend and shortVWAP and shortCVD and shortRSI and shortVolume and shortCandle and canTrade and
     (tradingDirection == "Short Only" or tradingDirection == "Both")

// ═══════════════════════════════════════════════════════════
// 💰 POSITION SIZING
// ═══════════════════════════════════════════════════════════

calcPositionSize(stopDistance) =>
    riskAmount = strategy.initial_capital * (riskPercent / 100)
    contracts = math.floor(riskAmount / stopDistance)
    math.min(contracts, maxContracts)

// ═══════════════════════════════════════════════════════════
// 📥 LONG ENTRY
// ═══════════════════════════════════════════════════════════

if longSignal
    entryPrice := close
    entryBar := bar_index
    
    // Calculate Stop Loss
    if stopLossType == "ATR"
        stopLoss := close - (atr * atrMultiplier)
    else if stopLossType == "Swing"
        stopLoss := math.min(swingLow, close - (atr * atrMultiplier))
    else
        stopLoss := close - fixedStopLoss
    
    risk = entryPrice - stopLoss
    target1 := entryPrice + (risk * rrTarget1)
    target2 := entryPrice + (risk * rrTarget2)
    
    qty = calcPositionSize(risk)
    
    trailStop := stopLoss
    target1Hit := false
    trailActive := false
    todayTrades += 1
    
    strategy.entry("LONG", strategy.long, qty=qty, comment="Long-" + str.tostring(todayTrades))

// ═══════════════════════════════════════════════════════════
// 📥 SHORT ENTRY
// ═══════════════════════════════════════════════════════════

if shortSignal
    entryPrice := close
    entryBar := bar_index
    
    // Calculate Stop Loss
    if stopLossType == "ATR"
        stopLoss := close + (atr * atrMultiplier)
    else if stopLossType == "Swing"
        stopLoss := math.max(swingHigh, close + (atr * atrMultiplier))
    else
        stopLoss := close + fixedStopLoss
    
    risk = stopLoss - entryPrice
    target1 := entryPrice - (risk * rrTarget1)
    target2 := entryPrice - (risk * rrTarget2)
    
    qty = calcPositionSize(risk)
    
    trailStop := stopLoss
    target1Hit := false
    trailActive := false
    todayTrades += 1
    
    strategy.entry("SHORT", strategy.short, qty=qty, comment="Short-" + str.tostring(todayTrades))

// ═══════════════════════════════════════════════════════════
// 🏃 TRAILING STOP (LONG)
// ═══════════════════════════════════════════════════════════

if strategy.position_size > 0 and useTrailing
    unrealizedProfit = close - entryPrice
    risk = entryPrice - stopLoss
    
    if unrealizedProfit >= (risk * trailActivationRR) and not trailActive
        trailActive := true
        trailStop := close - (risk * trailStopRR)
    
    if trailActive
        newTrailStop = close - (risk * trailStopRR)
        if newTrailStop > trailStop
            trailStop := newTrailStop

// ═══════════════════════════════════════════════════════════
// 🏃 TRAILING STOP (SHORT)
// ═══════════════════════════════════════════════════════════

if strategy.position_size < 0 and useTrailing
    unrealizedProfit = entryPrice - close
    risk = stopLoss - entryPrice
    
    if unrealizedProfit >= (risk * trailActivationRR) and not trailActive
        trailActive := true
        trailStop := close + (risk * trailStopRR)
    
    if trailActive
        newTrailStop = close + (risk * trailStopRR)
        if newTrailStop < trailStop
            trailStop := newTrailStop

// ═══════════════════════════════════════════════════════════
// 📤 LONG EXIT
// ═══════════════════════════════════════════════════════════

if strategy.position_size > 0
    activeSL = trailActive and useTrailing ? trailStop : stopLoss
    
    // Stop Loss
    if low <= activeSL
        strategy.close("LONG", comment="Long-SL")
    
    // Target 1
    else if high >= target1 and not target1Hit
        exitQty = math.floor(strategy.position_size * (partialExitPercent / 100))
        strategy.close("LONG", qty=exitQty, comment="Long-T1")
        target1Hit := true
        stopLoss := entryPrice
    
    // Target 2
    else if high >= target2
        strategy.close("LONG", comment="Long-T2")
    
    // Force Exit
    else if forceExitTime
        strategy.close("LONG", comment="Long-EOD")

// ═══════════════════════════════════════════════════════════
// 📤 SHORT EXIT
// ═══════════════════════════════════════════════════════════

if strategy.position_size < 0
    activeSL = trailActive and useTrailing ? trailStop : stopLoss
    
    // Stop Loss
    if high >= activeSL
        strategy.close("SHORT", comment="Short-SL")
    
    // Target 1
    else if low <= target1 and not target1Hit
        exitQty = math.floor(math.abs(strategy.position_size) * (partialExitPercent / 100))
        strategy.close("SHORT", qty=exitQty, comment="Short-T1")
        target1Hit := true
        stopLoss := entryPrice
    
    // Target 2
    else if low <= target2
        strategy.close("SHORT", comment="Short-T2")
    
    // Force Exit
    else if forceExitTime
        strategy.close("SHORT", comment="Short-EOD")

// ═══════════════════════════════════════════════════════════
// ⚠️ REVERSAL EXIT
// ═══════════════════════════════════════════════════════════

longReversal = strategy.position_size > 0 and (close < kernel and kernelSlope < 0 or close < vwapValue)
shortReversal = strategy.position_size < 0 and (close > kernel and kernelSlope > 0 or close > vwapValue)

if longReversal and target1Hit
    strategy.close("LONG", comment="Long-Rev")
if shortReversal and target1Hit
    strategy.close("SHORT", comment="Short-Rev")

// ═══════════════════════════════════════════════════════════
// 🎨 VISUALIZATION
// ═══════════════════════════════════════════════════════════

// Indicators
plot(kernel, "Kernel", color=color.new(color.purple, 0), linewidth=2)
plot(vwapValue, "VWAP", color=color.new(color.orange, 0), linewidth=2)

kernelUpper = kernel + atr
kernelLower = kernel - atr
plot(kernelUpper, "K Upper", color=color.new(color.purple, 70), linewidth=1, style=plot.style_circles)
plot(kernelLower, "K Lower", color=color.new(color.purple, 70), linewidth=1, style=plot.style_circles)

// Signals
plotshape(longSignal, "LONG", shape.triangleup, location.belowbar, 
     color=color.new(color.lime, 0), size=size.normal, text="LONG")
plotshape(shortSignal, "SHORT", shape.triangledown, location.abovebar, 
     color=color.new(color.red, 0), size=size.normal, text="SHORT")

// Position Levels
posColor = strategy.position_size > 0 ? color.blue : strategy.position_size < 0 ? color.orange : na
plot(strategy.position_size != 0 ? entryPrice : na, "Entry", 
     color=color.new(posColor, 0), style=plot.style_linebr, linewidth=2)

slColor = strategy.position_size > 0 ? color.red : color.fuchsia
plot(strategy.position_size != 0 ? stopLoss : na, "SL", 
     color=color.new(slColor, 0), style=plot.style_linebr, linewidth=2)

t1Color = strategy.position_size > 0 ? color.green : color.aqua
plot(strategy.position_size != 0 ? target1 : na, "T1", 
     color=color.new(t1Color, 0), style=plot.style_linebr, linewidth=1)
plot(strategy.position_size != 0 ? target2 : na, "T2", 
     color=color.new(t1Color, 0), style=plot.style_linebr, linewidth=2)

plot(strategy.position_size != 0 and trailActive ? trailStop : na, "Trail", 
     color=color.new(color.yellow, 0), style=plot.style_linebr, linewidth=2)

// Volume
barcolor(highVolume ? color.new(color.blue, 70) : na)

// Background
bgcolor(tradingTime ? color.new(color.green, 98) : color.new(color.gray, 95))
bgcolor(strategy.position_size > 0 ? color.new(color.blue, 97) : 
     strategy.position_size < 0 ? color.new(color.orange, 97) : na)
bgcolor(hitDailyTarget ? color.new(color.green, 92) : hitLossLimit ? color.new(color.red, 92) : na)

// ═══════════════════════════════════════════════════════════
// 📊 STATS TABLE
// ═══════════════════════════════════════════════════════════

var table stats = table.new(position.top_right, 2, 11, border_width=1)

if barstate.islast
    // Header
    table.cell(stats, 0, 0, "📊 LONG & SHORT", bgcolor=color.blue, text_color=color.white, text_size=size.small)
    table.cell(stats, 1, 0, "STRATEGY", bgcolor=color.blue, text_color=color.white, text_size=size.small)
    
    // Trades
    table.cell(stats, 0, 1, "Trades", text_size=size.small)
    table.cell(stats, 1, 1, str.tostring(todayTrades) + "/" + str.tostring(maxTradesPerDay), 
         bgcolor=todayTrades >= maxTradesPerDay ? color.red : color.green, text_color=color.white, text_size=size.small)
    
    // Losses
    table.cell(stats, 0, 2, "Losses", text_size=size.small)
    table.cell(stats, 1, 2, str.tostring(consecutiveLosses), 
         bgcolor=consecutiveLosses >= maxConsecutiveLosses ? color.red : color.green, 
         text_color=color.white, text_size=size.small)
    
    // P&L
    pnlPct = (todayPnL / strategy.initial_capital) * 100
    table.cell(stats, 0, 3, "P&L", text_size=size.small)
    table.cell(stats, 1, 3, str.tostring(todayPnL, "#,###") + "\n" + str.tostring(pnlPct, "#.##") + "%", 
         bgcolor=todayPnL > 0 ? color.green : todayPnL < 0 ? color.red : color.gray, 
         text_color=color.white, text_size=size.small)
    
    // Position
    table.cell(stats, 0, 4, "Position", text_size=size.small)
    posText = strategy.position_size > 0 ? "LONG\n" + str.tostring(strategy.position_size) : 
         strategy.position_size < 0 ? "SHORT\n" + str.tostring(math.abs(strategy.position_size)) : "FLAT"
    posBg = strategy.position_size > 0 ? color.blue : strategy.position_size < 0 ? color.orange : color.gray
    table.cell(stats, 1, 4, posText, bgcolor=posBg, text_color=color.white, text_size=size.small)
    
    if strategy.position_size != 0
        // Entry
        table.cell(stats, 0, 5, "Entry", text_size=size.small)
        table.cell(stats, 1, 5, str.tostring(entryPrice, "#.##"), text_size=size.small)
        
        // Live P&L
        livePnL = strategy.position_size > 0 ? (close - entryPrice) * strategy.position_size : 
             (entryPrice - close) * math.abs(strategy.position_size)
        livePct = strategy.position_size > 0 ? ((close - entryPrice) / entryPrice) * 100 : 
             ((entryPrice - close) / entryPrice) * 100
        table.cell(stats, 0, 6, "Live P&L", text_size=size.small)
        table.cell(stats, 1, 6, str.tostring(livePnL, "#,###") + "\n" + str.tostring(livePct, "#.##") + "%", 
             bgcolor=livePnL > 0 ? color.green : color.red, text_color=color.white, text_size=size.small)
        
        // Bars
        bars = bar_index - entryBar
        table.cell(stats, 0, 7, "Bars", text_size=size.small)
        table.cell(stats, 1, 7, str.tostring(bars), text_size=size.small)
        
        // Stop
        table.cell(stats, 0, 8, "Stop", text_size=size.small)
        table.cell(stats, 1, 8, str.tostring(trailActive ? trailStop : stopLoss, "#.##") + 
             (trailActive ? " 🟡" : ""), text_size=size.small)
        
        // T1
        table.cell(stats, 0, 9, "T1", text_size=size.small)
        table.cell(stats, 1, 9, str.tostring(target1, "#.##") + (target1Hit ? " ✓" : ""), text_size=size.small)
        
        // T2
        table.cell(stats, 0, 10, "T2", text_size=size.small)
        table.cell(stats, 1, 10, str.tostring(target2, "#.##"), text_size=size.small)

// ═══════════════════════════════════════════════════════════
// 🔔 ALERTS
// ═══════════════════════════════════════════════════════════

alertcondition(longSignal, "🟢 LONG SIGNAL", "LONG Entry Signal")
alertcondition(shortSignal, "🔴 SHORT SIGNAL", "SHORT Entry Signal")
alertcondition(longReversal or shortReversal, "⚠️ REVERSAL", "Reversal Detected")