Stratégie de trading quantitatif adaptative de suivi de la volatilité croisée des moyennes mobiles

MA交叉 ATR EMA SMA WMA HMA VWMA 趋势过滤 波动率过滤 跟踪止损 双重止盈
Date de création: 2025-05-14 10:49:04 Dernière modification: 2025-05-14 10:49:04
Copier: 0 Nombre de clics: 317
2
Suivre
319
Abonnés

Stratégie de trading quantitatif adaptative de suivi de la volatilité croisée des moyennes mobiles Stratégie de trading quantitatif adaptative de suivi de la volatilité croisée des moyennes mobiles

Aperçu de la stratégie

La stratégie de trading quantifiée de suivi de la volatilité croisée de la moyenne est une stratégie systématisée spécialement conçue pour le trading à haute fréquence et les opérations à courte fréquence. Le cœur de la stratégie utilise l’intersection de la moyenne mobile rapide (MA) avec la moyenne mobile lente comme point de déclenchement principal du signal, tout en combinant une variété de filtres clés et d’outils de gestion du risque précis pour capturer les fluctuations de prix faibles mais rapides.

Principe de stratégie

La logique de base de cette stratégie est divisée en plusieurs éléments clés:

  1. Signaux d’entrée: principalement via la croisée/traversée de la moyenne rapide avec la moyenne lente comme condition d’entrée. L’utilisateur peut configurer de manière flexible le type de moyenne (EMA, SMA, WMA, HMA, VWMA) et la longueur de la période pour ajuster la sensibilité du signal en fonction des différentes conditions du marché.

  2. Filtrage des tendancesStratégie: Utilisez sélectivement les longues moyennes mobiles comme filtre de tendance majeure, en veillant à ce que les transactions se déroulent uniquement dans la direction de la tendance majeure et en évitant de négocier des courts courts dans un marché fortement directionnel.

  3. Vérifiez le filtre

    • Filtre de fréquence ATR: Conçu pour la suspension de l’entrée sur des marchés extrêmement plats ou “silencieux”, où la volatilité est inférieure à la marge dynamique (basée sur l’ATR moyen), ce qui aide à prévenir les tremblements dans des conditions sans tendance et à faible énergie.
    • Filtre à débit: vérifier les signaux d’entrée en exigeant une participation minimale au marché (par rapport au volume de transactions et à sa moyenne mobile) et éviter l’entrée basée sur des pics de faible liquidité ou des prix insignifiants.
  4. La suite de gestion des risques

    • Stop à la volatilité initialeLe stop initial basé sur l’ATR fournit un point de départ objectif pour la définition du risque de chaque transaction, adapté à la volatilité récente.
    • Arrêt de la traque ATRIl est essentiel pour les marchés dynamiques de suivre les lignes de stop-loss qui s’ajustent en fonction des mouvements de prix favorables, afin de protéger les bénéfices des transactions courtoises réussies, tout en réduisant les pertes relativement rapidement en cas de reprise.
    • Stop-loss sur les pertes et les pertes (option): une fois que le TP1 est atteint ou que le prix a bougé d’une certaine distance ATR, le stop loss peut être automatiquement déplacé vers le prix d’entrée (avec une réserve) pour le risque de transaction rapide, neutre et qui a montré un succès initial.
    • Niveau de double bénéficeLe TP1 est conçu pour une partie rapide du profit (par exemple 50%), tandis que le TP2 est conçu pour une partie plus lucrative de la position restante.
  5. Gestion des positions: L’adoption d’un nombre fixe de tailles de position, permettant un contrôle précis de la taille des positions pour chaque transaction, est essentielle pour la génération de commandes API et d’applications de risque cohérentes dans un environnement à haute fréquence.

Avantages stratégiques

En analysant le code en profondeur, la stratégie présente les avantages suivants:

  1. Haute capacité de configuration: L’utilisateur peut ajuster de manière flexible divers paramètres, y compris le type et la période de la ligne moyenne, les paramètres de filtrage et de gestion du risque, afin que la stratégie s’adapte à divers environnements de marché et styles de négociation.

  2. Mécanisme de filtrage à plusieurs niveauxLe filtrage des tendances, des fluctuations et des volumes de transaction réduit les faux signaux et le bruit du marché et améliore la qualité des transactions.

  3. Une bonne gestion des risquesLa stratégie intègre plusieurs mécanismes de stop-loss (initial, suivi, compensation des pertes) et des objectifs de double profit, permettant un contrôle minutieux des risques et une protection des bénéfices.

  4. Conception adaptée aux API: Une logique d’entrée et de sortie claire et précise génère des signaux sans ambiguïté, facilitant l’intégration avec des systèmes de négociation externes et permettant une exécution des ordres presque instantanée.

  5. Contrôle de position précis: La taille des positions de nombre fixe simplifie la charge utile des points d’extrémité de l’API et rend l’exécution automatisée plus fiable.

  6. Très adaptableLa stratégie peut passer d’un mode de négociation à haute fréquence à un mode de suivi de tendance à plus long terme, en s’adaptant aux différentes conditions du marché et aux préférences de négociation individuelles, en ajustant les paramètres.

Risque stratégique

Bien que cette stratégie soit bien conçue, elle comporte des risques et des défis potentiels:

  1. Risques liés à l’optimisation des paramètres: Comme la stratégie contient de nombreux paramètres configurables, une optimisation excessive peut entraîner un bon résultat de rétroaction mais une mauvaise performance réelle (hyperadaptation), les investisseurs doivent vérifier sur des données hors échantillon ou éviter ce risque en effectuant des tests avant.

  2. Effets sur le coût des transactions: Le trading à haute fréquence implique un grand nombre de transactions, des commissions accumulées et des points de glissement qui peuvent avoir un impact significatif sur la rentabilité nette, ces coûts doivent être calculés avec précision lors de la configuration et de la retracement avant d’être utilisés.

  3. Variation de la qualité du signal: La fiabilité des signaux de croisement homogène peut varier selon les conditions du marché, en particulier dans les marchés où la volatilité est faible ou très élevée.

  4. La dépendance à la technologieEn tant que stratégie API-ready, son efficacité dépend en partie de la vitesse d’exécution et de la stabilité technologique. Les retards ou les pannes du système peuvent entraîner des opportunités perdues ou des écarts d’exécution.

  5. Limite de taille: le nombre de positions fixes peut ne pas correspondre à la taille de tous les comptes, les petits comptes peuvent être exposés à des risques excessifs et les grands comptes peuvent ne pas être en mesure de tirer pleinement parti des fonds.

Orientation de l’optimisation de la stratégie

Voici quelques pistes d’optimisation possibles, basées sur la conception de la stratégie et les risques potentiels:

  1. Paramètres d’adaptation: la conception de paramètres clés (comme la multiplication des ATR et la périodicité de la moyenne) pour s’adapter automatiquement en fonction des conditions du marché, améliorant ainsi l’adaptabilité de la stratégie aux différentes phases du marché.

  2. Filtrage intelligent amélioréL’intégration d’indicateurs supplémentaires de l’état du marché, tels que la structure du marché, l’identification des modèles de fluctuation ou la pertinence des actifs concernés, améliore encore la précision du filtre.

  3. Gestion dynamique des positionsLe calcul des positions dynamiques basé sur la taille des comptes, la volatilité actuelle et les performances stratégiques récentes, au lieu d’un nombre fixe de positions, permet une gestion plus intelligente des fonds.

  4. Confirmation de plusieurs périodesLes signaux sont vérifiés sur différentes périodes de temps pour s’assurer que la direction des transactions est cohérente avec la structure du marché plus large et pour réduire les transactions inutiles.

  5. Intégration du machine learning: analyse des performances des signaux historiques à l’aide d’algorithmes d’apprentissage automatique, prédit la probabilité de succès des signaux futurs et donne la priorité aux transactions à haut rendement.

  6. Gestion des sessions de négociation: Ajout d’un filtre de temps de négociation pour éviter les périodes de faible liquidité ou de forte volatilité et se concentrer sur les fenêtres de négociation les plus efficaces pour le marché.

  7. Filtrage par pertinence: pour les transactions multi-actifs, ajouter une analyse de la corrélation avec les marchés concernés, éviter l’exposition excessive à des facteurs de risque spécifiques.

Résumer

La Stratégie de trading quantifiée de suivi des fluctuations de la courbe de la courbe de la courbe de la courbe est un système de trading à haute fréquence complet, qui déclenche des signaux par courbe de la courbe de la courbe de la courbe, combiné à une variété de filtres clés et à des outils de gestion du risque précis, spécialement conçu pour capturer les fluctuations de prix faibles mais rapides. La force de la stratégie réside dans son cadre de gestion du risque hautement configurable et bien élaboré, permettant aux traders d’ajuster minutieusement les paramètres de trading en fonction de leur tolérance au risque et des conditions du marché.

Pour les traders à haute fréquence, la stratégie offre une logique d’entrée et de sortie claire et une capacité d’intégration transparente avec les plateformes d’exécution externes, ce qui est essentiel pour la prise de décision rapide dans un marché en évolution rapide. Cependant, lors de l’utilisation de cette stratégie, il convient de prêter une attention particulière au risque de cumulation des coûts de transaction et d’optimisation excessive, afin de garantir la robustesse et la rentabilité de la stratégie dans les transactions réelles.

En fin de compte, cette stratégie représente une approche équilibrée qui exploite la force des indicateurs techniques et des outils de gestion des risques, tout en conservant suffisamment de flexibilité pour s’adapter aux conditions changeantes du marché. Grâce à un ajustement prudent des paramètres et à une amélioration continue de la surveillance, cette stratégie peut devenir une composante précieuse d’un portefeuille de transactions quantifiées.

Code source de la stratégie
/*backtest
start: 2024-05-14 00:00:00
end: 2025-05-12 08:00:00
period: 2d
basePeriod: 2d
exchanges: [{"eid":"Futures_Binance","currency":"DOGE_USDT"}]
*/

//@version=5
// © ArrowTrade x:ArrowTrade

// --- STRATEGY DEFINITION ---
strategy(
     title="Arrow's Flexible MA Cross Strategy [API Ready]", // Added branding
     shorttitle="ArrowFlex",                  // Added branding
     overlay=true,
     initial_capital=1000, // Example capital, user should adjust
     commission_type=strategy.commission.percent,
     commission_value=0.036, // Example commission, user MUST adjust to their broker/exchange
     slippage=2,             // Example slippage (in ticks), user should adjust based on asset/broker
     process_orders_on_close=true, // Calculates/executes on bar close. Set to false for intrabar (use with caution & specific logic)
     pyramiding=0,           // No pyramiding allowed (one entry per direction)
     default_qty_type=strategy.fixed // Defaulting to fixed quantity
     // Removed default_qty_value from here
     )

// ================================================================================
//  Strategy Description (for TradingView Public Library & Users)
// ================================================================================
// © ArrowTrade
//
// A configurable Moving Average Crossover strategy designed for flexibility and
// API integration.
//
// Features:
// - MA Crossover Entries: Uses configurable Fast/Slow MA crossovers for signals.
// - Trend Filter: Optional longer-term MA filter to trade only with the trend.
// - Volatility Filter: Optional ATR filter to avoid low-volatility periods.
// - Volume Filter: Optional Volume filter to confirm entries with sufficient volume.
// - Stop Loss Options:
//     - Initial Volatility Stop (ATR-based)
//     - ATR Trailing Stop
//     - Break-Even Stop (activated by TP1 hit or ATR distance)
// - Take Profit Options:
//     - Two independent TP levels (percentage-based).
//     - Configurable partial close percentage at TP1.
// - Position Sizing: Fixed quantity per trade (adjustable).
//
// Intended Use:
// While configurable for various styles (scalping to trend-following by adjusting
// parameters), this strategy is built with API automation in mind. The clear
// entry and exit logic facilitates integration with external execution platforms
// via webhooks or other methods. Parameters can be tightened (shorter MAs,
// tighter stops/TPs, specific filters) for higher-frequency signals suitable
// for scalping.
//
// Disclaimer:
// Backtesting results are hypothetical and do not guarantee future performance.
// Market conditions change constantly. Always perform your own due diligence,
// forward testing, and rigorous risk management before trading live with any
// strategy. Ensure you adjust inputs like commission, slippage, and position
// size to accurately reflect your specific broker/exchange and risk profile.
// ================================================================================


// === INPUTS (Grouped and Ordered by Importance/Function) ===

// --- 1. Core Signal & Trend Filter ---
grp_signal = "1. Core Signal & Trend Filter"
signalSource   = input.source(high, title="Signal Source", group=grp_signal, tooltip="Price source for calculating the signal MAs (e.g., close, hl2, ohlc4). 'hlc3' or 'ohlc4' can provide smoother signals.")
signalMaType   = input.string("EMA", title="Signal MA Type", options=["EMA", "SMA", "WMA", "HMA", "VWMA"], group=grp_signal, tooltip="Type of Moving Average used for the fast/slow signal lines (EMA reacts faster, SMA smoother, HMA reduces lag).")
signalFastLen  = input.int(12, title="Fast MA Period", minval=2, maxval=100, step=1, group=grp_signal, tooltip="Period for the shorter-term signal MA. Shorter periods lead to more frequent signals (potentially more noise/scalping).")
signalSlowLen  = input.int(25, title="Slow MA Period", minval=3, maxval=200, step=1, group=grp_signal, tooltip="Period for the longer-term signal MA. Must be greater than Fast MA Period. Defines the crossover signal.")
useTrendFilter = input.bool(true, title="Enable Trend Filter", group=grp_signal, tooltip="If enabled, entry signals are only taken in the direction of the longer-term trend defined by the Trend MA.")
trendMaType    = input.string("EMA", title="Trend MA Type", options=["EMA", "SMA", "WMA", "HMA", "VWMA"], group=grp_signal, tooltip="Type of Moving Average used for the trend filter.")
trendMaLen     = input.int(100, title="Trend MA Period", minval=50, maxval=500, step=10, group=grp_signal, tooltip="Period for the Trend MA. Significantly longer than signal MAs typically. Higher values filter more aggressively.")
trendMaSource  = input.source(hl2, title="Trend MA Source", group=grp_signal, tooltip="Price source for the Trend MA calculation.")

// --- 2. Risk Management: Stop Loss ---
grp_stop = "2. Risk Management: Stop Loss"
useVolatilityStop    = input.bool(true, title="Enable Initial Volatility Stop", group=grp_stop, tooltip="Sets the initial stop loss based on Average True Range (ATR) at the time of entry.")
volStopAtrPeriod     = input.int(7, title="   Initial Stop ATR Period", minval=1, maxval=50, step=1, group=grp_stop, tooltip="ATR lookback period for calculating the initial stop distance.")
volStopAtrMultiplier = input.float(5, title="   Initial Stop ATR Multiplier", minval=0.5, maxval=10, step=0.1, group=grp_stop, tooltip="Multiplier for the ATR value to determine stop distance (Stop = Entry +/- ATR * Multiplier). Lower values = tighter initial stop.")
useTrailingStop      = input.bool(true, title="Enable ATR Trailing Stop", group=grp_stop, tooltip="If enabled, the stop loss will trail behind price based on current ATR, potentially locking in profits. Can override the initial/BE stop if it moves favorably.")
trailAtrPeriod       = input.int(15, title="   Trailing ATR Period", minval=1, maxval=50, step=1, group=grp_stop, tooltip="ATR lookback period for calculating the trailing distance.")
trailAtrMultiplier   = input.float(4.0, title="   Trailing ATR Multiplier", minval=0.5, maxval=10, step=0.1, group=grp_stop, tooltip="Multiplier for the current ATR to determine trailing distance. Lower values trail tighter.")
useBreakEvenStop     = input.bool(false, title="Enable Break-Even Stop", group=grp_stop, tooltip="If enabled, moves the stop loss to entry price (plus a small profit buffer) once a certain condition is met.")
beActivationChoice   = input.string("TP1 Reached", title="   BE Activation Condition", options=["TP1 Reached", "ATR Distance Moved"], group=grp_stop, tooltip="When should the Break-Even Stop activate? When TP1 is hit, or when price moves a certain ATR distance from entry?")
beActivationAtrMult  = input.float(1.5, title="   BE Activation ATR Multiplier", minval=0.1, maxval=5, step=0.1, group=grp_stop, tooltip="Used only if 'ATR Distance Moved' is selected. BE activates if price moves (Entry +/- ATR * Multiplier). Uses 'Initial Stop ATR Period'.")
beProfitTicks        = input.int(2, title="   BE Profit Buffer (Ticks)", minval=0, maxval=50, step=1, group=grp_stop, tooltip="Moves the stop to Entry Price +/- this many ticks (e.g., to cover commissions). Set to 0 for exact entry price.")

// --- 3. Risk Management: Take Profit ---
grp_tp = "3. Risk Management: Take Profit (TP)"
useTp1        = input.bool(true, title="Enable TP1", group=grp_tp, tooltip="Enable the first Take Profit level.")
tp1Pct        = input.float(1.5, title="   TP1 Target (%)", minval=0.1, maxval=20, step=0.1, group=grp_tp, tooltip="First TP target as a percentage distance from the entry price. Should be less than TP2 %.")
tp1QtyPercent = input.int(50, title="   TP1 Close Quantity (%)", minval=1, maxval=100, step=5, group=grp_tp, tooltip="Percentage of the original position size to close when TP1 is hit.")
useTp2        = input.bool(true, title="Enable TP2", group=grp_tp, tooltip="Enable the second (final) Take Profit level.")
tp2Pct        = input.float(3.0, title="   TP2 Target (%)", minval=0.2, maxval=30, step=0.1, group=grp_tp, tooltip="Second TP target as a percentage distance from the entry price. Closes the remaining position.")

// --- 4. Additional Filters ---
grp_filters = "4. Additional Filters"
useAtrFilter        = input.bool(true, title="Enable ATR Volatility Filter", group=grp_filters, tooltip="If enabled, avoids entries during periods of very low volatility (ATR below a moving average of ATR). Helps filter choppy/sideways markets.")
atrFilterPeriod     = input.int(14, title="   ATR Filter Period", minval=1, maxval=50, step=1, group=grp_filters, tooltip="Lookback period for calculating the current ATR and its average for the filter.")
atrFilterMultiplier = input.float(0.5, title="   ATR Filter Threshold Multiplier", minval=0.1, maxval=5, step=0.1, group=grp_filters, tooltip="Entry requires current ATR to be >= (Average ATR * Multiplier). Lower values filter more aggressively.")
useVolumeFilter     = input.bool(true, title="Enable Volume Filter", group=grp_filters, tooltip="If enabled, requires the volume of the entry bar to be above a moving average of volume. Acts as confirmation.")
volumeLookback      = input.int(30, title="   Volume MA Period", minval=2, maxval=100, step=1, group=grp_filters, tooltip="Lookback period for calculating the average volume.")
volumeMultiplier    = input.float(1.0, title="   Min Volume Ratio (vs Avg)", minval=0.1, maxval=5, step=0.1, group=grp_filters, tooltip="Entry requires current volume to be >= (Average Volume * Multiplier). Values >= 1 require above-average volume.")

// --- 5. Position Sizing ---
grp_size = "5. Position Sizing"
// Define the quantity input with its own default value
qtyValue = input.float(0.01, title="Position Size (Fixed Qty)", minval=0.0001, step=0.0001, group=grp_size, tooltip="Fixed quantity (contracts/shares/lots) per trade. Adjust based on your account size, risk tolerance, and the asset being traded. Can be overridden by API.")


// === FUNCTIONS ===
f_ma(maType, src, len) =>
    float result = na
    if maType == "SMA"
        result := ta.sma(src, len)
    else if maType == "EMA"
        result := ta.ema(src, len)
    else if maType == "WMA"
        result := ta.wma(src, len)
    else if maType == "HMA"
        result := ta.hma(src, len)
    else if maType == "VWMA"
        result := ta.vwma(src, len)
    result

// === CORE CALCULATIONS ===

// Parameter Sanity Check
if signalSlowLen <= signalFastLen and barstate.islast
    runtime.error("Signal Slow MA Period must be greater than Fast MA Period!")

// 1. Moving Averages
float fastMA = f_ma(signalMaType, signalSource, signalFastLen)
float slowMA = f_ma(signalMaType, signalSource, signalSlowLen)
float trendMA = useTrendFilter ? f_ma(trendMaType, trendMaSource, trendMaLen) : na

// 2. ATR Values
float atrValueStop = ta.atr(volStopAtrPeriod)
float atrValueTrail = ta.atr(trailAtrPeriod)
float atrValueFilter = ta.atr(atrFilterPeriod)
float atrValueBE = ta.atr(volStopAtrPeriod)

// 3. Filter Conditions
bool trendFilterOK_L = not useTrendFilter or (not na(trendMA) and signalSource > trendMA)
bool trendFilterOK_S = not useTrendFilter or (not na(trendMA) and signalSource < trendMA)
float avgAtrFilter = ta.sma(atrValueFilter, atrFilterPeriod)
bool volatilityFilterOK = not useAtrFilter or (not na(atrValueFilter) and not na(avgAtrFilter) and atrValueFilter >= avgAtrFilter * atrFilterMultiplier)
float avgVolume = ta.sma(volume, volumeLookback)
bool volumeFilterOK = not useVolumeFilter or (not na(volume) and not na(avgVolume) and volume >= avgVolume * volumeMultiplier)
bool finalFilterOK_L = trendFilterOK_L and volatilityFilterOK and volumeFilterOK
bool finalFilterOK_S = trendFilterOK_S and volatilityFilterOK and volumeFilterOK

// 4. Entry Signals
bool longCross = not na(fastMA) and not na(slowMA) and ta.crossover(fastMA, slowMA)
bool shortCross = not na(fastMA) and not na(slowMA) and ta.crossunder(fastMA, slowMA)
bool longEntrySignal = longCross and finalFilterOK_L
bool shortEntrySignal = shortCross and finalFilterOK_S

// === STRATEGY EXECUTION LOGIC ===

// --- State Variables (persisted between bars) ---
var float entryPriceVar = na
var float initialStopPrice = na
var float currentStopPrice = na
var float trailStopLevel = na
var bool isBEActive = false
var bool tp1Reached = false
var float qtyToCloseTp1_Var = na

// --- Position Status ---
bool inLong = strategy.position_size > 0
bool inShort = strategy.position_size < 0
bool inTrade = strategy.position_size != 0

// --- Reset State Variables on Trade Exit ---
if not inTrade and inTrade[1]
    entryPriceVar := na
    initialStopPrice := na
    currentStopPrice := na
    trailStopLevel := na
    isBEActive := false
    tp1Reached := false
    qtyToCloseTp1_Var := na

// --- Handle New Entries ---
if longEntrySignal and not inTrade
    strategy.entry("Long Entry", strategy.long, qty=qtyValue) // Use qtyValue from input

if shortEntrySignal and not inTrade
    strategy.entry("Short Entry", strategy.short, qty=qtyValue) // Use qtyValue from input


// --- Manage Stops and Take Profits for Open Positions ---
if inTrade
    // Initialize state on the bar immediately AFTER entry
    if na(entryPriceVar)
        entryPriceVar := strategy.position_avg_price
        float positionQty = strategy.position_size

        if not na(positionQty) and tp1QtyPercent > 0 and useTp1
            qtyToCloseTp1_Var := math.abs(positionQty * tp1QtyPercent / 100)
        else
            qtyToCloseTp1_Var := 0.0

        if useVolatilityStop and not na(atrValueStop)
            initialStopPrice := entryPriceVar + (inLong ? -1 : 1) * atrValueStop * volStopAtrMultiplier
            currentStopPrice := initialStopPrice
        else
            initialStopPrice := na
            currentStopPrice := na

        if useTrailingStop and not na(atrValueTrail)
            trailStopLevel := entryPriceVar + (inLong ? -1 : 1) * atrValueTrail * trailAtrMultiplier
        else
            trailStopLevel := na

        isBEActive := false
        tp1Reached := false

    // --- Calculations within the trade (if entry price is set) ---
    if not na(entryPriceVar)

        // 1. Calculate TP Levels for the current bar
        float tp1LevelL = na, float tp2LevelL = na, float tp1LevelS = na, float tp2LevelS = na
        if useTp1
            tp1LevelL := entryPriceVar * (1 + tp1Pct / 100)
            tp1LevelS := entryPriceVar * (1 - tp1Pct / 100)
        if useTp2
            tp2LevelL := entryPriceVar * (1 + tp2Pct / 100)
            tp2LevelS := entryPriceVar * (1 - tp2Pct / 100)

        // 2. Check and Activate Break-Even Stop
        if useBreakEvenStop and not isBEActive and not na(currentStopPrice)
            float beTriggerL = na, float beTriggerS = na
            if beActivationChoice == "TP1 Reached" and useTp1
                if not na(tp1LevelL)
                    beTriggerL := tp1LevelL
                if not na(tp1LevelS)
                    beTriggerS := tp1LevelS
            else if beActivationChoice == "ATR Distance Moved" and not na(atrValueBE)
                beTriggerL := entryPriceVar + atrValueBE * beActivationAtrMult
                beTriggerS := entryPriceVar - atrValueBE * beActivationAtrMult

            float beTargetLevel = entryPriceVar + (inLong ? 1 : -1) * beProfitTicks * syminfo.mintick

            if not na(beTriggerL) and not na(beTargetLevel) and inLong and high >= beTriggerL and beTargetLevel > currentStopPrice
                currentStopPrice := beTargetLevel
                isBEActive := true
            if not na(beTriggerS) and not na(beTargetLevel) and inShort and low <= beTriggerS and beTargetLevel < currentStopPrice
                currentStopPrice := beTargetLevel
                isBEActive := true

        // 3. Update Trailing Stop
        if useTrailingStop and not na(currentStopPrice) and not na(atrValueTrail)
            float newTrailStopL = low - atrValueTrail * trailAtrMultiplier
            float newTrailStopS = high + atrValueTrail * trailAtrMultiplier
            float prevTrail = trailStopLevel[1]
            float calculatedNewTrail = na

            if inLong
                calculatedNewTrail := na(prevTrail) ? newTrailStopL : math.max(prevTrail, newTrailStopL)
                if not na(calculatedNewTrail)
                    trailStopLevel := calculatedNewTrail
                if not na(trailStopLevel) and trailStopLevel > currentStopPrice
                    currentStopPrice := trailStopLevel
            if inShort
                calculatedNewTrail := na(prevTrail) ? newTrailStopS : math.min(prevTrail, newTrailStopS)
                if not na(calculatedNewTrail)
                    trailStopLevel := calculatedNewTrail
                if not na(trailStopLevel) and trailStopLevel < currentStopPrice
                    currentStopPrice := trailStopLevel

        // --- Execute Exits ---

        // 4. Apply Stop Loss Exit
        if not na(currentStopPrice)
            bool isTrailingActiveNow = useTrailingStop and not na(trailStopLevel) and currentStopPrice == trailStopLevel
            string stop_comment = isBEActive ? "BE Stop" : (isTrailingActiveNow ? "Trail Stop" : "Vol Stop")
            if inLong
                strategy.exit("SL Exit L", from_entry="Long Entry", stop=currentStopPrice, comment=stop_comment + " L")
            if inShort
                strategy.exit("SL Exit S", from_entry="Short Entry", stop=currentStopPrice, comment=stop_comment + " S")

        // 5. Apply Take Profit Exits
        // TP1 Exit (Partial Quantity)
        if useTp1 and not tp1Reached and not na(qtyToCloseTp1_Var) and qtyToCloseTp1_Var > 0
            if inLong and not na(tp1LevelL)
                strategy.exit("TP1 Exit L", from_entry="Long Entry", qty=qtyToCloseTp1_Var, limit=tp1LevelL, comment="TP1 Hit L")
                if high >= tp1LevelL
                    tp1Reached := true
            if inShort and not na(tp1LevelS)
                strategy.exit("TP1 Exit S", from_entry="Short Entry", qty=qtyToCloseTp1_Var, limit=tp1LevelS, comment="TP1 Hit S")
                if low <= tp1LevelS
                    tp1Reached := true

        // TP2 Exit (Remaining Quantity)
        if useTp2
            if inLong and not na(tp2LevelL)
                strategy.exit("TP2 Exit L", from_entry="Long Entry", limit=tp2LevelL, comment="TP2 Hit L")
            if inShort and not na(tp2LevelS)
                strategy.exit("TP2 Exit S", from_entry="Short Entry", limit=tp2LevelS, comment="TP2 Hit S")


// === PLOTTING ===

// 1. Moving Averages
plot(fastMA, "Fast MA", color=color.new(color.aqua, 0), linewidth=1)
plot(slowMA, "Slow MA", color=color.new(color.fuchsia, 0), linewidth=1)
plot(useTrendFilter and not na(trendMA) ? trendMA : na, "Trend MA", color=color.new(color.gray, 0), linewidth=2, style=plot.style_cross)

// 2. Active Stop Loss Level
color stopColor = color.new(color.red, 0)
bool isTrailingActivePlot = useTrailingStop and not na(trailStopLevel) and not na(currentStopPrice) and currentStopPrice == trailStopLevel
if isBEActive
    stopColor := color.new(color.orange, 0)
else if isTrailingActivePlot
    stopColor := color.new(color.blue, 0)
plot(inTrade and not na(currentStopPrice) ? currentStopPrice : na, "Active Stop Loss", stopColor, style=plot.style_linebr, linewidth=2)

// 3. Take Profit Levels
float plot_tp1LevelL = na, float plot_tp1LevelS = na, float plot_tp2LevelL = na, float plot_tp2LevelS = na
if not na(entryPriceVar)
    if useTp1
        plot_tp1LevelL := entryPriceVar * (1 + tp1Pct / 100)
        plot_tp1LevelS := entryPriceVar * (1 - tp1Pct / 100)
    if useTp2
        plot_tp2LevelL := entryPriceVar * (1 + tp2Pct / 100)
        plot_tp2LevelS := entryPriceVar * (1 - tp2Pct / 100)
plot(inTrade and useTp1 and not na(inLong ? plot_tp1LevelL : plot_tp1LevelS) ? (inLong ? plot_tp1LevelL : plot_tp1LevelS) : na, "TP1 Level", color=color.new(color.green, 30), style=plot.style_linebr, linewidth=1)
plot(inTrade and useTp2 and not na(inLong ? plot_tp2LevelL : plot_tp2LevelS) ? (inLong ? plot_tp2LevelL : plot_tp2LevelS) : na, "TP2 Level", color=color.new(color.green, 0), style=plot.style_linebr, linewidth=1)

// 4. Entry Signal Markers
plotshape(longEntrySignal, title="Long Entry Signal", location=location.belowbar, color=color.new(color.green, 0), style=shape.triangleup, size=size.small)
plotshape(shortEntrySignal, title="Short Entry Signal", location=location.abovebar, color=color.new(color.red, 0), style=shape.triangledown, size=size.small)

// 5. Background Color Filters
bgcolor(useTrendFilter and not na(trendMA) and inTrade ? (inLong ? color.new(color.blue, 90) : color.new(color.red, 90)) : na, title="Trend Filter Active")
bgcolor(useAtrFilter and not volatilityFilterOK ? color.new(color.gray, 85) : na, title="Low Volatility Filter Active")
bgcolor(useVolumeFilter and not volumeFilterOK ? color.new(color.yellow, 90) : na, title="Low Volume Filter Active")