Système de trading multi-indicateurs adaptatif de suivi de tendance à volatilité

ATR SMA RSI DCA 烛台模式 趋势跟踪 波动率适应 多时间周期 止损 止盈
Date de création: 2025-04-11 13:41:56 Dernière modification: 2025-04-11 13:41:56
Copier: 3 Nombre de clics: 378
2
Suivre
319
Abonnés

Système de trading multi-indicateurs adaptatif de suivi de tendance à volatilité Système de trading multi-indicateurs adaptatif de suivi de tendance à volatilité

Aperçu

Le système de trading de suivi de tendance multi-indicateurs auto-adaptatif est une stratégie de trading quantitative conçue pour les marchés à forte volatilité, qui combine des indicateurs techniques dynamiquement ajustés avec un mécanisme de gestion du risque avancé. Le cœur de la stratégie consiste à adapter dynamiquement les paramètres de la ligne de moyenne mobile via l’ATR (amplitude réelle moyenne) pour s’adapter aux fluctuations du marché, tout en intégrant des fonctionnalités telles que le RSI, les filtres d’achat et de vente excessifs, l’identification des tendances sur plusieurs périodes et la construction progressive d’une position (DCA) pour former un cadre de trading complet. Cette stratégie est particulièrement adaptée aux environnements à forte volatilité tels que les marchés à terme et offre un mode d’opération flexible pour les transactions intra-journées et les périodes de négociation d’ondes.

Principe de stratégie

Les principes fondamentaux de la stratégie sont basés sur les modules clés suivants:

  1. Système homogène mobile adaptatifLa stratégie consiste à utiliser des courbes moyennes simples, rapides et lentes (SMA), dont la longueur est ajustée dynamiquement par l’ATR. Dans les environnements à forte volatilité, la longueur de la courbe moyenne est raccourcie pour réagir rapidement aux variations du marché. Dans les environnements à faible volatilité, la longueur de la courbe moyenne est allongée pour réduire le bruit.

  2. Filtre de dynamique RSI: Vérifier les signaux d’entrée via le RSI (indicateur de la relative force et de la faiblesse) pour s’assurer que la direction des transactions est en accord avec la dynamique du marché. La fonction peut être activée ou désactivée et prend en charge des paramètres RSI personnalisés (tels que la longueur 14, les surachats 60 et les surventes 40).

  3. Identification de la forme de l’effondrement: Le système est capable d’identifier les formes fortes de bullish ou bearish engloutissement, et de combiner le volume d’échange et l’intensité de la gamme pour la vérification. Afin d’éviter les faux signaux, le système saute les transactions lorsque deux formes opposées se produisent simultanément.

  4. Confirmation de la tendance à plusieurs périodes: Aligner sélectivement les signaux de négociation avec les tendances SMA sur une période de 15 minutes, ajouter une couche de mécanisme de confirmation et améliorer la qualité des transactions.

  5. La mise en place progressive du mécanisme de DCA: permet de nombreuses entrées dans la direction de la tendance, prend en charge un maximum de nombre d’entrées prédéfinies (par exemple 4 entrées), l’intervalle d’entrée est basé sur le multiplicateur ATR. Ce mécanisme permet d’optimiser le coût moyen dans un marché où la tendance se poursuit.

  6. Gestion des risques de haut niveau

    • Stop initial: basé sur le réglage ATR (généralement 2 à 3,5 fois), un multiplicateur de stop fixe plus large est appliqué sur la colonne d’entrée (comme 1,3) [2].
    • Suivi des arrêts de perte: utilisation de l’écart et de la multiplication de la base ATR, ajustement dynamique à mesure que les bénéfices augmentent (par exemple, lorsque les bénéfices dépassent l’ATR, le multiplicateur est réduit de 0,5 à 0,3).
    • Objectif de stop: fixé à un certain multiple du prix d’entrée ± ATR (exemple 1.2).
    • Période de refroidissement: période de suspension après la sortie (de 0 à 5 minutes) pour éviter les transactions excessives.
    • Durée de la position minimale: pour assurer la continuité de la transaction, un certain nombre de colonnes (par exemple, 2 à 10) doivent être conservées.
  7. Logique d’exécution de la transaction: le système privilégie les signaux de forme moyenne mobile ou décroissante ((selon le choix de l’utilisateur) et applique des filtres de trafic, de volatilité et de temps. Pour assurer la qualité d’entrée, des conditions de trafic de pointe ont également été ajoutées ((trafic>1.2)*Le 10e numéro de la SMA)

Avantages stratégiques

  1. La capacité d’adaptation du marchéLa stratégie est capable de s’adapter automatiquement aux différentes conditions du marché en ajustant dynamiquement les paramètres de l’indicateur technique ATR, ce qui lui permet de rester efficace dans des environnements à forte et à faible volatilité.

  2. Filtrage de la qualité du signalLe mécanisme de filtrage multicouche (RSI, tendances multi-périodes, volume et volatilité) réduit efficacement les faux signaux et améliore la qualité des transactions.

  3. Une admission flexible: Prise en charge de l’utilisation prioritaire des signaux mobiles en équilibre ou en déclin selon les préférences de l’utilisateur, et optimisation des points d’entrée dans la direction de la tendance via la fonction DCA.

  4. Gestion dynamique des risquesLes points d’arrêt et les points d’arrêt de suivi s’adaptent à la fluctuation du marché et à la dynamique des bénéfices des transactions, tout en protégeant le capital et en laissant suffisamment de place à la tendance.

  5. Outils de visualisation et de débogageLes stratégies offrent une couverture graphique riche, des tableaux de bord en temps réel et des tableaux de démarrage pour aider les utilisateurs à optimiser les paramètres et à comprendre la logique de négociation.

  6. Conception modulaire: Les utilisateurs peuvent activer ou désactiver diverses fonctions en fonction de leurs préférences (filtrage RSI, reconnaissance de la forme de l’effondrement, tendance à plusieurs périodes de temps, etc.), hautement personnalisable.

  7. Contrôle de l’entréeLe filtrage des pics de transaction assure l’entrée en bourse uniquement lors d’activités significatives du marché, tandis que le mécanisme de période de refroidissement empêche les transactions excessives.

Risque stratégique

  1. Paramètre SensibilitéLa stratégie utilise plusieurs paramètres (longueur moyenne, cycle ATR, seuil RSI, etc.) dont la configuration a un impact significatif sur la performance. Une combinaison inappropriée de paramètres peut entraîner une suradaptation des données historiques.

Comment faire ?: effectuer des tests d’optimisation de paramètres étendus, mais en évitant l’optimisation excessive; utiliser des tests de marche avant et des tests hors échantillon pour vérifier la robustesse de la stratégie.

  1. Risques liés à la transition des marchés: Lorsqu’un modèle de marché change rapidement (par exemple, d’une tendance à une secousse), une stratégie peut générer des pertes continues avant de s’adapter à un nouvel environnement.

*Comment faire ?*Considérer l’ajout d’un mécanisme d’identification de l’état du marché, en utilisant différents ensembles de paramètres dans différents environnements de marché; mettre en œuvre des restrictions de risque globales, telles que la suspension des transactions après une perte maximale quotidienne ou une perte consécutive.

  1. Points de glissement et problèmes de liquiditéLe risque d’augmentation des points de glissement et de baisse de la liquidité est plus élevé dans les marchés à forte fréquence de négociation et à forte volatilité.

Comment faire ?: inclure des estimations de points de glissement et de commissions réels dans la rétroévaluation; éviter de négocier à des moments de faible liquidité; envisager d’utiliser des listes de prix limites plutôt que des listes de prix du marché.

  1. Complexité du systèmeLes logiques et les combinaisons de conditions multicouches ajoutent de la complexité à la stratégie et peuvent être difficiles à comprendre et à maintenir.

*Comment faire ?*Utilisez les outils de débogage fournis par la stratégie pour surveiller de près la performance de chaque composant; maintenez de bonnes annotations de code; considérez l’efficacité indépendante de chaque composant testé de manière modulaire.

  1. Risques liés à la surventeLes mécanismes DCA et la génération fréquente de signaux peuvent entraîner des transactions excessives et augmenter les coûts de transaction.

Comment faire ?: fixer un délai de refroidissement et une durée de détention minimale appropriés; prendre en compte strictement les coûts de transaction lors du réexamen; examiner et optimiser régulièrement les critères d’admission.

Direction d’optimisation

  1. Le renforcement de l’apprentissage automatiqueL’introduction d’algorithmes d’optimisation par paramètres auto-adaptatifs, tels que l’optimisation Bayesian ou l’algorithme génétique, pour trouver automatiquement la meilleure combinaison de paramètres pour différents environnements de marché. Cela réduira le besoin d’optimisation manuelle et améliorera l’adaptabilité des stratégies aux changements du marché.

  2. Catégorisation des environnements de marchéDévelopper un système de classification des états du marché (trends, oscillations, hautes et basses fluctuations, etc.) et prévoir la configuration optimale des paramètres pour chaque état. Cette méthode permet d’ajuster plus rapidement le comportement stratégique lors de la transformation du marché et de réduire le retard d’adaptation.

  3. Gestion améliorée des positions: l’introduction d’algorithmes de gestion de position plus complexes, tels que l’ajustement de position dynamique basé sur les règles de Kelly ou l’intensité du mouvement. Cela peut optimiser l’utilisation des fonds, augmenter l’exposition lors de signaux forts et réduire le risque lors de signaux faibles.

  4. Intégration des indicateurs alternatifs: tester l’efficacité d’autres indicateurs techniques, tels que les bandes de Bollinger, le MACD ou le nuage d’Ichimoku, en complément ou en remplacement des systèmes existants. Des indicateurs différents peuvent fournir des signaux plus précis dans certaines conditions de marché.

  5. Intégration des données émotionnellesConsidérez l’ajout d’indicateurs de l’humeur du marché, tels que l’indice de volatilité VIX ou les données du marché des options, pour identifier à l’avance les transformations potentielles du marché. Ces sources de données externes peuvent fournir des informations que les indicateurs techniques traditionnels ne peuvent pas capturer.

  6. Analyse de la corrélation entre plusieurs actifs: développer des analyses de corrélation entre les classes d’actifs, utiliser les signaux d’un marché pour vérifier ou renforcer les décisions de négociation d’un autre marché pertinent. Par exemple, utiliser les variations des prix des marchandises pour confirmer les tendances des secteurs d’actions concernés.

  7. Optimiser l’efficacité du calculRéorganisation du code pour améliorer l’efficacité des calculs, en particulier pour les stratégies à haute fréquence. Cela inclut l’optimisation du calcul de l’ATR, de l’ordre d’évaluation des conditions et de la réduction des calculs redondants inutiles.

Résumer

Le système de négociation de suivi de tendance à taux de volatilité auto-adaptatif multi-indicateurs représente une approche de négociation quantitative complète et flexible, qui répond efficacement aux différents environnements de marché grâce à un ajustement dynamique des paramètres et un mécanisme de filtrage à plusieurs niveaux. Le principal avantage de la stratégie réside dans son adaptabilité et son cadre de gestion du risque intégré, ce qui la rend particulièrement adaptée aux marchés à terme très volatils.

La stratégie intègre plusieurs outils d’analyse technique classiques (mobile, RSI, et bullish) et ajoute des éléments de trading quantitatif moderne (paramètres adaptatifs, analyse de plusieurs périodes de temps, DCA) pour former un système équilibré. En contrôlant minutieusement le moment d’entrée, en optimisant les stratégies d’entrée multiples et en ajustant dynamiquement les niveaux de stop loss, la stratégie permet de tirer le meilleur parti des opportunités de tendances du marché tout en protégeant le capital.

Cependant, la complexité de la stratégie entraîne également des défis en termes de sensibilité aux paramètres et de maintien du système. Les investisseurs doivent effectuer un retour d’expérience et un test avant de mettre en œuvre la stratégie et être prêts à ajuster les paramètres en fonction des changements du marché. Les orientations d’optimisation futures comprennent l’introduction de la technologie d’apprentissage automatique pour optimiser automatiquement les paramètres, l’ajout d’un système de classification des environnements de marché et l’amélioration des algorithmes de gestion de position.

Dans l’ensemble, la stratégie fournit un cadre de trading quantifié solide, adapté aux traders expérimentés, qui sont personnalisés en fonction de leurs besoins spécifiques et de leurs préférences en matière de risque, et qui recherchent un avantage de trading cohérent dans les marchés financiers en évolution rapide d’aujourd’hui.

Code source de la stratégie
/*backtest
start: 2024-04-11 00:00:00
end: 2025-04-10 00:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/

//@version=6
strategy('Dskyz Adaptive Futures Elite (DAFE) - Updated', 
         overlay=true, 
         default_qty_type=strategy.fixed, 
         initial_capital=1000000, 
         commission_value=0, 
         slippage=1, 
         pyramiding=10)

// === INPUTS ===

// Moving Average Settings
fastLength       = input.int(9, '[MA] Fast MA Length', minval=1)
slowLength       = input.int(19, '[MA] Slow MA Length', minval=1)

// RSI Settings
useRSI           = input.bool(false, '[RSI Settings] Use RSI Filter')
rsiLength        = input.int(14, 'RSI Length', minval=1)
rsiOverbought    = input.int(60, 'RSI Overbought', minval=50, maxval=100)
rsiOversold      = input.int(40, 'RSI Oversold', minval=0, maxval=50)
rsiLookback      = input.int(1, 'RSI Lookback', minval=1)

// Pattern Settings
usePatterns      = input.bool(true, '[Pattern Settings] Use Candlestick Patterns')
patternLookback  = input.int(19, 'Pattern Lookback Bars', minval=1)

// Filter Settings
useTrendFilter   = input.bool(true, '[Filter Settings] Use 15m Trend Filter')
minVolume        = input.int(10, 'Minimum Volume', minval=1)
volatilityThreshold = input.float(1.0, 'Volatility Threshold (%)', minval=0.1, step=0.1) / 100
tradingStartHour = input.int(9, 'Trading Start Hour (24h)', minval=0, maxval=23)
tradingEndHour   = input.int(16, 'Trading End Hour (24h)', minval=0, maxval=23)

// DCA Settings
useDCA           = input.bool(false, '[DCA Settings] Use DCA')
maxTotalEntries  = input.int(4, 'Max Total Entries per Direction', minval=1)
dcaMultiplier    = input.float(1.0, 'DCA ATR Multiplier', minval=0.1, step=0.1)

// Signal Settings
signalPriority   = input.string('MA', '[Signal Settings] Signal Priority', options=['Pattern', 'MA'])
minBarsBetweenSignals = input.int(5, 'Min Bars Between Signals', minval=1)
plotMode         = input.string('Potential Signals', 'Plot Mode', options=['Potential Signals', 'Actual Entries'])

// Exit Settings
trailOffset      = input.float(0.5, '[Exit Settings] Trailing Stop Offset ATR Multiplier', minval=0.01, step=0.01)
trailPointsMult  = input.float(0.5, 'Trailing Stop Points ATR Multiplier', minval=0.01, step=0.01)
profitTargetATRMult = input.float(1.2, 'Profit Target ATR Multiplier', minval=0.1, step=0.1)  // Profit target factor
fixedStopMultiplier  = input.float(1.3, 'Fixed Stop Multiplier', minval=0.5, step=0.1)    // Fixed stop multiplier

// General Settings
debugLogging     = input.bool(true, '[General Settings] Enable Debug Logging')
fixedQuantity    = input.int(2, 'Trade Quantity', minval=1)
cooldownMinutes  = input.int(0, 'Cooldown Minutes', minval=0)

// ATR Settings – Use Dynamic ATR or fixed value
useDynamicATR    = input.bool(true, title="Use Dynamic ATR")
userATRPeriod    = input.int(7, title="ATR Period (if not using dynamic)", minval=1)
defaultATR       = timeframe.isminutes and timeframe.multiplier <= 2 ? 5 :
                   timeframe.isminutes and timeframe.multiplier <= 5 ? 7 : 10
atrPeriod        = useDynamicATR ? defaultATR : userATRPeriod

// === TRADE TRACKING VARIABLES ===
var int lastSignalBar   = 0
var int lastSignalType  = 0         // 1 for long, -1 for short
var int entryBarIndex   = 0
var bool inLongTrade    = false
var bool inShortTrade   = false

// DCA Tracking Variables
var int longEntryCount  = 0
var int shortEntryCount = 0
var float longInitialEntryPrice = na
var float shortInitialEntryPrice = na
var float longEntryATR  = na
var float shortEntryATR = na
var float long_stop_price = na
var float short_stop_price = na

// Signal Plotting Variables
var int lastLongPlotBar = 0
var int lastShortPlotBar = 0

// === CALCULATIONS ===

// Volume and Time Filters
volumeOk    = volume >= minVolume
currentHour = hour(time)
timeWindow  = currentHour >= tradingStartHour and currentHour <= tradingEndHour

// Additional Entry Filter: Volume Spike Condition
volumeSpike = volume > 1.2 * ta.sma(volume, 10)

// ATR & Volatility Calculations
atr         = ta.atr(atrPeriod)
volatility  = nz(atr / close, 0)
volatilityOk= volatility <= volatilityThreshold

// Adaptive MA Lengths
fastLengthAdaptive = math.round(fastLength / (1 + volatility))
slowLengthAdaptive = math.round(slowLength / (1 + volatility))
fastLengthSafe     = math.max(1, not na(atr) ? fastLengthAdaptive : fastLength)
slowLengthSafe     = math.max(1, not na(atr) ? slowLengthAdaptive : slowLength)
fastMA             = ta.sma(close, fastLengthSafe)
slowMA             = ta.sma(close, slowLengthSafe)

// RSI Calculation
rsi               = ta.rsi(close, rsiLength)
rsiCrossover      = ta.crossover(rsi, rsiOversold)
rsiCrossunder     = ta.crossunder(rsi, rsiOverbought)
rsiLongOk         = not useRSI or (rsiCrossover and rsi[rsiLookback] < 70)
rsiShortOk        = not useRSI or (rsiCrossunder and rsi[rsiLookback] > 30)

// 15m Trend Filter
[fastMA15m, slowMA15m] = request.security(syminfo.tickerid, '15', [ta.sma(close, fastLength), ta.sma(close, slowLength)])
trend15m = fastMA15m > slowMA15m ? 1 : fastMA15m < slowMA15m ? -1 : 0

// Candlestick Patterns
isBullishEngulfing() =>
    close[1] < open[1] and close > open and open < close[1] and close > open[1] and (close - open) > (open[1] - close[1]) * 0.8

isBearishEngulfing() =>
    close[1] > open[1] and close < open and open > close[1] and close < open[1] and (open - close) > (close[1] - open[1]) * 0.8

// Pattern Strength Calculation
patternStrength(isBull) =>
    bull = isBull ? 1 : 0
    bear = isBull ? 0 : 1
    volumeStrength = volume > ta.sma(volume, 10) ? 1 : 0
    rangeStrength  = (high - low) > ta.sma(high - low, 10) ? 1 : 0
    strength = bull * (volumeStrength + rangeStrength) - bear * (volumeStrength + rangeStrength)
    strength

bullStrength = patternStrength(true)
bearStrength = patternStrength(false)

// Detect Patterns
bullishEngulfingOccurred = ta.barssince(isBullishEngulfing()) <= patternLookback and bullStrength >= 1
bearishEngulfingOccurred = ta.barssince(isBearishEngulfing()) <= patternLookback and bearStrength <= -1
patternConflict          = bullishEngulfingOccurred and bearishEngulfingOccurred

// MA Conditions with Trend & RSI Filters
maAbove      = close > fastMA and fastMA > slowMA and close > close[1]
maBelow      = close < fastMA and fastMA < slowMA and close < close[1]
trendLongOk  = not useTrendFilter or trend15m >= 0
trendShortOk = not useTrendFilter or trend15m <= 0

// Signal Priority Logic
bullPattern  = usePatterns and bullishEngulfingOccurred
bearPattern  = usePatterns and bearishEngulfingOccurred
bullMA       = maAbove and trendLongOk and rsiLongOk
bearMA       = maBelow and trendShortOk and rsiShortOk

longCondition  = false
shortCondition = false

if signalPriority == 'Pattern'
    longCondition  := bullPattern or (not bearPattern and bullMA)
    shortCondition := bearPattern or (not bullPattern and bearMA)
else
    longCondition  := bullMA or (not bearMA and bullPattern)
    shortCondition := bearMA or (not bullMA and bearPattern)

// Apply Filters and require volume spike for quality entries
longCondition  := longCondition and volumeOk and volumeSpike and timeWindow and volatilityOk and not patternConflict
shortCondition := shortCondition and volumeOk and volumeSpike and timeWindow and volatilityOk and not patternConflict

// Update Trade Status
if strategy.position_size > 0
    inLongTrade := true
    inShortTrade := false
else if strategy.position_size < 0
    inShortTrade := true
    inLongTrade := false
else
    inLongTrade := false
    inShortTrade := false

// Entry Checks
canTrade      = strategy.position_size == 0
validQuantity = fixedQuantity > 0
quantity      = fixedQuantity

// Prevent Multiple Alerts Per Bar
var bool alertSent = false
if barstate.isnew
    alertSent := false

// Cooldown Logic
var float lastExitTime = na
if strategy.position_size == 0 and strategy.position_size[1] != 0
    lastExitTime := time
canEnter = na(lastExitTime) or ((time - lastExitTime) / 60000 >= cooldownMinutes)

// === ENTRY LOGIC ===
if canTrade and validQuantity and not alertSent and canEnter and barstate.isconfirmed
    if longCondition and not shortCondition and (lastSignalBar != bar_index or lastSignalType != 1)
        strategy.entry('Long', strategy.long, qty=quantity)
        longInitialEntryPrice := close
        longEntryATR         := atr
        longEntryCount       := 1
        alert('Enter Long', alert.freq_once_per_bar)
        alertSent            := true
        lastSignalBar        := bar_index
        lastSignalType       := 1
        entryBarIndex        := bar_index

    else if shortCondition and not longCondition and (lastSignalBar != bar_index or lastSignalType != -1)
        strategy.entry('Short', strategy.short, qty=quantity)
        shortInitialEntryPrice := close
        shortEntryATR          := atr
        shortEntryCount        := 1
        alert('Enter Short', alert.freq_once_per_bar)
        alertSent             := true
        lastSignalBar         := bar_index
        lastSignalType        := -1
        entryBarIndex         := bar_index


// === DCA LOGIC (IF ENABLED) ===
if useDCA
    if strategy.position_size > 0 and longEntryCount < maxTotalEntries and bullMA and rsi < 70
        nextDCALevel = longInitialEntryPrice - longEntryCount * longEntryATR * dcaMultiplier
        if close <= nextDCALevel
            strategy.entry('Long DCA ' + str.tostring(longEntryCount), strategy.long, qty=quantity)
            longEntryCount := longEntryCount + 1
    if strategy.position_size < 0 and shortEntryCount < maxTotalEntries and bearMA and rsi > 30
        nextDCALevel = shortInitialEntryPrice + shortEntryATR * shortEntryCount * dcaMultiplier
        if close >= nextDCALevel
            strategy.entry('Short DCA ' + str.tostring(shortEntryCount), strategy.short, qty=quantity)
            shortEntryCount := shortEntryCount + 1

// === RESET DCA VARIABLES ON EXIT ===
if strategy.position_size == 0 and strategy.position_size[1] != 0
    longEntryCount := 0
    shortEntryCount := 0
    longInitialEntryPrice := na
    shortInitialEntryPrice := na
    longEntryATR := na
    shortEntryATR := na

// === FIXED STOP-LOSS CALCULATION (WIDER INITIAL STOP) ===
long_stop_price  := strategy.position_avg_price - atr * fixedStopMultiplier
short_stop_price := strategy.position_avg_price + atr * fixedStopMultiplier

// === ADJUST TRAILING POINTS BASED ON PROFIT ===
profitLong  = strategy.position_size > 0 ? close - strategy.position_avg_price : 0
profitShort = strategy.position_size < 0 ? strategy.position_avg_price - close : 0
trailPointsMultAdjusted       = profitLong > atr ? 0.3 : profitLong > atr * 0.66 ? 0.4 : trailPointsMult      // For long positions
trailPointsMultAdjustedShort  = profitShort > atr ? 0.3 : profitShort > atr * 0.66 ? 0.4 : trailPointsMult   // For short positions
trailPointsLong  = atr * trailPointsMultAdjusted
trailPointsShort = atr * trailPointsMultAdjustedShort

// === EXIT LOGIC ===
// On the entry bar, always use the fixed stop; thereafter, use a combination of fixed stop, trailing stop, and a profit target.
// Profit Target: For longs, exit at avg_entry + atr * profitTargetATRMult; for shorts, exit at avg_entry - atr * profitTargetATRMult.
if strategy.position_size > 0
    if bar_index == entryBarIndex
        if debugLogging
            log.info("Long exit on entry bar: fixed stop applied. Price=" + str.tostring(close))
        strategy.exit('Long Exit', 'Long', stop=long_stop_price)
    else
        if debugLogging
            log.info("Long Trade: profit=" + str.tostring(profitLong) + ", ATR=" + str.tostring(atr))
        strategy.exit('Long Exit', 'Long', 
             stop=long_stop_price, 
             limit = strategy.position_avg_price + atr * profitTargetATRMult,
             trail_points=trailPointsLong, 
             trail_offset=atr * trailOffset)
            
if strategy.position_size < 0
    if bar_index == entryBarIndex
        if debugLogging
            log.info("Short exit on entry bar: fixed stop applied. Price=" + str.tostring(close))
        strategy.exit('Short Exit', 'Short', stop=short_stop_price)
    else
        if debugLogging
            log.info("Short Trade: profit=" + str.tostring(profitShort) + ", ATR=" + str.tostring(atr))
        strategy.exit('Short Exit', 'Short', 
             stop=short_stop_price, 
             limit = strategy.position_avg_price - atr * profitTargetATRMult,
             trail_points=trailPointsShort, 
             trail_offset=atr * trailOffset)

// === FORCE CLOSE ON LAST BAR (OPTIONAL) ===
if barstate.islast
    if strategy.position_size > 0
        strategy.close('Long', comment='Forced Exit')
    if strategy.position_size < 0
        strategy.close('Short', comment='Forced Exit')

// === SIGNAL PLOTTING LOGIC ===
plotLongSignal  = longCondition and canTrade and (bar_index - lastLongPlotBar >= minBarsBetweenSignals or lastLongPlotBar == 0)
plotShortSignal = shortCondition and canTrade and (bar_index - lastShortPlotBar >= minBarsBetweenSignals or lastShortPlotBar == 0)

if plotLongSignal
    lastLongPlotBar := bar_index
if plotShortSignal
    lastShortPlotBar := bar_index

// Define plotting conditions based on plotMode
plotLongShape  = plotMode == 'Potential Signals' ? plotLongSignal : strategy.position_size > 0 and strategy.position_size[1] <= 0
plotShortShape = plotMode == 'Potential Signals' ? plotShortSignal : strategy.position_size < 0 and strategy.position_size[1] >= 0

// === VISUALIZATION ===
plot(fastMA, color=color.blue, linewidth=2, title='Fast MA')
plot(slowMA, color=color.red, linewidth=2, title='Slow MA')

var float longSL  = na
var float shortSL = na
if strategy.position_size > 0
    longSL := math.max(longSL, high - trailPointsLong)
else
    longSL := na
plot(longSL, color=color.green, style=plot.style_stepline, title='Long SL')

if strategy.position_size < 0
    shortSL := math.min(shortSL, low + trailPointsShort)
else
    shortSL := na
plot(shortSL, color=color.red, style=plot.style_stepline, title='Short SL')

bgcolor(timeWindow ? color.new(color.blue, 95) : na, title="Trading Hours Highlight")
if plotLongShape
    label.new(bar_index, low, "Buy", yloc=yloc.belowbar, color=color.green, textcolor=color.white, style=label.style_label_up)
if plotShortShape
    label.new(bar_index, high, "Sell", yloc=yloc.abovebar, color=color.red, textcolor=color.white, style=label.style_label_down)

// === DEBUG TABLE ===
var table debugTable = table.new(position.top_right, 3, 10, bgcolor=color.rgb(0, 0, 0, 80), border_color=color.white, border_width=1)
if barstate.islast
    table.cell(debugTable, 0, 0, 'Signal', text_color=color.rgb(168, 168, 168), bgcolor=color.rgb(50, 50, 50))
    table.cell(debugTable, 1, 0, 'Status', text_color=color.rgb(168, 168, 168), bgcolor=color.rgb(50, 50, 50))
    table.cell(debugTable, 2, 0, 'Priority', text_color=color.rgb(168, 168, 168), bgcolor=color.rgb(50, 50, 50))

    table.cell(debugTable, 0, 1, 'MA Long', text_color=color.blue)
    table.cell(debugTable, 1, 1, bullMA ? 'Yes' : 'No', text_color=bullMA ? color.green : color.red)
    table.cell(debugTable, 2, 1, signalPriority == 'MA' ? 'High' : 'Low', text_color=color.white)

    table.cell(debugTable, 0, 2, 'MA Short', text_color=color.blue)
    table.cell(debugTable, 1, 2, bearMA ? 'Yes' : 'No', text_color=bearMA ? color.green : color.red)
    table.cell(debugTable, 2, 2, signalPriority == 'MA' ? 'High' : 'Low', text_color=color.white)

    table.cell(debugTable, 0, 3, 'Bull Pattern', text_color=color.blue)
    table.cell(debugTable, 1, 3, bullPattern ? 'Yes' : 'No', text_color=bullPattern ? color.green : color.red)
    table.cell(debugTable, 2, 3, signalPriority == 'Pattern' ? 'High' : 'Low', text_color=color.white)

    table.cell(debugTable, 0, 4, 'Bear Pattern', text_color=color.blue)
    table.cell(debugTable, 1, 4, bearPattern ? 'Yes' : 'No', text_color=bearPattern ? color.green : color.red)
    table.cell(debugTable, 2, 4, signalPriority == 'Pattern' ? 'High' : 'Low', text_color=color.white)

    table.cell(debugTable, 0, 5, 'Filters', text_color=color.rgb(168, 168, 168), bgcolor=color.rgb(50, 50, 50))
    table.cell(debugTable, 1, 5, 'Status', text_color=color.rgb(168, 168, 168), bgcolor=color.rgb(50, 50, 50))
    table.cell(debugTable, 2, 5, '', text_color=color.white, bgcolor=color.rgb(50, 50, 50))

    table.cell(debugTable, 0, 6, 'Time Window', text_color=color.blue)
    table.cell(debugTable, 1, 6, timeWindow ? 'OK' : 'Closed', text_color=timeWindow ? color.green : color.red)
    table.cell(debugTable, 2, 6, str.tostring(currentHour) + 'h', text_color=color.white)

    table.cell(debugTable, 0, 7, 'Volume', text_color=color.blue)
    table.cell(debugTable, 1, 7, volumeOk ? 'OK' : 'Low', text_color=volumeOk ? color.green : color.red)
    table.cell(debugTable, 2, 7, str.tostring(volume, '#'), text_color=color.white)

    table.cell(debugTable, 0, 8, 'Volatility', text_color=color.blue)
    table.cell(debugTable, 1, 8, volatilityOk ? 'OK' : 'High', text_color=volatilityOk ? color.green : color.red)
    table.cell(debugTable, 2, 8, str.tostring(volatility * 100, '#.##') + '%', text_color=color.white)

    table.cell(debugTable, 0, 9, 'Signals', text_color=color.blue)
    table.cell(debugTable, 1, 9, longCondition and not shortCondition ? 'LONG' : shortCondition and not longCondition ? 'SHORT' : longCondition and shortCondition ? 'CONFLICT' : 'NONE', text_color=longCondition and not shortCondition ? color.green : shortCondition and not longCondition ? color.red : color.yellow)
    table.cell(debugTable, 2, 9, canEnter ? alertSent ? 'Sent' : 'Ready' : 'Cooldown', text_color=canEnter ? alertSent ? color.yellow : color.green : color.gray)

// === PERFORMANCE DASHBOARD ===
var table dashboard = table.new(position.bottom_left, 3, 3, bgcolor=color.rgb(0, 0, 0, 80), border_color=color.white, border_width=1)
if barstate.islast
    table.cell(dashboard, 0, 0, 'Position', text_color=color.rgb(168, 168, 168), bgcolor=color.rgb(50, 50, 50))
    table.cell(dashboard, 1, 0, 'P/L', text_color=color.rgb(168, 168, 168), bgcolor=color.rgb(50, 50, 50))
    table.cell(dashboard, 2, 0, 'Statistics', text_color=color.rgb(168, 168, 168), bgcolor=color.rgb(50, 50, 50))

    table.cell(dashboard, 0, 1, strategy.position_size > 0 ? 'Long' : strategy.position_size < 0 ? 'Short' : 'Flat', text_color=strategy.position_size > 0 ? color.green : strategy.position_size < 0 ? color.red : color.blue)
    table.cell(dashboard, 1, 1, str.tostring(strategy.netprofit, '#.##'), text_color=strategy.netprofit >= 0 ? color.green : color.red)
    table.cell(dashboard, 2, 1, 'Win Rate', text_color=color.white)

    table.cell(dashboard, 0, 2, strategy.position_size != 0 ? 'Bars: ' + str.tostring(bar_index - entryBarIndex) : '', text_color=color.white)
    table.cell(dashboard, 1, 2, strategy.position_size != 0 ? 'Cooldown: ' + str.tostring(cooldownMinutes) + 'm' : '', text_color=color.white)
    table.cell(dashboard, 2, 2, strategy.closedtrades > 0 ? str.tostring(strategy.wintrades / strategy.closedtrades * 100, '#.##') + '%' : 'N/A', text_color=color.white)

// === CHART TITLE ===
var table titleTable = table.new(position.bottom_right, 1, 1, bgcolor=color.rgb(0, 0, 0, 80), border_color=color.rgb(0, 50, 137), border_width=1)
table.cell(titleTable, 0, 0, "Dskyz - DAFE Trading Systems", text_color=color.rgb(159, 127, 255, 80), text_size=size.large)