Strategy · Pine Script v5 · On the chart

WR-SR + SMC Strategy ENHANCED

by alboogycOdR· code credited to KingdomFinancier - Wick Rejection + SMC Hybrid Strategy

This hybrid trading strategy combines wick rejection support and resistance levels with Smart Money Concepts.

View on GitHub

GitHub stars6on the repository
Pine versionv5runs as is
Lines of code1,441
Settings40inputs
LicenceNone statedfile: MPL-2.0
Last update7 months ago16 Mar 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new strategy, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.

Source Code

1,441 lines of Pine Script v5 from tradingview/shane-scalp-snr/updates/WR_SMC_Strategy_v4_1_ENHANCED.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

WR_SMC_Strategy_v4_1_ENHANCED.pine
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © KingdomFinancier - Wick Rejection + SMC Hybrid Strategy
// Version: 4.1 ENHANCED (FULL SMC INTEGRATION)
// 
// ✅ v4.1 NEW: FVG Tap Detection (+2 confidence)
// ✅ v4.1 NEW: Order Block Confluence (+2 confidence)
// ✅ v4.1 NEW: Recent CHoCH Filter (+2 confidence)
// ✅ v4.1 NEW: HTF Structure Confluence (+2 confidence)
// ✅ v4.1 NEW: Premium/Discount Zone Filter
// ✅ v4.1 NEW: Sweep + CHoCH Combo (+3 confidence)
// ✅ v4.1 NEW: Dynamic Position Sizing (1-4%)
// ✅ v4.1 NEW: Dynamic R:R Based on Confidence Tiers
// ✅ v4.1 NEW: Enhanced Visual Labels with Tier Emojis

//@version=5
strategy("WR-SR + SMC Strategy v4.1 ENHANCED", shorttitle="WR-SMC v4.1", overlay=true, max_lines_count=100, max_boxes_count=100, max_labels_count=100, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=2, commission_type=strategy.commission.percent, commission_value=0.05, slippage=2, pyramiding=1, close_entries_rule="ANY")

// ═══════════════════════════════════════════════════════════════════════════════
// INPUTS - SMC FEATURES (BASE)
// ═══════════════════════════════════════════════════════════════════════════════
grp_smc = "══════ SMC Features ══════"
enable_smc          = input.bool(true, "Enable SMC Components", group=grp_smc, tooltip="Turn on/off all SMC features")
show_choch_bos      = input.bool(true, "Show CHoCH/BOS Labels", group=grp_smc)
show_fvg            = input.bool(true, "Show FVG Zones", group=grp_smc)
show_order_blocks   = input.bool(true, "Show Order Blocks", group=grp_smc)
show_premium_discount = input.bool(false, "Show Premium/Discount Zones", group=grp_smc, tooltip="May use extra boxes")
show_structure_lines = input.bool(true, "Show HTF Structure Lines", group=grp_smc)
max_fvg_zones       = input.int(3, "Max FVG Zones per Side", minval=1, maxval=5, group=grp_smc)
max_ob_zones        = input.int(2, "Max Order Blocks per Side", minval=1, maxval=3, group=grp_smc)
smc_htf             = input.timeframe("60", "SMC HTF for Structure", group=grp_smc)
fractal_sensitivity = input.int(3, "Fractal Sensitivity", minval=2, maxval=10, group=grp_smc)

// ═══════════════════════════════════════════════════════════════════════════════
// INPUTS - SMC ENHANCED FEATURES (v4.1 NEW)
// ═══════════════════════════════════════════════════════════════════════════════
grp_smc_enhanced = "══════ SMC Enhanced v4.1 ══════"
use_fvg_tap_bonus       = input.bool(true, "FVG Tap Bonus (+2)", group=grp_smc_enhanced, tooltip="Add +2 confidence when price taps into FVG zone")
use_ob_confluence_bonus = input.bool(true, "Order Block Confluence (+2)", group=grp_smc_enhanced, tooltip="Add +2 when S/R level aligns with Order Block")
use_recent_choch_bonus  = input.bool(true, "Recent CHoCH Bonus (+2)", group=grp_smc_enhanced, tooltip="Add +2 when CHoCH occurred within lookback")
use_htf_confluence_bonus = input.bool(true, "HTF Structure Confluence (+2)", group=grp_smc_enhanced, tooltip="Add +2 when level aligns with HTF pivot")
use_premium_discount_filter = input.bool(true, "Premium/Discount Zone Filter", group=grp_smc_enhanced, tooltip="Filter or reject trades in wrong zones")
pd_filter_mode          = input.string("Bonus Only", "P/D Filter Mode", options=["Reject", "Bonus Only"], group=grp_smc_enhanced, tooltip="Reject=No trade in wrong zone, Bonus=+1 in correct zone")
use_sweep_choch_combo   = input.bool(true, "Sweep+CHoCH Combo (+3)", group=grp_smc_enhanced, tooltip="Add +3 when sweep followed by CHoCH")
use_smc_alignment_score = input.bool(true, "SMC Alignment Score (+0-4)", group=grp_smc_enhanced, tooltip="Add 0-4 based on overall SMC alignment")
choch_lookback_bars     = input.int(20, "CHoCH Lookback Bars", minval=5, maxval=50, group=grp_smc_enhanced)
ob_confluence_tolerance = input.float(3.0, "OB Confluence Tolerance", minval=0.5, maxval=10.0, step=0.5, group=grp_smc_enhanced)
htf_confluence_tolerance = input.float(5.0, "HTF Confluence Tolerance", minval=1.0, maxval=20.0, step=1.0, group=grp_smc_enhanced)
sweep_choch_max_bars    = input.int(15, "Sweep+CHoCH Max Bars Apart", minval=5, maxval=30, group=grp_smc_enhanced)

// ═══════════════════════════════════════════════════════════════════════════════
// INPUTS - LEVEL DETECTION (EXISTING WR-SR)
// ═══════════════════════════════════════════════════════════════════════════════
grp_levels = "══════ Level Detection ══════"
lookback_period     = input.int(100, "Lookback Period", minval=20, maxval=200, group=grp_levels)
wick_threshold      = input.float(0.35, "Wick Threshold %", minval=0.30, maxval=0.80, step=0.05, group=grp_levels)
level_proximity     = input.float(2.0, "Level Merge Distance", minval=0.5, maxval=20.0, step=0.5, group=grp_levels)
max_levels          = input.int(8, "Max S/R Levels to Show", minval=2, maxval=10, group=grp_levels, tooltip="Reduced from 10 to save resources")
zone_buffer         = input.float(1.5, "Zone Buffer (points)", minval=0.5, maxval=10.0, step=0.5, group=grp_levels)
min_candle_range    = input.float(1.0, "Min Candle Range", minval=0.1, maxval=10.0, step=0.1, group=grp_levels)
level_expiration    = input.int(500, "Level Expiration (bars)", minval=50, maxval=500, group=grp_levels)

// ═══════════════════════════════════════════════════════════════════════════════
// INPUTS - TREND FILTER
// ═══════════════════════════════════════════════════════════════════════════════
grp_trend = "══════ Trend Filter ══════"
ema_length          = input.int(9, "EMA Length", minval=5, maxval=50, group=grp_trend)
use_ema_filter      = input.bool(true, "Use EMA Filter", group=grp_trend)
require_h1_align    = input.bool(true, "Require H1 Confluence", group=grp_trend)
allow_reversal_trades = input.bool(true, "Allow Reversal Trades", group=grp_trend)
reversal_min_confidence = input.int(6, "Reversal Min Confidence", minval=3, maxval=10, group=grp_trend, tooltip="v4.1: Increased for new scoring scale")
show_ema            = input.bool(true, "Show EMA Line", group=grp_trend)

// ═══════════════════════════════════════════════════════════════════════════════
// INPUTS - CISD (Change in State of Delivery)
// ═══════════════════════════════════════════════════════════════════════════════
grp_cisd = "══════ CISD Settings ══════"
use_cisd            = input.bool(true, "Enable CISD", group=grp_cisd)
cisd_min_duration   = input.int(3, "Min CISD Duration", minval=0, maxval=20, group=grp_cisd)
cisd_max_duration   = input.int(50, "Max CISD Validity", minval=10, maxval=200, group=grp_cisd)
cisd_confidence_boost = input.int(1, "CISD Confidence Boost", minval=1, maxval=2, group=grp_cisd)
show_cisd_labels    = input.bool(true, "Show CISD Labels", group=grp_cisd)

// ═══════════════════════════════════════════════════════════════════════════════
// INPUTS - SIGNAL SETTINGS
// ═══════════════════════════════════════════════════════════════════════════════
grp_signals = "══════ Signal Settings ══════"
show_zone_test      = input.bool(true, "Show Zone Test Signals", group=grp_signals)
show_sweeps         = input.bool(true, "Show Liquidity Sweeps", group=grp_signals)
show_breakout_retest = input.bool(true, "Show Breakout Retests", group=grp_signals)
min_confidence      = input.int(6, "Minimum Confidence Score", minval=1, maxval=15, group=grp_signals, tooltip="v4.1: Scale is now 0-20, recommend 6+ for FAIR tier")
signal_cooldown     = input.int(8, "Signal Cooldown (bars)", minval=1, maxval=20, group=grp_signals)
max_signal_labels   = input.int(5, "Max Signal Labels", minval=3, maxval=8, group=grp_signals, tooltip="Reduced to save label space")

// ═══════════════════════════════════════════════════════════════════════════════
// INPUTS - VISUALS
// ═══════════════════════════════════════════════════════════════════════════════
grp_visuals = "══════ Visual Settings ══════"
resistance_color    = input.color(color.red, "Resistance Color", group=grp_visuals)
support_color       = input.color(color.green, "Support Color", group=grp_visuals)
zone_transparency   = input.int(90, "Zone Transparency", minval=70, maxval=98, group=grp_visuals)
show_zones          = input.bool(true, "Show Zone Boxes", group=grp_visuals)
show_labels         = input.bool(true, "Show Price Labels", group=grp_visuals)
show_info_table     = input.bool(true, "Show Info Table", group=grp_visuals)
table_text_size     = input.string("Normal", "Table Font Size", options=["Small", "Normal", "Large"], group=grp_visuals)
buy_signal_color    = input.color(color.green, "Buy Signal Color", group=grp_visuals)
sell_signal_color   = input.color(color.red, "Sell Signal Color", group=grp_visuals)

// ═══════════════════════════════════════════════════════════════════════════════
// INPUTS - STRATEGY & RISK MANAGEMENT
// ═══════════════════════════════════════════════════════════════════════════════
grp_strategy = "══════ Strategy & Risk Management ══════"
enable_strategy     = input.bool(true, "Enable Auto Trading", group=grp_strategy)
use_dynamic_sizing  = input.bool(true, "Dynamic Position Sizing", group=grp_strategy, tooltip="v4.1: Size based on confidence tier")
base_position_pct   = input.float(2.0, "Base Position %", minval=0.5, maxval=5.0, step=0.5, group=grp_strategy)
use_dynamic_rr      = input.bool(true, "Dynamic R:R Based on Confidence", group=grp_strategy, tooltip="v4.1: TP levels adjust to confidence tier")
risk_reward_ratio   = input.float(2.0, "Risk:Reward Ratio (if static)", minval=1.0, maxval=5.0, step=0.5, group=grp_strategy)
use_dynamic_tp      = input.bool(true, "Use Dynamic TP", group=grp_strategy)
tp_buffer           = input.float(0.5, "TP Buffer (points)", minval=0.0, maxval=5.0, step=0.5, group=grp_strategy)
use_trailing_stop   = input.bool(false, "Use Trailing Stop", group=grp_strategy)
trail_activation    = input.float(1.5, "Trail Activation (R)", minval=0.5, maxval=3.0, step=0.5, group=grp_strategy)
trail_offset        = input.float(0.5, "Trail Offset (R)", minval=0.1, maxval=2.0, step=0.1, group=grp_strategy)
close_on_opposite   = input.bool(true, "Close on Opposite Signal", group=grp_strategy)
max_trades_per_day  = input.int(10, "Max Trades Per Day", minval=0, maxval=50, group=grp_strategy)

// ═══════════════════════════════════════════════════════════════════════════════
// INPUTS - TAKE PROFIT LEVELS
// ═══════════════════════════════════════════════════════════════════════════════
grp_tp = "══════ Take Profit Settings ══════"
use_multiple_tp     = input.bool(true, "Use Multiple TP Levels", group=grp_tp)
tp1_percent         = input.int(50, "TP1 Close %", minval=10, maxval=100, group=grp_tp)
tp1_rr              = input.float(1.5, "TP1 R:R (if static)", minval=0.5, maxval=5.0, step=0.5, group=grp_tp)
tp2_percent         = input.int(30, "TP2 Close %", minval=10, maxval=100, group=grp_tp)
tp2_rr              = input.float(2.5, "TP2 R:R (if static)", minval=1.0, maxval=10.0, step=0.5, group=grp_tp)
tp3_rr              = input.float(4.0, "TP3 R:R (if static)", minval=2.0, maxval=20.0, step=1.0, group=grp_tp)

// ═══════════════════════════════════════════════════════════════════════════════
// CALCULATIONS - EMA & HTF DATA
// ═══════════════════════════════════════════════════════════════════════════════
ema_9 = ta.ema(close, ema_length)
[h1_close, h1_ema9] = request.security(syminfo.tickerid, "60", [close, ta.ema(close, ema_length)], lookahead=barmerge.lookahead_off)

m5_bullish = close > ema_9
m5_bearish = close < ema_9
h1_bullish = h1_close > h1_ema9
h1_bearish = h1_close < h1_ema9

f_has_h1_bullish_confluence() => not require_h1_align or h1_bullish
f_has_h1_bearish_confluence() => not require_h1_align or h1_bearish

overall_bullish = m5_bullish and f_has_h1_bullish_confluence()
overall_bearish = m5_bearish and f_has_h1_bearish_confluence()

// ═══════════════════════════════════════════════════════════════════════════════
// SMC - STRUCTURE DETECTION (CHoCH / BOS) WITH BAR TRACKING (v4.1)
// ═══════════════════════════════════════════════════════════════════════════════
pivotHigh = ta.pivothigh(high, fractal_sensitivity, fractal_sensitivity)
pivotLow = ta.pivotlow(low, fractal_sensitivity, fractal_sensitivity)

var float lastSwingHigh = na
var float lastSwingLow = na
var string smcTrendDir = "Neutral"

// v4.1 NEW: Bar tracking for temporal relationships
var int last_bull_choch_bar = 0
var int last_bear_choch_bar = 0
var int last_bull_bos_bar = 0
var int last_bear_bos_bar = 0
var int last_sweep_buy_bar = 0
var int last_sweep_sell_bar = 0

if not na(pivotHigh)
    lastSwingHigh := high[fractal_sensitivity]
if not na(pivotLow)
    lastSwingLow := low[fractal_sensitivity]

bullishCHoCH = not na(pivotHigh) and high[fractal_sensitivity] > nz(lastSwingHigh[1]) and smcTrendDir == "Bearish"
bearishCHoCH = not na(pivotLow) and low[fractal_sensitivity] < nz(lastSwingLow[1]) and smcTrendDir == "Bullish"
bullishBOS = not na(pivotLow) and low[fractal_sensitivity] > nz(lastSwingLow[1])
bearishBOS = not na(pivotHigh) and high[fractal_sensitivity] < nz(lastSwingHigh[1])

// v4.1: Update bar tracking
if bullishCHoCH
    last_bull_choch_bar := bar_index
if bearishCHoCH
    last_bear_choch_bar := bar_index
if bullishBOS
    last_bull_bos_bar := bar_index
if bearishBOS
    last_bear_bos_bar := bar_index

smcTrendDir := bullishCHoCH or bullishBOS ? "Bullish" : bearishCHoCH or bearishBOS ? "Bearish" : smcTrendDir

// ═══════════════════════════════════════════════════════════════════════════════
// SMC - HTF STRUCTURE LINES
// ═══════════════════════════════════════════════════════════════════════════════
htfPivotHigh = request.security(syminfo.tickerid, smc_htf, ta.pivothigh(high, fractal_sensitivity, fractal_sensitivity)[1], lookahead=barmerge.lookahead_off)
htfPivotLow = request.security(syminfo.tickerid, smc_htf, ta.pivotlow(low, fractal_sensitivity, fractal_sensitivity)[1], lookahead=barmerge.lookahead_off)

var float htfLastHigh = na
var float htfLastLow = na

if not na(htfPivotHigh)
    htfLastHigh := htfPivotHigh
if not na(htfPivotLow)
    htfLastLow := htfPivotLow

plot(enable_smc and show_structure_lines ? htfLastHigh : na, "HTF Resistance", color=color.new(color.red, 30), linewidth=2, style=plot.style_linebr)
plot(enable_smc and show_structure_lines ? htfLastLow : na, "HTF Support", color=color.new(color.green, 30), linewidth=2, style=plot.style_linebr)

// ═══════════════════════════════════════════════════════════════════════════════
// SMC - ORDER BLOCKS (OPTIMIZED)
// ═══════════════════════════════════════════════════════════════════════════════
var box[] bullOBs = array.new_box()
var box[] bearOBs = array.new_box()
var label[] obLabels = array.new_label()

if enable_smc and show_order_blocks and barstate.isconfirmed
    if not na(pivotLow) and smcTrendDir == "Bullish"
        if array.size(bullOBs) >= max_ob_zones
            old_box = array.shift(bullOBs)
            box.delete(old_box)
        ob_box = box.new(bar_index - 5, high, bar_index + 50, low, border_color=color.new(color.green, 70), bgcolor=color.new(color.green, 90), extend=extend.right)
        array.push(bullOBs, ob_box)
    
    if not na(pivotHigh) and smcTrendDir == "Bearish"
        if array.size(bearOBs) >= max_ob_zones
            old_box = array.shift(bearOBs)
            box.delete(old_box)
        ob_box = box.new(bar_index - 5, high, bar_index + 50, low, border_color=color.new(color.red, 70), bgcolor=color.new(color.red, 90), extend=extend.right)
        array.push(bearOBs, ob_box)

// ═══════════════════════════════════════════════════════════════════════════════
// SMC - FVG (FAIR VALUE GAP) ZONES (OPTIMIZED)
// ═══════════════════════════════════════════════════════════════════════════════
var box[] bullFVGs = array.new_box()
var box[] bearFVGs = array.new_box()

if enable_smc and show_fvg and barstate.isconfirmed
    if low[2] > high[0] and smcTrendDir == "Bullish"
        if array.size(bullFVGs) >= max_fvg_zones
            old_fvg = array.shift(bullFVGs)
            box.delete(old_fvg)
        fvg_box = box.new(bar_index - 2, low[2], bar_index, high[0], border_color=color.new(color.lime, 50), bgcolor=color.new(color.lime, 92), extend=extend.right)
        array.push(bullFVGs, fvg_box)
    
    if high[2] < low[0] and smcTrendDir == "Bearish"
        if array.size(bearFVGs) >= max_fvg_zones
            old_fvg = array.shift(bearFVGs)
            box.delete(old_fvg)
        fvg_box = box.new(bar_index - 2, high[2], bar_index, low[0], border_color=color.new(color.red, 50), bgcolor=color.new(color.red, 92), extend=extend.right)
        array.push(bearFVGs, fvg_box)

// ═══════════════════════════════════════════════════════════════════════════════
// SMC - PREMIUM/DISCOUNT ZONES (OPTIONAL VISUAL)
// ═══════════════════════════════════════════════════════════════════════════════
var box premiumBox = na
var box discountBox = na
var line eqLine = na

if enable_smc and show_premium_discount and not na(lastSwingHigh) and not na(lastSwingLow) and barstate.islast
    if not na(premiumBox)
        box.delete(premiumBox)
        box.delete(discountBox)
        line.delete(eqLine)
    eqPrice = (lastSwingHigh + lastSwingLow) / 2
    premiumBox := box.new(bar_index, lastSwingHigh, bar_index + 50, eqPrice, bgcolor=color.new(color.red, 95), border_color=na, extend=extend.right)
    discountBox := box.new(bar_index, eqPrice, bar_index + 50, lastSwingLow, bgcolor=color.new(color.green, 95), border_color=na, extend=extend.right)
    eqLine := line.new(bar_index, eqPrice, bar_index + 50, eqPrice, color=color.new(color.gray, 50), width=1, style=line.style_dashed)

// ═══════════════════════════════════════════════════════════════════════════════
// SMC - STRUCTURE LABELS (MEMORY-OPTIMIZED)
// ═══════════════════════════════════════════════════════════════════════════════
var label[] smcLabels = array.new_label()
max_smc_labels = 8

if enable_smc and show_choch_bos and barstate.isconfirmed
    if bullishCHoCH
        lbl = label.new(bar_index, low, "CHoCH ↑", style=label.style_label_up, color=color.new(color.orange, 30), textcolor=color.white, size=size.tiny)
        array.push(smcLabels, lbl)
    if bearishCHoCH
        lbl = label.new(bar_index, high, "CHoCH ↓", style=label.style_label_down, color=color.new(color.orange, 30), textcolor=color.white, size=size.tiny)
        array.push(smcLabels, lbl)
    if bullishBOS
        lbl = label.new(bar_index, low, "BOS ↑", style=label.style_label_up, color=color.new(color.lime, 30), textcolor=color.black, size=size.tiny)
        array.push(smcLabels, lbl)
    if bearishBOS
        lbl = label.new(bar_index, high, "BOS ↓", style=label.style_label_down, color=color.new(color.red, 30), textcolor=color.white, size=size.tiny)
        array.push(smcLabels, lbl)
    
    if array.size(smcLabels) > max_smc_labels
        old_lbl = array.shift(smcLabels)
        label.delete(old_lbl)

// ═══════════════════════════════════════════════════════════════════════════════
// CISD (Change in State of Delivery) TRACKING
// ═══════════════════════════════════════════════════════════════════════════════
bull_candle = close > open
bear_candle = close < open

var float cisd_bull_level = na
var int cisd_bull_start = 0
var bool cisd_bull_active = false
var bool cisd_bearish_signal = false

var float cisd_bear_level = na
var int cisd_bear_start = 0
var bool cisd_bear_active = false
var bool cisd_bullish_signal = false

cisd_bearish_signal := false
cisd_bullish_signal := false

if use_cisd and barstate.isconfirmed
    if bull_candle and bear_candle[1]
        if cisd_bull_active and not na(cisd_bull_level)
            cisd_bull_active := false
        cisd_bull_level := open
        cisd_bull_start := bar_index
        cisd_bull_active := true
    
    if cisd_bull_active and not na(cisd_bull_level)
        if bar_index - cisd_bull_start <= cisd_max_duration
            if close < cisd_bull_level
                if bar_index - cisd_bull_start >= cisd_min_duration
                    cisd_bearish_signal := true
                    if show_cisd_labels
                        label.new(bar_index, high, "CISD ▼", style=label.style_label_down, color=color.new(sell_signal_color, 80), textcolor=sell_signal_color, size=size.tiny)
                cisd_bull_active := false
        else
            cisd_bull_active := false
    
    if bear_candle and bull_candle[1]
        if cisd_bear_active and not na(cisd_bear_level)
            cisd_bear_active := false
        cisd_bear_level := open
        cisd_bear_start := bar_index
        cisd_bear_active := true
    
    if cisd_bear_active and not na(cisd_bear_level)
        if bar_index - cisd_bear_start <= cisd_max_duration
            if close > cisd_bear_level
                if bar_index - cisd_bear_start >= cisd_min_duration
                    cisd_bullish_signal := true
                    if show_cisd_labels
                        label.new(bar_index, low, "CISD ▲", style=label.style_label_up, color=color.new(buy_signal_color, 80), textcolor=buy_signal_color, size=size.tiny)
                cisd_bear_active := false
        else
            cisd_bear_active := false

// ═══════════════════════════════════════════════════════════════════════════════
// FUNCTIONS - WICK CALCULATIONS
// ═══════════════════════════════════════════════════════════════════════════════
f_candle_range() => high - low
f_body_top() => math.max(open, close)
f_body_bottom() => math.min(open, close)
f_upper_wick() => high - f_body_top()
f_lower_wick() => f_body_bottom() - low

f_upper_wick_ratio() =>
    range_size = f_candle_range()
    range_size > min_candle_range ? f_upper_wick() / range_size : 0.0

f_lower_wick_ratio() =>
    range_size = f_candle_range()
    range_size > min_candle_range ? f_lower_wick() / range_size : 0.0

f_is_bullish_rejection() => f_lower_wick_ratio() >= wick_threshold
f_is_bearish_rejection() => f_upper_wick_ratio() >= wick_threshold

// ═══════════════════════════════════════════════════════════════════════════════
// v4.1 NEW: SMC CONFLUENCE FUNCTIONS
// ═══════════════════════════════════════════════════════════════════════════════

// FVG Tap Detection (+2 confidence)
f_check_fvg_tap(bool is_bullish) =>
    tapped = false
    if enable_smc and use_fvg_tap_bonus
        if is_bullish and array.size(bullFVGs) > 0
            for i = 0 to math.min(array.size(bullFVGs) - 1, max_fvg_zones - 1)
                fvg = array.get(bullFVGs, i)
                if not na(fvg)
                    fvg_top = box.get_top(fvg)
                    fvg_bot = box.get_bottom(fvg)
                    if low <= fvg_top and low >= fvg_bot
                        tapped := true
                        break
        else if not is_bullish and array.size(bearFVGs) > 0
            for i = 0 to math.min(array.size(bearFVGs) - 1, max_fvg_zones - 1)
                fvg = array.get(bearFVGs, i)
                if not na(fvg)
                    fvg_top = box.get_top(fvg)
                    fvg_bot = box.get_bottom(fvg)
                    if high >= fvg_bot and high <= fvg_top
                        tapped := true
                        break
    tapped

// Order Block Confluence (+2 confidence)
f_check_ob_confluence(float price, bool is_bullish) =>
    confluence = false
    if enable_smc and use_ob_confluence_bonus
        if is_bullish and array.size(bullOBs) > 0
            for i = 0 to math.min(array.size(bullOBs) - 1, max_ob_zones - 1)
                ob = array.get(bullOBs, i)
                if not na(ob)
                    ob_low = box.get_bottom(ob)
                    ob_high = box.get_top(ob)
                    if price >= ob_low - ob_confluence_tolerance and price <= ob_high + ob_confluence_tolerance
                        confluence := true
                        break
        else if not is_bullish and array.size(bearOBs) > 0
            for i = 0 to math.min(array.size(bearOBs) - 1, max_ob_zones - 1)
                ob = array.get(bearOBs, i)
                if not na(ob)
                    ob_low = box.get_bottom(ob)
                    ob_high = box.get_top(ob)
                    if price >= ob_low - ob_confluence_tolerance and price <= ob_high + ob_confluence_tolerance
                        confluence := true
                        break
    confluence

// Recent CHoCH Filter (+2 confidence)
f_recent_choch(bool is_bullish) =>
    recent = false
    if enable_smc and use_recent_choch_bonus
        if is_bullish
            recent := bar_index - last_bull_choch_bar <= choch_lookback_bars and last_bull_choch_bar > 0
        else
            recent := bar_index - last_bear_choch_bar <= choch_lookback_bars and last_bear_choch_bar > 0
    recent

// HTF Structure Confluence (+2 confidence)
f_htf_structure_confluence(float price, bool is_bullish) =>
    confluence = false
    if enable_smc and use_htf_confluence_bonus
        if is_bullish and not na(htfLastLow)
            confluence := math.abs(price - htfLastLow) <= htf_confluence_tolerance
        else if not is_bullish and not na(htfLastHigh)
            confluence := math.abs(price - htfLastHigh) <= htf_confluence_tolerance
    confluence

// Premium/Discount Zone Filter (+1 or reject)
f_in_correct_zone(bool is_bullish) =>
    correct_zone = true
    bonus = 0
    if enable_smc and use_premium_discount_filter
        if not na(lastSwingHigh) and not na(lastSwingLow) and lastSwingHigh > lastSwingLow
            eqPrice = (lastSwingHigh + lastSwingLow) / 2
            if is_bullish
                correct_zone := close < eqPrice
                bonus := correct_zone ? 1 : 0
            else
                correct_zone := close > eqPrice
                bonus := correct_zone ? 1 : 0
    [correct_zone, bonus]

// Sweep + CHoCH Combo (+3 confidence)
f_sweep_then_choch(bool is_bullish, int sweep_bar) =>
    combo = false
    if enable_smc and use_sweep_choch_combo and sweep_bar > 0
        if is_bullish
            sweep_recent = bar_index - sweep_bar <= sweep_choch_max_bars
            choch_recent = bar_index - last_bull_choch_bar <= sweep_choch_max_bars and last_bull_choch_bar > 0
            choch_after_sweep = last_bull_choch_bar >= sweep_bar
            combo := sweep_recent and choch_recent and choch_after_sweep
        else
            sweep_recent = bar_index - sweep_bar <= sweep_choch_max_bars
            choch_recent = bar_index - last_bear_choch_bar <= sweep_choch_max_bars and last_bear_choch_bar > 0
            choch_after_sweep = last_bear_choch_bar >= sweep_bar
            combo := sweep_recent and choch_recent and choch_after_sweep
    combo

// SMC Alignment Score (+0-4 confidence)
f_calculate_smc_alignment(bool is_bullish) =>
    score = 0
    if enable_smc and use_smc_alignment_score
        if is_bullish and smcTrendDir == "Bullish"
            score += 1
        else if not is_bullish and smcTrendDir == "Bearish"
            score += 1
        
        choch_recent = is_bullish ? 
            (bar_index - last_bull_choch_bar <= 30 and last_bull_choch_bar > 0) : 
            (bar_index - last_bear_choch_bar <= 30 and last_bear_choch_bar > 0)
        bos_recent = is_bullish ? 
            (bar_index - last_bull_bos_bar <= 30 and last_bull_bos_bar > 0) : 
            (bar_index - last_bear_bos_bar <= 30 and last_bear_bos_bar > 0)
        if choch_recent or bos_recent
            score += 1
        
        if is_bullish and array.size(bullFVGs) > 0
            score += 1
        else if not is_bullish and array.size(bearFVGs) > 0
            score += 1
        
        if is_bullish and array.size(bullOBs) > 0
            score += 1
        else if not is_bullish and array.size(bearOBs) > 0
            score += 1
    score

// ═══════════════════════════════════════════════════════════════════════════════
// v4.1 NEW: DYNAMIC POSITION SIZING
// ═══════════════════════════════════════════════════════════════════════════════
f_calculate_position_size(int confidence) =>
    multiplier = 1.0
    if use_dynamic_sizing
        if confidence >= 15
            multiplier := 2.0      // 4% (PERFECT)
        else if confidence >= 12
            multiplier := 1.5      // 3% (EXCELLENT)
        else if confidence >= 9
            multiplier := 1.25     // 2.5% (GOOD)
        else if confidence >= 6
            multiplier := 1.0      // 2% (FAIR)
        else if confidence >= 3
            multiplier := 0.5      // 1% (WEAK)
        else
            multiplier := 0.0      // NO TRADE
    base_position_pct * multiplier

// ═══════════════════════════════════════════════════════════════════════════════
// v4.1 NEW: DYNAMIC R:R BASED ON CONFIDENCE
// ═══════════════════════════════════════════════════════════════════════════════
f_calculate_dynamic_rr_tiers(int confidence) =>
    t1 = tp1_rr
    t2 = tp2_rr
    t3 = tp3_rr
    if use_dynamic_rr
        if confidence >= 15      // PERFECT
            t1 := 2.0
            t2 := 3.5
            t3 := 6.0
        else if confidence >= 12 // EXCELLENT
            t1 := 1.75
            t2 := 3.0
            t3 := 5.0
        else if confidence >= 9  // GOOD
            t1 := 1.5
            t2 := 2.5
            t3 := 4.0
        else if confidence >= 6  // FAIR
            t1 := 1.25
            t2 := 2.0
            t3 := 3.0
        else                     // WEAK
            t1 := 1.0
            t2 := 1.5
            t3 := 2.0
    [t1, t2, t3]

// v4.1 NEW: Confidence Tier Label
f_get_confidence_tier(int confidence) =>
    if confidence >= 15
        "PERFECT"
    else if confidence >= 12
        "EXCELLENT"
    else if confidence >= 9
        "GOOD"
    else if confidence >= 6
        "FAIR"
    else if confidence >= 3
        "WEAK"
    else
        "REJECT"

f_get_tier_emoji(int confidence) =>
    if confidence >= 15
        "🔥🔥🔥"
    else if confidence >= 12
        "🔥🔥"
    else if confidence >= 9
        "🔥"
    else if confidence >= 6
        "⚡"
    else if confidence >= 3
        "⚠"
    else
        "❌"

// ═══════════════════════════════════════════════════════════════════════════════
// LEVEL STORAGE
// ═══════════════════════════════════════════════════════════════════════════════
type LevelData
    float price
    int touches
    int bar_created
    int last_signal_bar
    line level_line
    box level_box
    label level_label

var LevelData[] support_data = array.new<LevelData>()
var LevelData[] resistance_data = array.new<LevelData>()
var bool levels_changed = false

// ═══════════════════════════════════════════════════════════════════════════════
// FUNCTIONS - LEVEL MANAGEMENT
// ═══════════════════════════════════════════════════════════════════════════════
f_find_nearby_level_idx(LevelData[] levels, float price, float proximity) =>
    idx = -1
    if array.size(levels) > 0
        for i = 0 to array.size(levels) - 1
            level_obj = array.get(levels, i)
            if math.abs(level_obj.price - price) <= proximity
                idx := i
                break
    idx

f_delete_level_drawings(LevelData level_obj) =>
    if not na(level_obj.level_line)
        line.delete(level_obj.level_line)
    if not na(level_obj.level_box)
        box.delete(level_obj.level_box)
    if not na(level_obj.level_label)
        label.delete(level_obj.level_label)

f_remove_weakest_level(LevelData[] levels) =>
    if array.size(levels) > 0
        min_score = 999999.0
        min_idx = 0
        for i = 0 to array.size(levels) - 1
            level_obj = array.get(levels, i)
            age = bar_index - level_obj.bar_created
            score = level_obj.touches * 10.0 - age * 0.1
            if score < min_score
                min_score := score
                min_idx := i
        level_to_remove = array.get(levels, min_idx)
        f_delete_level_drawings(level_to_remove)
        array.remove(levels, min_idx)

f_add_or_update_support(float price) =>
    changed = false
    nearby_idx = f_find_nearby_level_idx(support_data, price, level_proximity)
    if nearby_idx >= 0
        level_obj = array.get(support_data, nearby_idx)
        level_obj.touches += 1
        level_obj.bar_created := bar_index
        array.set(support_data, nearby_idx, level_obj)
        changed := true
    else
        if array.size(support_data) >= max_levels
            f_remove_weakest_level(support_data)
        new_level = LevelData.new()
        new_level.price := price
        new_level.touches := 1
        new_level.bar_created := bar_index
        new_level.last_signal_bar := 0
        new_level.level_line := na
        new_level.level_box := na
        new_level.level_label := na
        array.push(support_data, new_level)
        changed := true
    changed

f_add_or_update_resistance(float price) =>
    changed = false
    nearby_idx = f_find_nearby_level_idx(resistance_data, price, level_proximity)
    if nearby_idx >= 0
        level_obj = array.get(resistance_data, nearby_idx)
        level_obj.touches += 1
        level_obj.bar_created := bar_index
        array.set(resistance_data, nearby_idx, level_obj)
        changed := true
    else
        if array.size(resistance_data) >= max_levels
            f_remove_weakest_level(resistance_data)
        new_level = LevelData.new()
        new_level.price := price
        new_level.touches := 1
        new_level.bar_created := bar_index
        new_level.last_signal_bar := 0
        new_level.level_line := na
        new_level.level_box := na
        new_level.level_label := na
        array.push(resistance_data, new_level)
        changed := true
    changed

f_expire_old_levels() =>
    changed = false
    if array.size(support_data) > 0
        for i = array.size(support_data) - 1 to 0
            level_obj = array.get(support_data, i)
            if bar_index - level_obj.bar_created > level_expiration
                f_delete_level_drawings(level_obj)
                array.remove(support_data, i)
                changed := true
    if array.size(resistance_data) > 0
        for i = array.size(resistance_data) - 1 to 0
            level_obj = array.get(resistance_data, i)
            if bar_index - level_obj.bar_created > level_expiration
                f_delete_level_drawings(level_obj)
                array.remove(resistance_data, i)
                changed := true
    changed

levels_changed := f_expire_old_levels() or levels_changed

if barstate.isconfirmed
    if f_is_bullish_rejection()
        levels_changed := f_add_or_update_support(low) or levels_changed
    if f_is_bearish_rejection()
        levels_changed := f_add_or_update_resistance(high) or levels_changed

// ═══════════════════════════════════════════════════════════════════════════════
// TAKE PROFIT CALCULATION FUNCTIONS
// ═══════════════════════════════════════════════════════════════════════════════
f_calculate_tp_levels(float entry, float sl, bool is_long, float rr1, float rr2, float rr3) =>
    risk_distance = math.abs(entry - sl)
    tp1 = 0.0
    tp2 = 0.0
    tp3 = 0.0
    if is_long
        tp1 := entry + (risk_distance * rr1)
        tp2 := entry + (risk_distance * rr2)
        tp3 := entry + (risk_distance * rr3)
    else
        tp1 := entry - (risk_distance * rr1)
        tp2 := entry - (risk_distance * rr2)
        tp3 := entry - (risk_distance * rr3)
    [tp1, tp2, tp3]

f_find_next_resistance(float current_price) =>
    nearest_res = 0.0
    min_dist = 99999.0
    if array.size(resistance_data) > 0
        for i = 0 to array.size(resistance_data) - 1
            r = array.get(resistance_data, i)
            dist = r.price - current_price
            if dist > 0 and dist < min_dist
                min_dist := dist
                nearest_res := r.price
    nearest_res

f_find_next_support(float current_price) =>
    nearest_sup = 0.0
    min_dist = 99999.0
    if array.size(support_data) > 0
        for i = 0 to array.size(support_data) - 1
            s = array.get(support_data, i)
            dist = current_price - s.price
            if dist > 0 and dist < min_dist
                min_dist := dist
                nearest_sup := s.price
    nearest_sup

f_calculate_dynamic_tp_price(float entry, float sl, bool is_long) =>
    dynamic_tp = 0.0
    if use_dynamic_tp
        if is_long
            next_level = f_find_next_resistance(entry)
            dynamic_tp := next_level > 0 ? next_level - tp_buffer : entry + (math.abs(entry - sl) * risk_reward_ratio)
        else
            next_level = f_find_next_support(entry)
            dynamic_tp := next_level > 0 ? next_level + tp_buffer : entry - (math.abs(entry - sl) * risk_reward_ratio)
    else
        risk_distance = math.abs(entry - sl)
        dynamic_tp := is_long ? entry + (risk_distance * risk_reward_ratio) : entry - (risk_distance * risk_reward_ratio)
    dynamic_tp

// ═══════════════════════════════════════════════════════════════════════════════
// ASYMMETRIC ZONE BUFFERS
// ═══════════════════════════════════════════════════════════════════════════════
support_zone_above = zone_buffer * 1.2
support_zone_below = zone_buffer * 0.8
resist_zone_above = zone_buffer * 0.8
resist_zone_below = zone_buffer * 1.2

// ═══════════════════════════════════════════════════════════════════════════════
// SIGNAL DETECTION (ENHANCED WITH v4.1 SMC CONFLUENCE)
// ═══════════════════════════════════════════════════════════════════════════════
var bool buy_signal = false
var bool sell_signal = false
var bool is_sweep_signal = false
var bool is_breakout_retest = false
var float signal_level = 0.0
var int signal_confidence = 0
var string signal_type = ""
var float suggested_sl = 0.0
var string confluence_text = ""

buy_signal := false
sell_signal := false
is_sweep_signal := false
is_breakout_retest := false
signal_confidence := 0
signal_type := ""
confluence_text := ""

// ═══════════════════════════════════════════════════════════════════════════════
// CHECK SUPPORT SIGNALS (WITH v4.1 SMC CONFLUENCE)
// ═══════════════════════════════════════════════════════════════════════════════
f_check_support_signals() =>
    _signal_found = false
    _is_sweep = false
    _level = 0.0
    _conf = 0
    _type = ""
    _sl = 0.0
    _confluence = ""
    
    if array.size(support_data) > 0 and barstate.isconfirmed
        for i = 0 to array.size(support_data) - 1
            if _signal_found
                break
            level_obj = array.get(support_data, i)
            level_price = level_obj.price
            touches = level_obj.touches
            last_sig = level_obj.last_signal_bar
            if bar_index - last_sig < signal_cooldown and last_sig > 0
                continue
            
            // v4.1: Check Premium/Discount filter first (skip if wrong zone in Reject mode)
            [in_correct_zone, zone_bonus] = f_in_correct_zone(true)
            if pd_filter_mode == "Reject" and not in_correct_zone
                continue
            
            zone_top = level_price + support_zone_above
            zone_bottom = level_price - support_zone_below
            in_zone = low <= zone_top and low >= zone_bottom
            swept = low < level_price and close > level_price
            rejecting = in_zone and f_is_bullish_rejection()
            
            if show_sweeps and swept
                _is_sweep := true
                _signal_found := true
                _level := level_price
                _sl := low - (zone_buffer * 0.5)
                _conf := 3  // Base sweep score
                
                // v4.1: Track sweep bar for combo detection
                last_sweep_buy_bar := bar_index
                
                // Original confluence
                _conf += touches >= 3 ? 1 : 0
                _conf += m5_bullish ? 1 : 0
                _conf += h1_bullish ? 1 : 0
                _conf += enable_smc and smcTrendDir == "Bullish" ? 1 : 0
                if use_cisd and cisd_bullish_signal
                    _conf += cisd_confidence_boost
                
                // v4.1 NEW: SMC Confluence Bonuses
                fvg_tapped = f_check_fvg_tap(true)
                ob_conf = f_check_ob_confluence(level_price, true)
                recent_choch = f_recent_choch(true)
                htf_conf = f_htf_structure_confluence(level_price, true)
                sweep_choch = f_sweep_then_choch(true, last_sweep_buy_bar)
                smc_align = f_calculate_smc_alignment(true)
                
                _conf += fvg_tapped ? 2 : 0
                _conf += ob_conf ? 2 : 0
                _conf += recent_choch ? 2 : 0
                _conf += htf_conf ? 2 : 0
                _conf += sweep_choch ? 3 : 0
                _conf += smc_align
                _conf += zone_bonus
                
                // Build confluence text for label
                _confluence := ""
                if fvg_tapped
                    _confluence += "FVG+"
                if ob_conf
                    _confluence += "OB+"
                if recent_choch
                    _confluence += "CHoCH+"
                if htf_conf
                    _confluence += "HTF+"
                if sweep_choch
                    _confluence += "COMBO+"
                
                _type := "LIQUIDITY SWEEP"
                level_obj.last_signal_bar := bar_index
                array.set(support_data, i, level_obj)
                
            else if show_zone_test and rejecting and not _signal_found
                conf = 1  // Base zone test score
                conf += touches >= 3 ? 1 : 0
                conf += f_lower_wick_ratio() > 0.6 ? 1 : 0
                conf += m5_bullish ? 1 : 0
                conf += h1_bullish ? 1 : 0
                conf += enable_smc and smcTrendDir == "Bullish" ? 1 : 0
                if use_cisd and cisd_bullish_signal
                    conf += cisd_confidence_boost
                
                // v4.1 NEW: SMC Confluence Bonuses
                fvg_tapped = f_check_fvg_tap(true)
                ob_conf = f_check_ob_confluence(level_price, true)
                recent_choch = f_recent_choch(true)
                htf_conf = f_htf_structure_confluence(level_price, true)
                smc_align = f_calculate_smc_alignment(true)
                
                conf += fvg_tapped ? 2 : 0
                conf += ob_conf ? 2 : 0
                conf += recent_choch ? 2 : 0
                conf += htf_conf ? 2 : 0
                conf += smc_align
                conf += zone_bonus
                
                if conf >= min_confidence
                    _signal_found := true
                    _level := level_price
                    _sl := zone_bottom - (zone_buffer * 0.5)
                    _conf := conf
                    _type := "ZONE TEST"
                    
                    // Build confluence text
                    _confluence := ""
                    if fvg_tapped
                        _confluence += "FVG+"
                    if ob_conf
                        _confluence += "OB+"
                    if recent_choch
                        _confluence += "CHoCH+"
                    if htf_conf
                        _confluence += "HTF+"
                    
                    level_obj.last_signal_bar := bar_index
                    array.set(support_data, i, level_obj)
                    
    [_signal_found, _is_sweep, _level, _conf, _type, _sl, _confluence]

// ═══════════════════════════════════════════════════════════════════════════════
// CHECK RESISTANCE SIGNALS (WITH v4.1 SMC CONFLUENCE)
// ═══════════════════════════════════════════════════════════════════════════════
f_check_resistance_signals() =>
    _signal_found = false
    _is_sweep = false
    _level = 0.0
    _conf = 0
    _type = ""
    _sl = 0.0
    _confluence = ""
    
    if array.size(resistance_data) > 0 and barstate.isconfirmed
        for i = 0 to array.size(resistance_data) - 1
            if _signal_found
                break
            level_obj = array.get(resistance_data, i)
            level_price = level_obj.price
            touches = level_obj.touches
            last_sig = level_obj.last_signal_bar
            if bar_index - last_sig < signal_cooldown and last_sig > 0
                continue
            
            // v4.1: Check Premium/Discount filter first
            [in_correct_zone, zone_bonus] = f_in_correct_zone(false)
            if pd_filter_mode == "Reject" and not in_correct_zone
                continue
            
            zone_top = level_price + resist_zone_above
            zone_bottom = level_price - resist_zone_below
            in_zone = high >= zone_bottom and high <= zone_top
            swept = high > level_price and close < level_price
            rejecting = in_zone and f_is_bearish_rejection()
            
            if show_sweeps and swept
                _is_sweep := true
                _signal_found := true
                _level := level_price
                _sl := high + (zone_buffer * 0.5)
                _conf := 3
                
                // v4.1: Track sweep bar
                last_sweep_sell_bar := bar_index
                
                _conf += touches >= 3 ? 1 : 0
                _conf += m5_bearish ? 1 : 0
                _conf += h1_bearish ? 1 : 0
                _conf += enable_smc and smcTrendDir == "Bearish" ? 1 : 0
                if use_cisd and cisd_bearish_signal
                    _conf += cisd_confidence_boost
                
                // v4.1 NEW: SMC Confluence
                fvg_tapped = f_check_fvg_tap(false)
                ob_conf = f_check_ob_confluence(level_price, false)
                recent_choch = f_recent_choch(false)
                htf_conf = f_htf_structure_confluence(level_price, false)
                sweep_choch = f_sweep_then_choch(false, last_sweep_sell_bar)
                smc_align = f_calculate_smc_alignment(false)
                
                _conf += fvg_tapped ? 2 : 0
                _conf += ob_conf ? 2 : 0
                _conf += recent_choch ? 2 : 0
                _conf += htf_conf ? 2 : 0
                _conf += sweep_choch ? 3 : 0
                _conf += smc_align
                _conf += zone_bonus
                
                _confluence := ""
                if fvg_tapped
                    _confluence += "FVG+"
                if ob_conf
                    _confluence += "OB+"
                if recent_choch
                    _confluence += "CHoCH+"
                if htf_conf
                    _confluence += "HTF+"
                if sweep_choch
                    _confluence += "COMBO+"
                
                _type := "LIQUIDITY SWEEP"
                level_obj.last_signal_bar := bar_index
                array.set(resistance_data, i, level_obj)
                
            else if show_zone_test and rejecting and not _signal_found
                conf = 1
                conf += touches >= 3 ? 1 : 0
                conf += f_upper_wick_ratio() > 0.6 ? 1 : 0
                conf += m5_bearish ? 1 : 0
                conf += h1_bearish ? 1 : 0
                conf += enable_smc and smcTrendDir == "Bearish" ? 1 : 0
                if use_cisd and cisd_bearish_signal
                    conf += cisd_confidence_boost
                
                // v4.1 NEW: SMC Confluence
                fvg_tapped = f_check_fvg_tap(false)
                ob_conf = f_check_ob_confluence(level_price, false)
                recent_choch = f_recent_choch(false)
                htf_conf = f_htf_structure_confluence(level_price, false)
                smc_align = f_calculate_smc_alignment(false)
                
                conf += fvg_tapped ? 2 : 0
                conf += ob_conf ? 2 : 0
                conf += recent_choch ? 2 : 0
                conf += htf_conf ? 2 : 0
                conf += smc_align
                conf += zone_bonus
                
                if conf >= min_confidence
                    _signal_found := true
                    _level := level_price
                    _sl := zone_top + (zone_buffer * 0.5)
                    _conf := conf
                    _type := "ZONE TEST"
                    
                    _confluence := ""
                    if fvg_tapped
                        _confluence += "FVG+"
                    if ob_conf
                        _confluence += "OB+"
                    if recent_choch
                        _confluence += "CHoCH+"
                    if htf_conf
                        _confluence += "HTF+"
                    
                    level_obj.last_signal_bar := bar_index
                    array.set(resistance_data, i, level_obj)
                    
    [_signal_found, _is_sweep, _level, _conf, _type, _sl, _confluence]

[buy_found, buy_is_sweep, buy_level, buy_conf, buy_type, buy_sl, buy_confluence] = f_check_support_signals()
[sell_found, sell_is_sweep, sell_level, sell_conf, sell_type, sell_sl, sell_confluence] = f_check_resistance_signals()

if buy_found and (not use_ema_filter or overall_bullish or (allow_reversal_trades and buy_conf >= reversal_min_confidence))
    buy_signal := true
    is_sweep_signal := buy_is_sweep
    signal_level := buy_level
    signal_confidence := buy_conf
    signal_type := buy_type
    suggested_sl := buy_sl
    confluence_text := buy_confluence

if sell_found and (not use_ema_filter or overall_bearish or (allow_reversal_trades and sell_conf >= reversal_min_confidence))
    sell_signal := true
    is_sweep_signal := sell_is_sweep
    signal_level := sell_level
    signal_confidence := sell_conf
    signal_type := sell_type
    suggested_sl := sell_sl
    confluence_text := sell_confluence

// ═══════════════════════════════════════════════════════════════════════════════
// TRADE EXECUTION & MANAGEMENT
// ═══════════════════════════════════════════════════════════════════════════════
var int trades_today = 0
var int last_trade_day = 0
var float last_position_size = 0.0

if dayofweek != dayofweek[1]
    trades_today := 0
    last_trade_day := dayofweek

max_trades_reached = max_trades_per_day > 0 and trades_today >= max_trades_per_day

var float entry_price = 0.0
var float stop_loss = 0.0
var float tp1_price = 0.0
var float tp2_price = 0.0
var float tp3_price = 0.0
var float original_position_size = 0.0
var bool tp1_hit = false
var bool tp2_hit = false
var bool is_long_position = false
var int last_signal_confidence = 0
var string last_signal_tier = ""

if strategy.position_size == 0 and strategy.position_size[1] != 0
    is_long_position := false
    tp1_hit := false
    tp2_hit := false
    entry_price := 0.0
    original_position_size := 0.0

if close_on_opposite and enable_strategy
    if buy_signal and strategy.position_size < 0
        strategy.close("Short", alert_message="WR-SMC | Closed SHORT on opposite BUY signal")
    if sell_signal and strategy.position_size > 0
        strategy.close("Long", alert_message="WR-SMC | Closed LONG on opposite SELL signal")

if buy_signal and enable_strategy and not max_trades_reached and strategy.position_size == 0
    // v4.1: Calculate dynamic position size
    pos_size = f_calculate_position_size(signal_confidence)
    if pos_size > 0
        // v4.1: Calculate dynamic R:R levels
        [rr1, rr2, rr3] = f_calculate_dynamic_rr_tiers(signal_confidence)
        
        if use_multiple_tp
            [tp1, tp2, tp3] = f_calculate_tp_levels(close, suggested_sl, true, rr1, rr2, rr3)
            tp1_price := tp1
            tp2_price := tp2
            tp3_price := tp3
        else
            tp1_price := f_calculate_dynamic_tp_price(close, suggested_sl, true)
            tp2_price := tp1_price
            tp3_price := tp1_price
        
        entry_price := close
        stop_loss := suggested_sl
        is_long_position := true
        tp1_hit := false
        tp2_hit := false
        trades_today += 1
        last_signal_confidence := signal_confidence
        last_signal_tier := f_get_confidence_tier(signal_confidence)
        last_position_size := pos_size
        
        tier_emoji = f_get_tier_emoji(signal_confidence)
        tier_name = f_get_confidence_tier(signal_confidence)
        alert_msg = "WR-SMC BUY " + tier_name + " | " + signal_type + " | Conf:" + str.tostring(signal_confidence) + "/20 | Entry:" + str.tostring(close, format.mintick) + " | SL:" + str.tostring(suggested_sl, format.mintick) + " | Size:" + str.tostring(pos_size, "#.##") + "%"
        
        strategy.entry("Long", strategy.long, qty=pos_size, alert_message=alert_msg)
        original_position_size := strategy.position_size
        
        if use_trailing_stop
            risk_dist = math.abs(entry_price - stop_loss)
            trail_trigger = entry_price + (risk_dist * trail_activation)
            trail_offset_points = risk_dist * trail_offset
            strategy.exit("Long SL/Trail", "Long", stop=stop_loss, trail_price=trail_trigger, trail_offset=trail_offset_points)
        else
            strategy.exit("Long SL", "Long", stop=stop_loss)

if sell_signal and enable_strategy and not max_trades_reached and strategy.position_size == 0
    pos_size = f_calculate_position_size(signal_confidence)
    if pos_size > 0
        [rr1, rr2, rr3] = f_calculate_dynamic_rr_tiers(signal_confidence)
        
        if use_multiple_tp
            [tp1, tp2, tp3] = f_calculate_tp_levels(close, suggested_sl, false, rr1, rr2, rr3)
            tp1_price := tp1
            tp2_price := tp2
            tp3_price := tp3
        else
            tp1_price := f_calculate_dynamic_tp_price(close, suggested_sl, false)
            tp2_price := tp1_price
            tp3_price := tp1_price
        
        entry_price := close
        stop_loss := suggested_sl
        is_long_position := false
        tp1_hit := false
        tp2_hit := false
        trades_today += 1
        last_signal_confidence := signal_confidence
        last_signal_tier := f_get_confidence_tier(signal_confidence)
        last_position_size := pos_size
        
        tier_emoji = f_get_tier_emoji(signal_confidence)
        tier_name = f_get_confidence_tier(signal_confidence)
        alert_msg = "WR-SMC SELL " + tier_name + " | " + signal_type + " | Conf:" + str.tostring(signal_confidence) + "/20 | Entry:" + str.tostring(close, format.mintick) + " | SL:" + str.tostring(suggested_sl, format.mintick) + " | Size:" + str.tostring(pos_size, "#.##") + "%"
        
        strategy.entry("Short", strategy.short, qty=pos_size, alert_message=alert_msg)
        original_position_size := math.abs(strategy.position_size)
        
        if use_trailing_stop
            risk_dist = math.abs(entry_price - stop_loss)
            trail_trigger = entry_price - (risk_dist * trail_activation)
            trail_offset_points = risk_dist * trail_offset
            strategy.exit("Short SL/Trail", "Short", stop=stop_loss, trail_price=trail_trigger, trail_offset=trail_offset_points)
        else
            strategy.exit("Short SL", "Short", stop=stop_loss)

if strategy.position_size != 0 and original_position_size == 0.0
    original_position_size := math.abs(strategy.position_size)

if strategy.position_size != 0
    if is_long_position and strategy.position_size > 0
        if use_multiple_tp
            if not tp1_hit and high >= tp1_price
                close_qty = original_position_size * (tp1_percent / 100.0)
                strategy.close("Long", qty=close_qty, comment="TP1", alert_message="WR-SMC TP1 HIT | Closed " + str.tostring(tp1_percent) + "%")
                tp1_hit := true
            if tp1_hit and not tp2_hit and high >= tp2_price
                close_qty = original_position_size * (tp2_percent / 100.0)
                strategy.close("Long", qty=close_qty, comment="TP2", alert_message="WR-SMC TP2 HIT | Closed " + str.tostring(tp2_percent) + "%")
                tp2_hit := true
            if tp2_hit and high >= tp3_price
                strategy.close("Long", comment="TP3", alert_message="WR-SMC TP3 HIT | Full exit")
        else
            if high >= tp1_price
                strategy.close("Long", comment="TP", alert_message="WR-SMC TP HIT")
    if not is_long_position and strategy.position_size < 0
        if use_multiple_tp
            if not tp1_hit and low <= tp1_price
                close_qty = original_position_size * (tp1_percent / 100.0)
                strategy.close("Short", qty=close_qty, comment="TP1", alert_message="WR-SMC TP1 HIT | Closed " + str.tostring(tp1_percent) + "%")
                tp1_hit := true
            if tp1_hit and not tp2_hit and low <= tp2_price
                close_qty = original_position_size * (tp2_percent / 100.0)
                strategy.close("Short", qty=close_qty, comment="TP2", alert_message="WR-SMC TP2 HIT | Closed " + str.tostring(tp2_percent) + "%")
                tp2_hit := true
            if tp2_hit and low <= tp3_price
                strategy.close("Short", comment="TP3", alert_message="WR-SMC TP3 HIT | Full exit")
        else
            if low <= tp1_price
                strategy.close("Short", comment="TP", alert_message="WR-SMC TP HIT")

// ═══════════════════════════════════════════════════════════════════════════════
// VISUALIZE TP LEVELS
// ═══════════════════════════════════════════════════════════════════════════════
var line tp1_line = na
var line tp2_line = na
var line tp3_line = na
var line sl_line = na

if barstate.islast
    if not na(tp1_line)
        line.delete(tp1_line)
        line.delete(tp2_line)
        line.delete(tp3_line)
        line.delete(sl_line)
    tp1_line := na
    tp2_line := na
    tp3_line := na
    sl_line := na
    
    if strategy.position_size != 0
        tp1_line := line.new(bar_index - 10, tp1_price, bar_index + 10, tp1_price, color=color.new(color.green, 30), width=2, style=line.style_dashed, extend=extend.right)
        if use_multiple_tp
            tp2_line := line.new(bar_index - 10, tp2_price, bar_index + 10, tp2_price, color=color.new(color.green, 50), width=1, style=line.style_dotted, extend=extend.right)
            tp3_line := line.new(bar_index - 10, tp3_price, bar_index + 10, tp3_price, color=color.new(color.green, 70), width=1, style=line.style_dotted, extend=extend.right)
        sl_line := line.new(bar_index - 10, stop_loss, bar_index + 10, stop_loss, color=color.new(color.red, 30), width=2, style=line.style_solid, extend=extend.right)

// ═══════════════════════════════════════════════════════════════════════════════
// VISUALIZATION - S/R LEVELS
// ═══════════════════════════════════════════════════════════════════════════════
f_draw_support_levels() =>
    if array.size(support_data) > 0
        for i = 0 to array.size(support_data) - 1
            level_obj = array.get(support_data, i)
            level_price = level_obj.price
            touches = level_obj.touches
            lwidth = touches >= 4 ? 3 : touches >= 2 ? 2 : 1
            lstyle = touches >= 3 ? line.style_solid : line.style_dashed
            age = bar_index - level_obj.bar_created
            age_factor = math.max(0.3, 1.0 - (age / level_expiration) * 0.5)
            line_alpha = math.round((1.0 - age_factor) * 50)
            f_delete_level_drawings(level_obj)
            level_obj.level_line := line.new(bar_index - lookback_period, level_price, bar_index + 20, level_price, color=color.new(support_color, line_alpha), width=lwidth, style=lstyle, extend=extend.right)
            if show_zones
                level_obj.level_box := box.new(bar_index - lookback_period, level_price + support_zone_above, bar_index + 20, level_price - support_zone_below, bgcolor=color.new(color.green, zone_transparency), border_color=color.new(color.green, 80), extend=extend.right)
            if show_labels
                touch_text = touches > 1 ? " (" + str.tostring(touches) + "x)" : ""
                level_obj.level_label := label.new(bar_index + 25, level_price, str.tostring(level_price, format.mintick) + touch_text, style=label.style_label_left, color=color.new(support_color, 60), textcolor=color.black, size=size.tiny)
            array.set(support_data, i, level_obj)

f_draw_resistance_levels() =>
    if array.size(resistance_data) > 0
        for i = 0 to array.size(resistance_data) - 1
            level_obj = array.get(resistance_data, i)
            level_price = level_obj.price
            touches = level_obj.touches
            lwidth = touches >= 4 ? 3 : touches >= 2 ? 2 : 1
            lstyle = touches >= 3 ? line.style_solid : line.style_dashed
            age = bar_index - level_obj.bar_created
            age_factor = math.max(0.3, 1.0 - (age / level_expiration) * 0.5)
            line_alpha = math.round((1.0 - age_factor) * 50)
            f_delete_level_drawings(level_obj)
            level_obj.level_line := line.new(bar_index - lookback_period, level_price, bar_index + 20, level_price, color=color.new(resistance_color, line_alpha), width=lwidth, style=lstyle, extend=extend.right)
            if show_zones
                level_obj.level_box := box.new(bar_index - lookback_period, level_price + resist_zone_above, bar_index + 20, level_price - resist_zone_below, bgcolor=color.new(color.red, zone_transparency), border_color=color.new(color.red, 80), extend=extend.right)
            if show_labels
                touch_text = touches > 1 ? " (" + str.tostring(touches) + "x)" : ""
                level_obj.level_label := label.new(bar_index + 25, level_price, str.tostring(level_price, format.mintick) + touch_text, style=label.style_label_left, color=color.new(resistance_color, 60), textcolor=color.black, size=size.tiny)
            array.set(resistance_data, i, level_obj)

if barstate.islast or levels_changed
    f_draw_support_levels()
    f_draw_resistance_levels()
    levels_changed := false

plot(show_ema ? ema_9 : na, "9 EMA", color=color.red, linewidth=2)

plotshape(buy_signal and not is_sweep_signal, "Buy Signal", shape.triangleup, location.belowbar, buy_signal_color, size=size.small)
plotshape(sell_signal and not is_sweep_signal, "Sell Signal", shape.triangledown, location.abovebar, sell_signal_color, size=size.small)
plotshape(buy_signal and is_sweep_signal, "Sweep Buy", shape.diamond, location.belowbar, color.blue, size=size.large)
plotshape(sell_signal and is_sweep_signal, "Sweep Sell", shape.diamond, location.abovebar, color.blue, size=size.large)

// ═══════════════════════════════════════════════════════════════════════════════
// v4.1 ENHANCED SIGNAL LABELS
// ═══════════════════════════════════════════════════════════════════════════════
var label[] signal_labels = array.new_label()

if buy_signal and barstate.isconfirmed
    tier_emoji = f_get_tier_emoji(signal_confidence)
    tier_name = f_get_confidence_tier(signal_confidence)
    type_short = is_sweep_signal ? "SWEEP" : "ZONE"
    
    // v4.1: Enhanced label with tier and confluence info
    label_text = tier_emoji + " BUY " + tier_name + "\n@" + str.tostring(signal_level, format.mintick) + " | SL:" + str.tostring(suggested_sl, format.mintick) + "\nConf: " + str.tostring(signal_confidence) + "/20"
    if str.length(confluence_text) > 0
        label_text := label_text + "\n" + str.replace(confluence_text, "+", " ")
    
    new_label = label.new(bar_index, low - (zone_buffer * 2), label_text, style=label.style_label_up, color=buy_signal_color, textcolor=color.black, size=size.small)
    array.push(signal_labels, new_label)
    if array.size(signal_labels) > max_signal_labels
        old_label = array.shift(signal_labels)
        label.delete(old_label)

if sell_signal and barstate.isconfirmed
    tier_emoji = f_get_tier_emoji(signal_confidence)
    tier_name = f_get_confidence_tier(signal_confidence)
    type_short = is_sweep_signal ? "SWEEP" : "ZONE"
    
    label_text = tier_emoji + " SELL " + tier_name + "\n@" + str.tostring(signal_level, format.mintick) + " | SL:" + str.tostring(suggested_sl, format.mintick) + "\nConf: " + str.tostring(signal_confidence) + "/20"
    if str.length(confluence_text) > 0
        label_text := label_text + "\n" + str.replace(confluence_text, "+", " ")
    
    new_label = label.new(bar_index, high + (zone_buffer * 2), label_text, style=label.style_label_down, color=sell_signal_color, textcolor=color.black, size=size.small)
    array.push(signal_labels, new_label)
    if array.size(signal_labels) > max_signal_labels
        old_label = array.shift(signal_labels)
        label.delete(old_label)

// ═══════════════════════════════════════════════════════════════════════════════
// INFO TABLE (ENHANCED WITH v4.1 SMC DATA)
// ═══════════════════════════════════════════════════════════════════════════════
f_get_table_size() =>
    table_text_size == "Large" ? size.large : table_text_size == "Small" ? size.small : size.normal

var table info_table = table.new(position.top_right, 2, 14, bgcolor=color.new(color.black, 20), border_width=2, border_color=color.new(color.gray, 50))

if show_info_table and barstate.islast
    txt_size = f_get_table_size()
    
    // Header
    table.cell(info_table, 0, 0, "WR-SMC v4.1", text_color=color.white, text_size=txt_size, bgcolor=color.new(color.blue, 30), text_halign=text.align_center)
    table.cell(info_table, 1, 0, "ENHANCED", text_color=color.yellow, text_size=txt_size, bgcolor=color.new(color.blue, 30), text_halign=text.align_center)
    
    // Biases
    m5_bias_text = m5_bullish ? "BULLISH ▲" : m5_bearish ? "BEARISH ▼" : "NEUTRAL ●"
    m5_bias_color = m5_bullish ? color.new(color.lime, 0) : m5_bearish ? color.new(color.red, 0) : color.gray
    table.cell(info_table, 0, 1, "M5 Bias", text_color=color.new(color.silver, 0), text_size=txt_size, bgcolor=color.new(color.black, 30))
    table.cell(info_table, 1, 1, m5_bias_text, text_color=m5_bias_color, text_size=txt_size, bgcolor=color.new(color.black, 30), text_halign=text.align_right)
    
    h1_bias_text = h1_bullish ? "BULLISH ▲" : h1_bearish ? "BEARISH ▼" : "NEUTRAL ●"
    h1_bias_color = h1_bullish ? color.new(color.lime, 0) : h1_bearish ? color.new(color.red, 0) : color.gray
    table.cell(info_table, 0, 2, "H1 Bias", text_color=color.new(color.silver, 0), text_size=txt_size, bgcolor=color.new(color.black, 30))
    table.cell(info_table, 1, 2, h1_bias_text, text_color=h1_bias_color, text_size=txt_size, bgcolor=color.new(color.black, 30), text_halign=text.align_right)
    
    smc_trend_text = smcTrendDir == "Bullish" ? "BULLISH ▲" : smcTrendDir == "Bearish" ? "BEARISH ▼" : "NEUTRAL ●"
    smc_trend_color = smcTrendDir == "Bullish" ? color.new(color.lime, 0) : smcTrendDir == "Bearish" ? color.new(color.red, 0) : color.gray
    table.cell(info_table, 0, 3, "SMC Trend", text_color=color.new(color.silver, 0), text_size=txt_size, bgcolor=color.new(color.black, 30))
    table.cell(info_table, 1, 3, smc_trend_text, text_color=smc_trend_color, text_size=txt_size, bgcolor=color.new(color.black, 30), text_halign=text.align_right)
    
    dir_text = overall_bullish ? "LONGS ONLY" : overall_bearish ? "SHORTS ONLY" : "NO TRADE"
    dir_color = overall_bullish ? color.new(color.lime, 0) : overall_bearish ? color.new(color.red, 0) : color.orange
    dir_bg = overall_bullish ? color.new(color.green, 80) : overall_bearish ? color.new(color.maroon, 80) : color.new(color.gray, 80)
    table.cell(info_table, 0, 4, "Direction", text_color=color.white, text_size=txt_size, bgcolor=dir_bg)
    table.cell(info_table, 1, 4, dir_text, text_color=dir_color, text_size=txt_size, bgcolor=dir_bg, text_halign=text.align_right)
    
    cisd_text = use_cisd and cisd_bullish_signal ? "BULLISH 🔥" : use_cisd and cisd_bearish_signal ? "BEARISH 🔥" : "INACTIVE"
    cisd_color = cisd_bullish_signal ? color.new(color.lime, 0) : cisd_bearish_signal ? color.new(color.red, 0) : color.gray
    table.cell(info_table, 0, 5, "CISD", text_color=color.new(color.silver, 0), text_size=txt_size, bgcolor=color.new(color.black, 30))
    table.cell(info_table, 1, 5, cisd_text, text_color=cisd_color, text_size=txt_size, bgcolor=color.new(color.black, 30), text_halign=text.align_right)
    
    // Separator
    table.cell(info_table, 0, 6, "━━━━━", text_color=color.new(color.gray, 30), text_size=txt_size, bgcolor=color.new(color.black, 50))
    table.cell(info_table, 1, 6, "━━━━━", text_color=color.new(color.gray, 30), text_size=txt_size, bgcolor=color.new(color.black, 50))
    
    // Levels
    nearest_sup = 0.0
    if array.size(support_data) > 0
        min_dist = 99999.0
        for i = 0 to array.size(support_data) - 1
            s = array.get(support_data, i)
            dist = close - s.price
            if dist > 0 and dist < min_dist
                min_dist := dist
                nearest_sup := s.price
    sup_text = nearest_sup > 0 ? str.tostring(nearest_sup, format.mintick) : "N/A"
    table.cell(info_table, 0, 7, "Support ↓", text_color=color.new(color.silver, 0), text_size=txt_size, bgcolor=color.new(color.black, 30))
    table.cell(info_table, 1, 7, sup_text, text_color=color.new(color.lime, 0), text_size=txt_size, bgcolor=color.new(color.black, 30), text_halign=text.align_right)
    
    nearest_res = 0.0
    if array.size(resistance_data) > 0
        min_dist = 99999.0
        for i = 0 to array.size(resistance_data) - 1
            r = array.get(resistance_data, i)
            dist = r.price - close
            if dist > 0 and dist < min_dist
                min_dist := dist
                nearest_res := r.price
    res_text = nearest_res > 0 ? str.tostring(nearest_res, format.mintick) : "N/A"
    table.cell(info_table, 0, 8, "Resist ↑", text_color=color.new(color.silver, 0), text_size=txt_size, bgcolor=color.new(color.black, 30))
    table.cell(info_table, 1, 8, res_text, text_color=color.new(color.red, 0), text_size=txt_size, bgcolor=color.new(color.black, 30), text_halign=text.align_right)
    
    table.cell(info_table, 0, 9, "S/R Levels", text_color=color.new(color.silver, 0), text_size=txt_size, bgcolor=color.new(color.black, 30))
    table.cell(info_table, 1, 9, str.tostring(array.size(support_data)) + " / " + str.tostring(array.size(resistance_data)), text_color=color.white, text_size=txt_size, bgcolor=color.new(color.black, 30), text_halign=text.align_right)
    
    table.cell(info_table, 0, 10, "FVG Zones", text_color=color.new(color.silver, 0), text_size=txt_size, bgcolor=color.new(color.black, 30))
    table.cell(info_table, 1, 10, str.tostring(array.size(bullFVGs)) + " / " + str.tostring(array.size(bearFVGs)), text_color=color.white, text_size=txt_size, bgcolor=color.new(color.black, 30), text_halign=text.align_right)
    
    table.cell(info_table, 0, 11, "Order Blocks", text_color=color.new(color.silver, 0), text_size=txt_size, bgcolor=color.new(color.black, 30))
    table.cell(info_table, 1, 11, str.tostring(array.size(bullOBs)) + " / " + str.tostring(array.size(bearOBs)), text_color=color.white, text_size=txt_size, bgcolor=color.new(color.black, 30), text_halign=text.align_right)
    
    // v4.1 NEW: Last Signal Info
    last_sig_text = last_signal_tier != "" ? last_signal_tier + " (" + str.tostring(last_signal_confidence) + "/20)" : "N/A"
    last_sig_color = last_signal_confidence >= 15 ? color.new(color.orange, 0) : last_signal_confidence >= 12 ? color.new(color.yellow, 0) : last_signal_confidence >= 9 ? color.new(color.lime, 0) : color.white
    table.cell(info_table, 0, 12, "Last Signal", text_color=color.new(color.silver, 0), text_size=txt_size, bgcolor=color.new(color.black, 30))
    table.cell(info_table, 1, 12, last_sig_text, text_color=last_sig_color, text_size=txt_size, bgcolor=color.new(color.black, 30), text_halign=text.align_right)
    
    // v4.1 NEW: Position Size
    pos_text = last_position_size > 0 ? str.tostring(last_position_size, "#.##") + "%" : "N/A"
    table.cell(info_table, 0, 13, "Position Size", text_color=color.new(color.silver, 0), text_size=txt_size, bgcolor=color.new(color.black, 30))
    table.cell(info_table, 1, 13, pos_text, text_color=color.white, text_size=txt_size, bgcolor=color.new(color.black, 30), text_halign=text.align_right)

// ═══════════════════════════════════════════════════════════════════════════════
// END OF v4.1 ENHANCED STRATEGY - WR-SR + SMC HYBRID ✅
// ═══════════════════════════════════════════════════════════════════════════════

Overview

WR-SR + SMC Strategy ENHANCED calculates entry confidence scores based on multi-timeframe structure, Fair Value Gap taps, Order Block alignment, and recent Change of Character occurrences. Entries utilize dynamic position sizing and risk-reward ratios scaled to the overall confidence tier. All analysis, including FVGs, Order Blocks, and market structure, is plotted directly on the main price chart.

Details

Published by

alboogycOdR on GitHub

Code credit

KingdomFinancier - Wick Rejection + SMC Hybrid Strategy, as written in the script's header

Type

Strategy, Pine Script v5

Draws

On the price chart

Category

SMC / ICT / price action, Support & resistance, Trend

Markets

Gold, Forex, Indices

Timeframes

M1-M5, M15-H1

Risk Notes

  • The strategy can add several entries in the same direction

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Enable SMC Componentsbooltrueenable_smc
Show CHoCH/BOS Labelsbooltrueshow_choch_bos
Show FVG Zonesbooltrueshow_fvg
Show Order Blocksbooltrueshow_order_blocks
Show Premium/Discount Zonesboolfalseshow_premium_discount
Show HTF Structure Linesbooltrueshow_structure_lines
Max FVG Zones per Sideint3max_fvg_zones
Max Order Blocks per Sideint2max_ob_zones
SMC HTF for Structuretimeframe60smc_htf
Fractal Sensitivityint3fractal_sensitivity
FVG Tap Bonus (+2)booltrueuse_fvg_tap_bonus
Order Block Confluence (+2)booltrueuse_ob_confluence_bonus
Show all 40 settings
SettingTypeDefaultVariable
Recent CHoCH Bonus (+2)booltrueuse_recent_choch_bonus
HTF Structure Confluence (+2)booltrueuse_htf_confluence_bonus
Premium/Discount Zone Filterbooltrueuse_premium_discount_filter
P/D Filter ModestringBonus Onlypd_filter_mode
Sweep+CHoCH Combo (+3)booltrueuse_sweep_choch_combo
SMC Alignment Score (+0-4)booltrueuse_smc_alignment_score
CHoCH Lookback Barsint20choch_lookback_bars
OB Confluence Tolerancefloat3.0ob_confluence_tolerance
HTF Confluence Tolerancefloat5.0htf_confluence_tolerance
Sweep+CHoCH Max Bars Apartint15sweep_choch_max_bars
Lookback Periodint100lookback_period
Wick Threshold %float0.35wick_threshold
Level Merge Distancefloat2.0level_proximity
Max S/R Levels to Showint8max_levels
Zone Buffer (points)float1.5zone_buffer
Min Candle Rangefloat1.0min_candle_range
Level Expiration (bars)int500level_expiration
EMA Lengthint9ema_length
Use EMA Filterbooltrueuse_ema_filter
Require H1 Confluencebooltruerequire_h1_align
Allow Reversal Tradesbooltrueallow_reversal_trades
Reversal Min Confidenceint6reversal_min_confidence
Show EMA Linebooltrueshow_ema
Enable CISDbooltrueuse_cisd
Min CISD Durationint3cisd_min_duration
Max CISD Validityint50cisd_max_duration
CISD Confidence Boostint1cisd_confidence_boost
Show CISD Labelsbooltrueshow_cisd_labels
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

FilledValueGap A006

by ruckard
13 stars

This strategy enters trades in the opposite direction of filled value gaps, operating under the assumption that price action will resume the primary trend after filling a recent gap. It plots directly on the main price chart and supports MA-based trend filters

Strategy v5 SMC / ICT / price actionTrend
Updated 1 year ago · None stated GitHub repository of FilledValueGap A006

This strategy identifies reversal opportunities based on liquidity sweeps and multi-gate confluence scoring. It evaluates setups using mandatory conditions such as swing sweeps, body and ATR filters, and dual EMA higher-timeframe trend alignment, alongside opt

Strategy v6 SMC / ICT / price actionTrend
Updated yesterday · MIT GitHub repository of Reversal Engine Score [WavesUnchained] Strategy

XXX

by MeridianAlgo
9 stars

This multi-timeframe scalping strategy plots moving averages alongside Smart Money Concepts elements on the price chart. It calculates trend signals using configurable moving average types like ALMA, Hull MA, or TEMA across alternate timeframes. It also plots

Strategy v5 TrendMoving averages Repaints
Updated 4 months ago · MIT GitHub repository of XXX

FVG Strategy

by muammeryldrm42
7 stars

Calculates three-bar Fair Value Gaps (FVG) and filters them using Average True Range. When price mitigates the FVG midpoint, the strategy enters a position in the direction of the gap, provided an optional EMA trend filter is satisfied. Exits are defined by an

Strategy v5 SMC / ICT / price actionSupport & resistance
Updated 3 months ago · MIT GitHub repository of FVG Strategy

NQ 9:45-10:15 ICT Strategy

by eddiebelaval
7 stars

This ICT-based strategy trades during the 9:45 AM to 10:15 AM New York session window. It calculates a daily bias using a 20-period daily EMA and tracks previous day highs and lows to identify liquidity sweeps. The script refines order block entry levels and m

Strategy v6 SMC / ICT / price actionSessions & time Repaints
Updated 3 months ago · None stated GitHub repository of NQ 9:45-10:15 ICT Strategy
5 stars

RG Structure is a pivot-constrained break-and-retest strategy that calculates dynamic trendlines, market structure changes, and regime states on the price chart. It identifies support and resistance lines through pivot points and evaluates break-and-retest sig

Strategy v6 TrendSupport & resistance
Updated 7 weeks ago · None stated GitHub repository of RG Structure Visual Edition

More strategys

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers