Sistema de trading de seguimiento de tendencias con múltiples indicadores de volatilidad adaptativa

ATR SMA RSI DCA 烛台模式 趋势跟踪 波动率适应 多时间周期 止损 止盈
Fecha de creación: 2025-04-11 13:41:56 Última modificación: 2025-04-11 13:41:56
Copiar: 3 Número de Visitas: 378
2
Seguir
319
Seguidores

Sistema de trading de seguimiento de tendencias con múltiples indicadores de volatilidad adaptativa Sistema de trading de seguimiento de tendencias con múltiples indicadores de volatilidad adaptativa

Descripción general

El sistema de comercio de seguimiento de tendencias de múltiples indicadores de volatilidad auto-adaptativo es una estrategia de comercio cuantitativa diseñada para mercados de alta volatilidad, que combina indicadores técnicos de ajuste dinámico con un mecanismo de gestión de riesgos avanzado. El núcleo de la estrategia es ajustar dinámicamente los parámetros de la línea de media móvil a través de ATR (ampliación real promedio) para adaptarse a la volatilidad del mercado, mientras que integra funciones como el RSI para comprar y vender en exceso, filtros de venta y plataformas, identificación de tendencias de múltiples períodos de tiempo y confirmación de posiciones progresivas (DCA), para formar un marco de comercio integral.

Principio de estrategia

El núcleo de la estrategia se basa en los siguientes módulos:

  1. Adaptación de un sistema de movilidad uniformeLa estrategia utiliza una media móvil simple rápida y lenta (SMA), cuya longitud se ajusta dinámicamente a través de ATR. En un entorno de alta volatilidad, la longitud de la media se acorta para reaccionar rápidamente a los cambios en el mercado; en un entorno de baja volatilidad, la longitud de la media se alarga para reducir el ruido. La señal larga se produce cuando la media lenta se cruza en una media rápida y se confirma el precio; la señal corta, por el contrario.

  2. Filtrado de la dinámica RSIVerifica las señales de entrada a través del RSI (indicador de la fuerza y debilidad relativa) para asegurar que la dirección de la operación coincida con la dinámica del mercado. Esta función se puede activar o desactivar de manera opcional y admite parámetros RSI personalizados (como longitud 14, sobrecompra de 60, sobreventa de 40).

  3. Identificación de las formas de la caída: El sistema es capaz de identificar las formas fuertes de absorción de la ganancia o la pérdida, y combinar la intensidad de la transacción y el rango para la verificación. Para evitar falsas señales, el sistema salta la transacción cuando dos formas opuestas aparecen al mismo tiempo.

  4. Confirmación de la tendencia en varios períodos: Selectivamente alinear la señal de negociación con la tendencia SMA en el período de tiempo de 15 minutos, agregar una capa de mecanismo de confirmación y mejorar la calidad de la negociación.

  5. Mecanismo de DCA: Permiten muchas entradas en la dirección de la tendencia, soportan un máximo de entradas predeterminadas (por ejemplo, 4 entradas), el intervalo de entrada se establece en función del múltiplo ATR. Este mecanismo ayuda a optimizar el costo promedio en un mercado en el que la tendencia continúa.

  6. Gestión de riesgos de alto nivel

    • Detención inicial: basado en la configuración ATR (por lo general, 2 a 3,5 veces), se aplica un multiplicador de detención fijo más amplio en los postes de entrada (por ejemplo, 1.3) [2].
    • Seguimiento de la pérdida: el uso de la base ATR de desplazamiento y multiplicación, con un ajuste dinámico a medida que las ganancias aumentan (por ejemplo, cuando las ganancias superan el ATR, la multiplicación disminuye de 0.5 a 0.3);
    • Objetivo de parada: se establece en un determinado múltiplo del precio de entrada ± ATR (como 1.2).
    • Período de enfriamiento: período de suspensión después de la salida (de 0 a 5 minutos) para evitar el exceso de operaciones.
    • Tiempo mínimo de mantenimiento: asegúrese de que el comercio continúe en un cierto número de columnas (como 2-10)
  7. Logía de ejecución de transacciones: El sistema prioriza la señal de movimiento de la línea media o de la forma de la caída ((según la elección del usuario) y aplica filtros de volumen de transacción, volatilidad y tiempo. Para garantizar la calidad de entrada, también se aumentan las condiciones de pico de volumen de transacción ((Transacción> 1.2*No hay más que eso.

Ventajas estratégicas

  1. La adaptabilidad del mercadoA través de ATR, la estrategia puede adaptarse automáticamente a las diferentes condiciones del mercado y mantener su eficacia en entornos de alta y baja volatilidad.

  2. Filtración de la calidad de la señalEl mecanismo de filtración de múltiples capas (RSI, tendencias de varios períodos de tiempo, volumen de transacciones y volatilidad) reduce efectivamente las señales falsas y mejora la calidad de las transacciones.

  3. Mecanismo de admisión flexible: soporte para priorizar el uso de señales móviles de línea media o caída según las preferencias del usuario, y optimizar los puntos de entrada en la dirección de la tendencia a través de la función DCA.

  4. Gestión de riesgos dinámicosLos puntos de parada y los puntos de parada de seguimiento se ajustan a las fluctuaciones del mercado y a la dinámica de las ganancias de las operaciones, dando suficiente espacio para que la tendencia se desarrolle al mismo tiempo que se protege el capital.

  5. Herramientas de visualización y debujoLa estrategia ofrece una amplia cobertura de gráficos, paneles de instrumentos en tiempo real y tablas de despliegue para ayudar a los usuarios a optimizar los parámetros y comprender la lógica de las operaciones.

  6. Diseño modular: El usuario puede activar o desactivar varias funciones según sus preferencias (como el filtro RSI, la identificación de la forma de la caída, la tendencia de múltiples períodos de tiempo, etc.), altamente personalizable.

  7. Control de entrada muy precisoLos filtros de pico de transacción aseguran la entrada en el mercado solo durante actividades significativas, mientras que el mecanismo de período de enfriamiento evita el exceso de transacciones.

Riesgo estratégico

  1. Sensibilidad de los parámetrosLa estrategia utiliza varios parámetros (como la longitud de la línea media, el ciclo ATR, el umbral RSI, etc.) cuya configuración tiene un impacto significativo en el rendimiento, y una combinación inadecuada de parámetros puede causar una adaptación excesiva de los datos históricos.

*Cómo solucionarlo*Realizar pruebas de optimización de parámetros extensas, pero evitando la optimización excesiva; usar pruebas de caminata (walk-forward testing) y pruebas fuera de la muestra para verificar la solidez de la estrategia.

  1. Riesgo de cambio de mercadoCuando el patrón de mercado cambia rápidamente (por ejemplo, de tendencia a oscilación), la estrategia puede generar pérdidas continuas antes de adaptarse al nuevo entorno.

*Cómo solucionarlo*Considere la posibilidad de agregar mecanismos de identificación de estados de mercado, utilizando diferentes conjuntos de parámetros en diferentes entornos de mercado; Implemente restricciones generales de riesgo, como la suspensión de operaciones después de pérdidas máximas diarias o pérdidas continuas.

  1. Punto de deslizamiento y problemas de liquidezLos mercados con alta frecuencia de transacciones y gran volatilidad pueden enfrentar riesgos de aumento de puntos de deslizamiento y disminución de la liquidez.

*Cómo solucionarlo*Incluir en la retrospectiva los puntos de deslizamiento reales y las estimaciones de comisiones; evitar el comercio en momentos de baja liquidez; considerar el uso de una lista de precios límite en lugar de una lista de precios de mercado.

  1. Complejidad del sistemaLa combinación de múltiples capas de lógica y condiciones aumenta la complejidad de las estrategias, que pueden ser difíciles de entender y mantener.

*Cómo solucionarlo*Utilice las herramientas de desbloqueo que ofrece la estrategia para monitorear de cerca el rendimiento de los componentes; mantenga una buena anotación de código; considere la eficacia de las pruebas modulares independientes de los componentes.

  1. El riesgo de sobrecomercializaciónLos mecanismos de DCA y la frecuente generación de señales pueden conducir a una sobrecambio y aumentar los costos de las transacciones.

*Cómo solucionarlo*El objetivo de la estrategia es: establecer un período de enfriamiento adecuado y un tiempo de retención mínimo; considerar estrictamente los costos de las transacciones en la evaluación posterior; revisar y optimizar periódicamente los criterios de admisión.

Dirección de optimización

  1. Aprendizaje automáticoIntroducción de algoritmos de optimización de parámetros adaptativos, como optimización de Bayes o algoritmos genéticos, para encontrar automáticamente la combinación de parámetros óptima para diferentes entornos de mercado. Esto reducirá la necesidad de optimización manual y mejorará la adaptabilidad de las estrategias a los cambios en el mercado.

  2. Clasificación del entorno del mercadoDesarrollar un sistema de clasificación de estados de mercado (trend, oscilación, alta volatilidad, baja volatilidad, etc.) y configurar los parámetros óptimos para cada estado. Este método permite ajustar el comportamiento de la estrategia más rápidamente cuando el mercado cambia y reduce el retraso de adaptación.

  3. Mejora en la gestión de posicionesIntroducción de algoritmos de gestión de posiciones más complejos, como el ajuste de posiciones dinámicas basadas en los principios de Kelly o la intensidad del impulso. Esto puede optimizar el uso de los fondos, aumentar la exposición en señales fuertes y reducir el riesgo en señales débiles.

  4. Integración de los indicadores alternativos: probar la eficacia de otros indicadores técnicos, como las bandas de Bollinger, MACD o el gráfico de la nube de Ichimoku, como complemento o sustitución de los sistemas existentes. Diferentes indicadores pueden proporcionar señales más precisas en determinadas condiciones de mercado.

  5. Integración de datos de emocionesConsidere la inclusión de indicadores de sentimiento de mercado, como el índice de volatilidad VIX o los datos del mercado de opciones, para identificar con anticipación las posibles transformaciones del mercado. Estas fuentes de datos externas pueden proporcionar información que los indicadores técnicos tradicionales no pueden capturar.

  6. Análisis de la correlación entre varios activos: Desarrollar análisis de correlación entre las clases de activos, utilizando las señales de un mercado para validar o reforzar las decisiones comerciales de otro mercado relevante. Por ejemplo, el uso de los cambios en los precios de los productos para confirmar las tendencias de los sectores de acciones relevantes.

  7. Optimización de la eficiencia de la computaciónReestructurar el código para mejorar la eficiencia de los cálculos, especialmente para las estrategias de alta frecuencia. Esto incluye optimizar el cálculo de ATR, la secuencia de evaluación de condiciones y reducir la redundancia innecesaria.

Resumir

El sistema de comercio de seguimiento de tendencias de múltiples indicadores de volatilidad auto-adaptativa representa un método de comercio cuantitativo completo y flexible que responde de manera efectiva a diferentes entornos de mercado a través de ajustes de parámetros dinámicos y un mecanismo de filtración de múltiples capas. La ventaja central de la estrategia radica en su adaptabilidad y el marco de gestión de riesgos integral, que la hace especialmente adecuada para los mercados de futuros con alta volatilidad.

La estrategia integra varias herramientas clásicas de análisis técnico (moving averages, RSI, and bullish patterns) con elementos modernos de comercio cuantitativo (parámetros adaptables, análisis de múltiples períodos de tiempo, DCA), formando un sistema equilibrado. Mediante el control preciso del tiempo de entrada, la optimización de la estrategia de entrada múltiple y el ajuste dinámico del nivel de pérdida, la estrategia puede aprovechar al máximo las oportunidades de tendencias del mercado, al tiempo que protege el capital.

Sin embargo, la complejidad de las estrategias también conlleva desafíos de sensibilidad a los parámetros y mantenimiento del sistema. Antes de implementar la estrategia, los inversores deben realizar una adecuada retroalimentación y prueba de avance y estar preparados para ajustar los parámetros según los cambios en el mercado.

En general, la estrategia ofrece un sólido marco de trading cuantitativo, adecuado para que los operadores experimentados lo puedan personalizar según sus necesidades y preferencias de riesgo específicas, buscando una ventaja de trading consistente en los mercados financieros cambiantes de hoy en día.

Código Fuente de la Estrategia
/*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)