Delayed Exit Strategy: The Art of Patience

RSI ATR VOLUME PATTERN
Created on: 2025-09-08 13:38:17 Modified on: 2025-09-08 13:38:17
Copy: 7 Number of hits: 236
avatar of ianzeng123 ianzeng123
2
Follow
319
Followers

 Delayed Exit Strategy: The Art of Patience  Delayed Exit Strategy: The Art of Patience

🎯 What This Strategy Actually Does

You know what? Most traders have a bad habit: they run away the moment they see unfavorable signals! 😱 But this strategy does the complete opposite, telling you: “Hold on, let’s wait and see!”

It’s like dating - would you break up just because your partner said something in anger? Too impulsive! This strategy waits for 3 bars (adjustable) to see if it’s really time to “break up” or just an emotional outburst.

📊 Core Logic: No Impulsive Decisions

Entry Conditions: - Detect Higher Low/Lower High breakthrough patterns - Confirm with candlestick validation (correct closing direction) - Multi-dimensional scoring system: RSI momentum + Volume confirmation + Volatility analysis - Minimum score of 3.0 required for entry (out of 5.0)

Key Point! The scoring system is super intelligent, considering: - Candlestick strength (body-to-range ratio) - Volume expansion - RSI within reasonable range - Current volatility level

⏰ The Wisdom of Delayed Exits

Traditional strategy: See failure signal → Exit immediately This strategy: See failure signal → Wait 3 bars → Reconfirm → Rational exit

Why delay? 1. Avoid false breakout traps: Markets often “fake death,” delays filter noise 2. Reduce overtrading: Lower commission costs 3. Improve win rate: Give trends more time to develop

🛡️ Risk Management: Strict When It Matters

While exits are “zen-like,” risk control is absolutely strict: - Stop Loss: 1.5x ATR (adjustable) - Take Profit: 2.5x ATR (adjustable) - Trading Hours: Only during US market hours - EOD Close: Never hold overnight

🎨 Visual Design: Crystal Clear

  • 🟢 Green triangles: Regular long signals
  • 🔴 Red triangles: Regular short signals
  • 🏁 Flag markers: High-quality signals (score ≥4.5)
  • 🟠 Orange X: Early failure signals (ignored)
  • 🔴 Red X: Delayed failure signals (execute exit)

Pitfall Guide: Don’t panic when orange X appears - these are “false alarms” the strategy intentionally ignores!

💡 Best Use Cases

This strategy is perfect for: - Catching reversals in ranging markets - Traders tired of frequent stop-outs - Investors seeking higher signal quality - US stock intraday trading enthusiasts

Remember: Patience is a trader’s greatest weapon. Sometimes “wait and see” is wiser than “act immediately”! 🚀

Strategy source code
/*backtest
start: 2025-08-08 00:00:00
end: 2025-09-07 00:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDC"}]
*/

//@version=6
strategy("Delayed X Exit Strategy - Final Version", overlay=true)

// === INPUTS ===
// Strategy Settings
delayBars = input.int(3, "Delay X Exit (bars after entry)", minval=1, maxval=10, group="Exit Strategy")
showScores = input.bool(true, "Show Signal Scores", group="Display")
minScore = input.float(3.0, "Minimum Score to Trade", minval=1.0, maxval=5.0, step=0.1, group="Strategy")
volumePeriod = input.int(20, "Volume Average Period", group="Strategy")

// Risk Management
stopATRMult = input.float(1.5, "Stop Loss ATR Multiplier", minval=0.5, maxval=3.0, step=0.1, group="Risk Management")
targetATRMult = input.float(2.5, "Take Profit ATR Multiplier", minval=1.0, maxval=5.0, step=0.1, group="Risk Management")

// Time Filters - US Market Hours Only
startHour = input.int(9, "Start Trading Hour", minval=0, maxval=23, group="Time Filter")
endHour = input.int(16, "End Trading Hour", minval=0, maxval=23, group="Time Filter")
startMinute = input.int(30, "Start Trading Minute", minval=0, maxval=59, group="Time Filter")

// === TIME FILTER - MARKET HOURS ONLY ===
currentHour = hour(time, "America/New_York") 
currentMinute = minute(time, "America/New_York")
marketOpen = (currentHour == startHour and currentMinute >= startMinute) or (currentHour > startHour and currentHour < endHour)
inTradingHours = marketOpen

// --- Original Pattern Detection ---
lowPoint      = ta.lowest(low, 3)
prevLowPoint  = ta.lowest(low[3], 3)
isHigherLow   = low == lowPoint and low > prevLowPoint
bullConfirm   = isHigherLow and close > open

highPoint     = ta.highest(high, 3)
prevHighPoint = ta.highest(high[3], 3)
isLowerHigh   = high == highPoint and high < prevHighPoint
bearConfirm   = isLowerHigh and close < open

// --- Pattern Failures (X signals) ---
failHigherLow = isHigherLow[1] and low < low[1]
failLowerHigh = isLowerHigh[1] and high > high[1]

// Track entry information for delayed exit logic
var int entryBar = na
var string entryDirection = na
var float entryPrice = na

// === ENHANCED SCORING SYSTEM ===
rsi = ta.rsi(close, 14)
atr = ta.atr(14)
avgVolume = ta.sma(volume, volumePeriod)

// Scoring components (optimized for delayed exits)
bullCandleStrength = bullConfirm ? (close > open and (close - open) / (high - low) > 0.6 ? 1 : 0.5) : 0
bearCandleStrength = bearConfirm ? (close < open and (open - close) / (high - low) > 0.6 ? 1 : 0.5) : 0
volumeConfirm = volume > avgVolume * 1.2 ? 1 : (volume > avgVolume ? 0.5 : 0)
bullMomentum = bullConfirm ? (rsi > 25 and rsi < 65 ? 1 : (rsi < 75 ? 0.5 : 0)) : 0
bearMomentum = bearConfirm ? (rsi > 35 and rsi < 75 ? 1 : (rsi > 25 ? 0.5 : 0)) : 0
currentRange = high - low
volatilityScore = currentRange > atr * 0.7 ? 1 : 0.5

// Pattern quality (more lenient for delayed exits)
recentBullSignals = ta.barssince(bullConfirm)
recentBearSignals = ta.barssince(bearConfirm)
bullPatternQuality = bullConfirm ? (na(recentBearSignals) or recentBearSignals > 2 ? 1 : 0.5) : 0
bearPatternQuality = bearConfirm ? (na(recentBullSignals) or recentBullSignals > 2 ? 1 : 0.5) : 0

// Calculate total scores
bullScore = bullConfirm ? bullCandleStrength + volumeConfirm + bullMomentum + volatilityScore + bullPatternQuality : 0
bearScore = bearConfirm ? bearCandleStrength + volumeConfirm + bearMomentum + volatilityScore + bearPatternQuality : 0

// === TRADE SIGNALS ===
longSignal = bullConfirm and bullScore >= minScore and inTradingHours
shortSignal = bearConfirm and bearScore >= minScore and inTradingHours

// === STRATEGY ENTRIES ===
if longSignal and strategy.position_size == 0
    strategy.entry("LONG", strategy.long, qty=1)
    entryBar := bar_index
    entryDirection := "LONG"
    entryPrice := close
    
if shortSignal and strategy.position_size == 0
    strategy.entry("SHORT", strategy.short, qty=1)
    entryBar := bar_index
    entryDirection := "SHORT"
    entryPrice := close

// === DELAYED EXIT LOGIC ===
// Only consider X exits if they occur delayBars+ after entry
shouldExitOnDelayedFailure = false
barsAfterEntry = na(entryBar) ? 0 : bar_index - entryBar

if strategy.position_size != 0 and not na(entryBar) and barsAfterEntry >= delayBars
    // Check for pattern failure that matches our position direction
    if strategy.position_size > 0 and failHigherLow
        shouldExitOnDelayedFailure := true
    if strategy.position_size < 0 and failLowerHigh  
        shouldExitOnDelayedFailure := true

// Execute delayed failure exits
if shouldExitOnDelayedFailure
    if strategy.position_size > 0
        strategy.close("LONG", comment="Delayed X Exit")
    if strategy.position_size < 0
        strategy.close("SHORT", comment="Delayed X Exit")
    entryBar := na
    entryDirection := na
    entryPrice := na

// === STANDARD STOP/TARGET EXITS ===
// Only use stop/target if we haven't exited on delayed failure
if strategy.position_size > 0 and not shouldExitOnDelayedFailure  // Long position
    stopLevel = strategy.position_avg_price - (atr * stopATRMult)
    targetLevel = strategy.position_avg_price + (atr * targetATRMult)
    strategy.exit("LONG_EXIT", "LONG", stop=stopLevel, limit=targetLevel)

if strategy.position_size < 0 and not shouldExitOnDelayedFailure  // Short position  
    stopLevel = strategy.position_avg_price + (atr * stopATRMult)
    targetLevel = strategy.position_avg_price - (atr * targetATRMult)
    strategy.exit("SHORT_EXIT", "SHORT", stop=stopLevel, limit=targetLevel)

// Reset entry tracking when position closes
if strategy.position_size == 0 and not na(entryBar)
    entryBar := na
    entryDirection := na
    entryPrice := na

// End of day exit
if not inTradingHours and strategy.position_size != 0
    strategy.close_all(comment="EOD")
    entryBar := na
    entryDirection := na
    entryPrice := na

// === VISUAL ELEMENTS ===

// Main entry signals
plotshape(longSignal, "Long Entry", shape.triangleup, location.belowbar, 
          color=color.new(color.lime, 0), size=size.normal)
plotshape(shortSignal, "Short Entry", shape.triangledown, location.abovebar, 
          color=color.new(color.red, 0), size=size.normal)

// Premium signals (score >= 4.5)
premiumLong = longSignal and bullScore >= 4.5
premiumShort = shortSignal and bearScore >= 4.5

plotshape(premiumLong, "Premium Long", shape.flag, location.belowbar, 
          color=color.new(color.aqua, 0), size=size.large)
plotshape(premiumShort, "Premium Short", shape.flag, location.abovebar, 
          color=color.new(color.fuchsia, 0), size=size.large)

// Pattern failures - Orange for early (ignored), Red for delayed (actionable)
earlyFailure = (failHigherLow or failLowerHigh) and not na(entryBar) and barsAfterEntry < delayBars
actionableFailure = (failHigherLow or failLowerHigh) and not na(entryBar) and barsAfterEntry >= delayBars

plotshape(earlyFailure, "Early X (Ignored)", shape.xcross, location.abovebar, 
          color=color.new(color.orange, 0), size=size.small)
plotshape(actionableFailure, "Delayed X (Exit)", shape.xcross, location.abovebar, 
          color=color.new(color.red, 0), size=size.normal)

// Entry confirmation arrows
plotarrow(longSignal ? 1 : shortSignal ? -1 : 0, 
          colorup=color.new(color.green, 30), colordown=color.new(color.red, 30))

// === ENHANCED POSITION VISUALIZATION ===
var line stopLine = na
var line targetLine = na  
var label positionLabel = na
var label delayLabel = na

if strategy.position_size != 0
    
    // Draw position lines and labels
    if strategy.position_size > 0  // Long position
        stopPrice = strategy.position_avg_price - (atr * stopATRMult)
        targetPrice = strategy.position_avg_price + (atr * targetATRMult)
        
        // Show delay status
        delayText = barsAfterEntry < delayBars ? 
                   "X Ignored (" + str.tostring(barsAfterEntry) + "/" + str.tostring(delayBars) + ")" : 
                   "X Active (" + str.tostring(barsAfterEntry) + " bars)"
        delayLabel := label.new(bar_index, high + (atr * 2), delayText, 
                              color=barsAfterEntry < delayBars ? color.orange : color.red, 
                              textcolor=color.white, size=size.small)
    
    if strategy.position_size < 0  // Short position
        stopPrice = strategy.position_avg_price + (atr * stopATRMult)
        targetPrice = strategy.position_avg_price - (atr * targetATRMult)

        
        // Show delay status  
        delayText = barsAfterEntry < delayBars ? 
                   "X Ignored (" + str.tostring(barsAfterEntry) + "/" + str.tostring(delayBars) + ")" : 
                   "X Active (" + str.tostring(barsAfterEntry) + " bars)"
        delayLabel := label.new(bar_index, low - (atr * 2), delayText, 
                              color=barsAfterEntry < delayBars ? color.orange : color.red, 
                              textcolor=color.white, size=size.small)


// === ALERTS ===
alertcondition(longSignal, title="Long Entry", message="LONG Entry Signal Triggered")
alertcondition(shortSignal, title="Short Entry", message="SHORT Entry Signal Triggered")
alertcondition(shouldExitOnDelayedFailure, title="Delayed X Exit", message="Pattern Failure Exit - Delayed Strategy")
alertcondition(premiumLong, title="Premium Long", message="PREMIUM LONG Signal - High Probability Setup")
alertcondition(premiumShort, title="Premium Short", message="PREMIUM SHORT Signal - High Probability Setup")