← กลับหน้ารายการ

SMC Pro BTC - ICT Order Blocks & FVG [DOE]

Strategy ผู้เขียน: DOE_Trade Profit Factor: 1.148

ลิงก์ TradingView

เปิดใน TradingView

Equity Chart

Equity chart

เปิดรูปเต็มขนาด

คำอธิบาย

SMC Pro BTC - ICT Order Blocks & FVG
A multi-timeframe Smart Money Concepts engine built exclusively for Bitcoin. This indicator combines order blocks, fair value gaps, liquidity sweeps, break of structure, and premium/discount zone analysis into one backtest-verified, non-repainting strategy.
Every signal you see in history is exactly what you would have seen live. No repainting. No lookahead. No curve-fitting.
Built by a former quantitative analyst from a US-based systematic fund. The structural logic behind this indicator is the same order flow mechanics that institutional algorithms use to identify and exploit liquidity imbalances — adapted for retail traders on TradingView.

TWO STRATEGY MODES
The indicator offers two execution modes on the same structural foundation. Both include commissions (0.075% per trade) and slippage (3 ticks) in all backtested results.

AGGRESSIVE MODE — More trades, more exposure
Entries fire on any valid BOS or CHoCH confirmed by an order block and fair value gap on the confirmation timeframe. Accepts a lower win rate in exchange for capturing a larger portion of trending moves.
Metric Value
Period Jan 2021 — Feb 2026 (5 years)
Total Trades 90
Win Rate 45.56%
Net P&L +14.36%
Profit Factor 1.95
Max Drawdown 1.36%
90 trades across 5 full years — including the 2022 bear market. A profit factor of 1.95 means that for every dollar lost, the system recovered nearly two. The 45% win rate works because winning trades are structurally larger than losers. This is positive expectancy executed over a statistically meaningful sample.

SELECTIVE MODE — Fewer trades, higher precision
Adds a premium/discount zone filter. Longs only in the discount zone of the HTF dealing range. Shorts only in the premium zone. This single structural filter cuts the trade count significantly while improving signal quality.
Metric Value
Period Jan 2021 — Feb 2026 (5 years)
Total Trades 29
Win Rate 51.72%
Net P&L +1.10%
Profit Factor 1.324
Max Drawdown 1.23%

The Selective mode sacrifices P&L for risk control — the maximum drawdown over 5 years was just 1.23%. The lower trade count (29) reflects the strict filtering: every signal requires structural confluence plus optimal price positioning. This mode is designed for traders who prioritize capital preservation over returns.

Both modes are provided so you can evaluate the tradeoff between frequency and precision. There is no objectively "better" mode — only the one that matches your risk tolerance.
Note on sample size: The Aggressive mode produces 90 trades over the 5-year test period, approaching the 100-trade benchmark for statistical significance. The Selective mode produces 29 trades due to the strict confluence requirements — each trade requires alignment across 6 independent conditions (BOS, OB, FVG, liquidity sweep, premium/discount zone). We recommend supplementing the backtest with forward-testing on live data for additional confidence. The Strategy Tester is fully available for you to verify all results with your own settings.

ENTRY LOGIC — STEP BY STEP
Every signal requires alignment across structure, zone, imbalance, and liquidity. No single condition is sufficient.

LONG ENTRY SEQUENCE
Step 1 — HTF Directional Bias
The Direction Timeframe (default: 4H) detects a bullish break of structure or change of character. This establishes the higher-timeframe directional bias. Without bullish structure on the HTF, no long signal fires.

Step 2 — MTF Confirmation
The Confirmation Timeframe (default: 1H) must confirm with its own bullish BOS or CHoCH, aligning both timeframes in the same direction.

Step 3 — Order Block Identification
The script finds the last bearish candle before the impulsive bullish move — the order block where smart money accumulated positions.

Step 4 — Fair Value Gap Validation
A bullish FVG must overlap the identified order block zone. An OB alone is a level. An OB combined with an FVG is confluence.

Step 5 — Liquidity Sweep Confirmation
A recent liquidity sweep must have occurred — price dipped below a prior swing low, triggering stop-losses, before reversing.

Step 6 — Premium/Discount Zone Filter (Selective Mode Only)
Entry must occur in the discount zone of the HTF dealing range.

Step 7 — Execution
All conditions met. Signal fires. Stop-loss below the order block. Take-profit at the configured R:R distance.

SHORT ENTRY SEQUENCE
Mirrors the long with inverted conditions:
HTF bearish BOS/CHoCH
MTF bearish BOS/CHoCH confirms
Bearish order block identified
Bearish FVG overlaps the OB zone
Liquidity sweep above a prior swing high
Price in premium zone (Selective only)
SL above OB high + buffer; TP at R:R below entry
Every step is objective. No discretionary component.

FEATURES
Non-repainting, non-lookahead signals — barstate.isconfirmed enforced on all calculations
Multi-timeframe structure analysis — HTF for direction, MTF for confirmation, entry TF for execution
Order block detection with configurable lookback and automatic invalidation
Fair value gap multi-zone display — configurable by count and max distance from price
Liquidity sweep recognition with adjustable memory window
BOS and CHoCH detection on multiple timeframes
Premium/discount zone mapping with configurable threshold
Automatic SL/TP with visual trade boxes
Two strategy modes — Aggressive and Selective
Fully configurable parameters with sensible BTC 4H defaults
Built-in strategy engine — backtest directly in Strategy Tester

DEFAULT STRATEGY PROPERTIES
These are the exact settings used for the published backtest. You can verify all results by loading the indicator with default settings and opening the Strategy Tester:
Symbol: BTCUSDT (Binance)
Timeframe: 4H
Period: January 2021 — February 2026 (5+ years)
Initial Capital: $10,000
Order Size: 10% of equity per trade
Commission: 0.075% per trade (Binance taker fee)
Slippage: 3 ticks per order
Pyramiding: 0 (one position at a time)
Non-repainting: barstate.isconfirmed enforced
No lookahead bias: lookahead = barmerge.lookahead_off on all request.security() calls
No future leakage: entries execute on the bar after all conditions are confirmed
The 10% equity sizing means each trade risks a sustainable portion of the account. This is consistent with professional risk management standards where no single trade should expose more than 5-10% of capital.

SETTINGS DOCUMENTATION
Strategy Mode — Aggressive / Selective
Aggressive: BOS/CHoCH + Order Block + FVG + Liquidity Sweep. Selective adds premium/discount zone filter. New to SMC? Start with Selective.
Direction TF (HTF) — Default: 240 (4H)
Higher timeframe for directional bias. Increase to Daily for fewer, higher-conviction signals.
Confirmation TF (MTF) — Default: 60 (1H)
Mid timeframe that confirms HTF bias. Default 240/60 provides a 4:1 ratio.
Swing Length — Default: 10 | Range: 3-50
Bars used to identify swing highs/lows. Lower = more sensitive, higher = major shifts only.
OB Lookback Bars — Default: 15 | Range: 3-30
How far back to search for valid order blocks after a structural break.
Sweep Memory — Default: 20 bars | Range: 5-50
Lookback window for detecting liquidity sweeps before entries.
Risk:Reward Ratio — Default: 2.0 | Range: 1.0-5.0
TP placement relative to SL distance. Re-run backtest after changing.
SL Buffer % — Default: 0.3 | Range: 0.0-2.0
Buffer beyond OB boundary to prevent wick stop-outs.
P/D Zone Threshold — Default: 0.80 | Range: 0.50-0.85 | Selective Only
How deep into premium/discount zone for entry qualification.
Max FVGs per Side — Default: 5 | Range: 1-10
Active FVGs displayed per direction.
FVG Max Distance % — Default: 8.0 | Range: 1.0-25.0
Hides FVGs beyond this % from current price.
Show Trade Boxes — On / Off
Visual boxes showing entry, SL, and TP for each signal.

CONCEPTS EXPLAINED
Order Blocks (OB) — The last opposing candle before a significant impulsive move. Where institutional participants positioned themselves. The foundation of SMC entry models.
Fair Value Gap (FVG) — A three-candle price imbalance where the market moved too fast for orders to fill. Markets tend to return to these inefficiencies. When an FVG overlaps an OB, that is high-probability confluence.
Break of Structure (BOS) — Price moves beyond a prior swing high/low in the trend direction. Signals continuation.
Change of Character (CHoCH) — A structural break against the prevailing trend. The first objective signal of a potential reversal.
Liquidity Sweep — Price pushes beyond a key level to trigger stop-losses, then reverses. Institutional participants hunting clustered orders for liquidity.
Premium and Discount Zones — The HTF range divided by the 50% equilibrium. Premium = expensive (favor shorts). Discount = cheap (favor longs).

HOW TO USE
Add to any BTCUSDT chart (optimized for 4H Binance)
Select Aggressive or Selective mode in Settings
Green arrows = long entries, red arrows = short entries, with SL/TP lines
Enable Show Trade Boxes for visual risk/reward on every signal
Open Strategy Tester to verify all backtest results with your own settings
Adjust one setting at a time and re-run the backtest after each change
Combine with your own analysis — this is a structural tool, not a prediction engine
Manage risk — no indicator guarantees profits

CREDITS
This script builds upon concepts and structural approaches from the following open-source projects:
LuxAlgo — SMC structural detection framework
ICT Master Suite — ICT concepts implementation reference
PineScript-SMC-Strategy — SMC strategy architecture reference
Significant modifications and original work include: dual-mode strategy engine (Aggressive/Selective), multi-timeframe confluence model requiring 5-6 simultaneous conditions, FVG multi-zone display with distance filtering, integrated backtest engine with realistic position sizing, and complete strategy automation with configurable risk management.

DISCLAIMER
This indicator is published for educational and informational purposes only. It is not financial advice, investment advice, or a recommendation to buy or sell any asset. Trading Bitcoin involves substantial risk of loss. Never trade capital you cannot afford to lose. Past performance does not guarantee future results. You are solely responsible for your own trading decisions. Use at your own risk.

รูป Preview

Preview

Pine Script Source

// =====================================================================
// SMC Pro BTC - ICT Order Blocks & FVG [DOE Framework]
// =====================================================================
//
// Multi-timeframe Smart Money Concepts strategy for BTC.
// Combines institutional order flow analysis with structural
// confluence to identify high-probability entries.
//
// ─── TWO MODES ─────────────────────────────────────────────────────
//
// AGGRESSIVE MODE (default)
//   Higher frequency, higher P&L. Enters on full SMC confluence
//   without price location filtering.
//   Backtest (4H, Jan 2021 - Feb 2026, 10% equity):
//     90 trades | 46% WR | +14.36% P&L | PF 1.95 | DD 1.36%
//
// SELECTIVE MODE
//   Higher win rate, lower drawdown. Adds ICT Premium/Discount
//   zone filter — only buys in discount, sells in premium.
//   Backtest (4H, Jan 2021 - Feb 2026, 10% equity):
//     29 trades | 52% WR | +1.10% P&L | PF 1.32 | DD 1.23%
//
// ─── ENTRY LOGIC ───────────────────────────────────────────────────
//
// LONG:  4H bullish structure + 1H bullish confirmation
//        + recent liquidity sweep + price in Order Block or FVG
//        + bullish candle close [+ discount zone in Selective mode]
//
// SHORT: 4H bearish structure + 1H bearish confirmation
//        + recent liquidity sweep + price in Order Block or FVG
//        + bearish candle close [+ premium zone in Selective mode]
//
// ─── HOW TO USE ────────────────────────────────────────────────────
//
// 1. Apply to BTCUSDT (or any BTC pair) on 4H or 1H chart
// 2. Choose your mode in Settings → Strategy Mode
// 3. Open Strategy Tester tab to view backtest results
// 4. Set alerts for live trading notifications
//
// ─── CONCEPTS ──────────────────────────────────────────────────────
//
// • Order Blocks (OB): Last opposing candle before a Break of
//   Structure. Marks institutional supply/demand zones.
// • Fair Value Gaps (FVG): 3-candle imbalance gaps where price
//   moved too fast. Revisited 70-80% of the time.
// • Break of Structure (BOS): Price closing beyond a swing
//   high/low, confirming directional bias.
// • Liquidity Sweeps: Wick beyond a swing point that closes back
//   inside — captures stop-loss liquidity before reversing.
// • Premium/Discount: Price location relative to the swing range
//   midpoint. ICT teaches: buy in discount, sell in premium.
//
// Based on: LuxAlgo SMC, ICT Master Suite, PineScript-SMC-Strategy
// =====================================================================

//@version=5
strategy("SMC Pro BTC - ICT Order Blocks & FVG [DOE]",
     shorttitle        = "SMC Pro BTC",
     overlay           = true,
     initial_capital    = 10000,
     default_qty_type   = strategy.percent_of_equity,
     default_qty_value  = 10,
     commission_type    = strategy.commission.percent,
     commission_value   = 0.075,
     slippage           = 3,
     pyramiding         = 0,
     max_labels_count   = 500,
     max_lines_count    = 500,
     max_boxes_count    = 500,
     calc_on_every_tick = false)

// =====================================================================
// INPUTS
// =====================================================================

// --- Strategy Mode ---
GRP0 = "Strategy Mode"
i_mode = input.string("Aggressive", "Strategy Mode", options = ["Aggressive", "Selective"], group = GRP0, tooltip = "Aggressive: more trades, higher P&L, higher DD. Selective: fewer trades, higher WR, lower DD (adds Premium/Discount filter).")

// --- Multi-Timeframe ---
GRP1 = "Multi-Timeframe"
i_htfTF       = input.timeframe("240", "Direction TF (HTF)",    group = GRP1, tooltip = "Higher timeframe for trend direction. Default: 4H")
i_mtfTF       = input.timeframe("60",  "Confirmation TF (MTF)", group = GRP1, tooltip = "Mid timeframe for structure confirmation. Default: 1H")

// --- Structure Detection ---
GRP2 = "Structure Detection"
i_swingLen    = input.int(10,   "Swing Length",         minval = 3,  maxval = 50, group = GRP2, tooltip = "Bars for pivot high/low detection. Higher = fewer, stronger swings.")
i_obLookback  = input.int(15,   "OB Lookback Bars",    minval = 3,  maxval = 30, group = GRP2, tooltip = "How many bars back to search for the OB candle after a BOS.")
i_sweepWindow = input.int(20,   "Sweep Memory (bars)",  minval = 5,  maxval = 50, group = GRP2, tooltip = "A liquidity sweep must have occurred within this many bars.")

// --- Risk Management ---
GRP3 = "Risk Management"
i_rrRatio     = input.float(2.0,  "Risk:Reward Ratio",   minval = 1.0, maxval = 5.0, step = 0.5, group = GRP3, tooltip = "TP distance = SL distance × this ratio.")
i_slBuffer    = input.float(0.3,  "SL Buffer (%)",       minval = 0.0, maxval = 2.0, step = 0.1, group = GRP3, tooltip = "Extra buffer beyond OB/FVG edge for stop-loss.")
i_pdThreshold = input.float(0.80, "P/D Zone Threshold",  minval = 0.5, maxval = 0.85, step = 0.05, group = GRP3, tooltip = "Selective mode only. 0.50 = strict equilibrium. 0.80 = longs allowed in lower 80% of swing range.")

// --- Visual ---
GRP4 = "Visual"
i_showTradeBox = input.bool(true,    "Show Trade Boxes",    group = GRP4, tooltip = "Show entry/SL/TP zone boxes for active trades.")
i_showZones    = input.bool(true,    "Show FVG Zones",      group = GRP4, tooltip = "Show active FVG zones on chart.")
i_showLabels   = input.bool(true,    "Show Entry Labels",   group = GRP4, tooltip = "Minimal entry marker at signal bar.")
i_showDash     = input.bool(true,    "Show Info Dashboard",  group = GRP4, tooltip = "Show bias/mode info panel.")
i_boxLen       = input.int(30,       "Box Length (bars)",    minval = 10, maxval = 80, group = GRP4)
i_maxFVGs      = input.int(5,        "Max FVGs per Side",   minval = 1, maxval = 10, group = GRP4, tooltip = "Maximum unfilled FVGs shown per direction (bull/bear).")
i_maxFVGDist   = input.float(8.0,    "FVG Max Distance (%)", minval = 1.0, maxval = 25.0, step = 1.0, group = GRP4, tooltip = "Hide FVGs further than this % from current price.")
i_longCol      = input.color(#089981, "Long",               group = GRP4, inline = "colors")
i_shortCol     = input.color(#F23645, "Short",              group = GRP4, inline = "colors")
i_slCol        = input.color(#787B86, "SL",                 group = GRP4, inline = "colors")

// =====================================================================
// MULTI-TIMEFRAME TREND DETECTION
// =====================================================================

f_structureTrend(_len) =>
    var float _lastSH = na
    var float _lastSL = na
    var int   _dir    = 0
    _sh = ta.pivothigh(high, _len, _len)
    _sl = ta.pivotlow(low, _len, _len)
    if not na(_sh)
        _lastSH := _sh
    if not na(_sl)
        _lastSL := _sl
    if not na(_lastSH) and close > _lastSH
        _dir := 1
    if not na(_lastSL) and close < _lastSL
        _dir := -1
    _dir

htfTrend = request.security(syminfo.tickerid, i_htfTF, f_structureTrend(i_swingLen), lookahead = barmerge.lookahead_off)
htfBull  = htfTrend == 1
htfBear  = htfTrend == -1

mtfTrend = request.security(syminfo.tickerid, i_mtfTF, f_structureTrend(i_swingLen), lookahead = barmerge.lookahead_off)
mtfBull  = mtfTrend == 1
mtfBear  = mtfTrend == -1

// =====================================================================
// CHART TIMEFRAME — SWING DETECTION
// =====================================================================

swingHigh = ta.pivothigh(high, i_swingLen, i_swingLen)
swingLow  = ta.pivotlow(low, i_swingLen, i_swingLen)

var float lastSH = na
var float lastSL = na

if not na(swingHigh)
    lastSH := swingHigh
if not na(swingLow)
    lastSL := swingLow

// =====================================================================
// PREMIUM / DISCOUNT ZONE (Selective mode)
// =====================================================================

isSelective  = i_mode == "Selective"
swingRange   = not na(lastSH) and not na(lastSL) ? lastSH - lastSL : na
discountCeil = not na(swingRange) ? lastSL + swingRange * i_pdThreshold : na
premiumFloor = not na(swingRange) ? lastSH - swingRange * i_pdThreshold : na

// In Aggressive mode, P/D always passes. In Selective mode, must be in correct zone.
inDiscount = not isSelective or (not na(discountCeil) and close < discountCeil)
inPremium  = not isSelective or (not na(premiumFloor) and close > premiumFloor)

// =====================================================================
// BREAK OF STRUCTURE
// =====================================================================

bullBOS = not na(lastSH) and ta.crossover(close, lastSH)
bearBOS = not na(lastSL) and ta.crossunder(close, lastSL)

// =====================================================================
// LIQUIDITY SWEEP DETECTION
// =====================================================================

bullSweep = not na(lastSL) and low < lastSL and close > lastSL
bearSweep = not na(lastSH) and high > lastSH and close < lastSH

var int barsSinceBullSweep = 999
var int barsSinceBearSweep = 999
barsSinceBullSweep := bullSweep ? 0 : barsSinceBullSweep + 1
barsSinceBearSweep := bearSweep ? 0 : barsSinceBearSweep + 1
recentBullSweep = barsSinceBullSweep <= i_sweepWindow
recentBearSweep = barsSinceBearSweep <= i_sweepWindow

// =====================================================================
// ORDER BLOCK DETECTION
// =====================================================================

var float bullOB_top   = na
var float bullOB_bot   = na
var bool  bullOB_valid = false

var float bearOB_top   = na
var float bearOB_bot   = na
var bool  bearOB_valid = false

if bullBOS
    for i = 1 to i_obLookback
        if close[i] < open[i]
            bullOB_top   := high[i]
            bullOB_bot   := low[i]
            bullOB_valid := true
            break

if bearBOS
    for i = 1 to i_obLookback
        if close[i] > open[i]
            bearOB_top   := high[i]
            bearOB_bot   := low[i]
            bearOB_valid := true
            break

if bullOB_valid and close < bullOB_bot
    bullOB_valid := false
if bearOB_valid and close > bearOB_top
    bearOB_valid := false

// =====================================================================
// FAIR VALUE GAP DETECTION
// =====================================================================

bullFVG_cond = low > high[2] and close[1] > open[1]
bearFVG_cond = high < low[2] and close[1] < open[1]

var float bullFVG_top   = na
var float bullFVG_bot   = na
var bool  bullFVG_valid = false

var float bearFVG_top   = na
var float bearFVG_bot   = na
var bool  bearFVG_valid = false

if bullFVG_cond
    bullFVG_top   := low
    bullFVG_bot   := high[2]
    bullFVG_valid := true

if bearFVG_cond
    bearFVG_top   := low[2]
    bearFVG_bot   := high
    bearFVG_valid := true

if bullFVG_valid and close < bullFVG_bot
    bullFVG_valid := false
if bearFVG_valid and close > bearFVG_top
    bearFVG_valid := false

// =====================================================================
// PRICE IN ZONE DETECTION
// =====================================================================

inBullOB  = bullOB_valid  and low <= bullOB_top  and close >= bullOB_bot
inBearOB  = bearOB_valid  and high >= bearOB_bot and close <= bearOB_top
inBullFVG = bullFVG_valid and low <= bullFVG_top and close >= bullFVG_bot
inBearFVG = bearFVG_valid and high >= bearFVG_bot and close <= bearFVG_top

inBullZone = inBullOB or inBullFVG
inBearZone = inBearOB or inBearFVG

// =====================================================================
// ENTRY CONDITIONS — MULTI-TF CONFLUENCE
// =====================================================================

bullCandle = close > open
bearCandle = close < open

longSignal  = htfBull and mtfBull and recentBullSweep and inBullZone and bullCandle and inDiscount and strategy.position_size == 0
shortSignal = htfBear and mtfBear and recentBearSweep and inBearZone and bearCandle and inPremium  and strategy.position_size == 0

// =====================================================================
// RISK MANAGEMENT — SL / TP CALCULATION
// =====================================================================

var float activeSL = na
var float activeTP = na

if longSignal
    _slBase  = inBullOB ? bullOB_bot : bullFVG_bot
    _sl      = _slBase * (1 - i_slBuffer / 100)
    _dist    = close - _sl
    _tp      = close + _dist * i_rrRatio
    activeSL := _sl
    activeTP := _tp
    strategy.entry("Long", strategy.long)
    strategy.exit("Long Exit", "Long", stop = _sl, limit = _tp)

if shortSignal
    _slBase  = inBearOB ? bearOB_top : bearFVG_top
    _sl      = _slBase * (1 + i_slBuffer / 100)
    _dist    = _sl - close
    _tp      = close - _dist * i_rrRatio
    activeSL := _sl
    activeTP := _tp
    strategy.entry("Short", strategy.short)
    strategy.exit("Short Exit", "Short", stop = _sl, limit = _tp)

// =====================================================================
// VISUALS — PROFESSIONAL TRADE SETUP & ZONES
// =====================================================================

// --- Color Palette ---
// Trade setup: strong, visible lines
entryCol  = color.new(#FFFFFF, 10)          // white, very visible
tpCol     = color.new(i_longCol, 10)        // strong green
slRedCol  = color.new(#F23645, 20)          // strong red for SL

// --- Track entry for box drawing ---
var float entryPrice = na

if longSignal
    entryPrice := close
if shortSignal
    entryPrice := close

// --- Trade Setup: Entry / SL / TP lines (THE MAIN EVENT) ---
if longSignal and i_showTradeBox
    // Background boxes (very subtle, just context)
    box.new(bar_index, activeTP, bar_index + i_boxLen, entryPrice,
         border_color = color.new(i_longCol, 80), bgcolor = color.new(i_longCol, 95),
         border_width = 1, border_style = line.style_solid)
    box.new(bar_index, entryPrice, bar_index + i_boxLen, activeSL,
         border_color = color.new(#F23645, 80), bgcolor = color.new(#F23645, 96),
         border_width = 1, border_style = line.style_solid)
    // Entry line — white, thick
    line.new(bar_index, entryPrice, bar_index + i_boxLen, entryPrice,
         color = entryCol, style = line.style_solid, width = 2)
    // TP line — green, solid
    line.new(bar_index, activeTP, bar_index + i_boxLen, activeTP,
         color = tpCol, style = line.style_solid, width = 2)
    // SL line — red, solid
    line.new(bar_index, activeSL, bar_index + i_boxLen, activeSL,
         color = slRedCol, style = line.style_solid, width = 2)
    // Labels with prices
    label.new(bar_index + i_boxLen, entryPrice,
         " Entry " + str.tostring(entryPrice, format.mintick),
         style = label.style_label_left, color = color.new(#000000, 100),
         textcolor = entryCol, size = size.small)
    label.new(bar_index + i_boxLen, activeTP,
         " TP " + str.tostring(activeTP, format.mintick),
         style = label.style_label_left, color = color.new(#000000, 100),
         textcolor = tpCol, size = size.small)
    label.new(bar_index + i_boxLen, activeSL,
         " SL " + str.tostring(activeSL, format.mintick),
         style = label.style_label_left, color = color.new(#000000, 100),
         textcolor = slRedCol, size = size.small)

if shortSignal and i_showTradeBox
    // Background boxes (very subtle)
    box.new(bar_index, entryPrice, bar_index + i_boxLen, activeTP,
         border_color = color.new(i_shortCol, 80), bgcolor = color.new(i_shortCol, 95),
         border_width = 1, border_style = line.style_solid)
    box.new(bar_index, activeSL, bar_index + i_boxLen, entryPrice,
         border_color = color.new(#F23645, 80), bgcolor = color.new(#F23645, 96),
         border_width = 1, border_style = line.style_solid)
    // Entry line — white, thick
    line.new(bar_index, entryPrice, bar_index + i_boxLen, entryPrice,
         color = entryCol, style = line.style_solid, width = 2)
    // TP line — green, solid
    line.new(bar_index, activeTP, bar_index + i_boxLen, activeTP,
         color = tpCol, style = line.style_solid, width = 2)
    // SL line — red, solid
    line.new(bar_index, activeSL, bar_index + i_boxLen, activeSL,
         color = slRedCol, style = line.style_solid, width = 2)
    // Labels with prices
    label.new(bar_index + i_boxLen, entryPrice,
         " Entry " + str.tostring(entryPrice, format.mintick),
         style = label.style_label_left, color = color.new(#000000, 100),
         textcolor = entryCol, size = size.small)
    label.new(bar_index + i_boxLen, activeTP,
         " TP " + str.tostring(activeTP, format.mintick),
         style = label.style_label_left, color = color.new(#000000, 100),
         textcolor = tpCol, size = size.small)
    label.new(bar_index + i_boxLen, activeSL,
         " SL " + str.tostring(activeSL, format.mintick),
         style = label.style_label_left, color = color.new(#000000, 100),
         textcolor = slRedCol, size = size.small)

// --- Entry Labels (minimal triangle marker) ---
if longSignal and i_showLabels
    label.new(bar_index, low, "",
         style = label.style_triangleup, color = i_longCol,
         textcolor = color.white, size = size.tiny)

if shortSignal and i_showLabels
    label.new(bar_index, high, "",
         style = label.style_triangledown, color = i_shortCol,
         textcolor = color.white, size = size.tiny)

// --- FVG Zones (multi-zone: up to N unfilled per direction) ---
var vBullTops  = array.new<float>()
var vBullBots  = array.new<float>()
var vBullBoxes = array.new<box>()
var vBearTops  = array.new<float>()
var vBearBots  = array.new<float>()
var vBearBoxes = array.new<box>()

if i_showZones
    // Register new bullish FVG
    if bullFVG_cond
        array.push(vBullTops, low)
        array.push(vBullBots, high[2])
        array.push(vBullBoxes, box.new(bar_index - 2, low, bar_index + 5, high[2],
             border_color = color.new(i_longCol, 30), bgcolor = color.new(i_longCol, 85),
             border_width = 1, border_style = line.style_solid,
             text = "FVG", text_color = color.new(i_longCol, 30), text_size = size.tiny,
             text_halign = text.align_left, text_valign = text.align_top))

    // Register new bearish FVG
    if bearFVG_cond
        array.push(vBearTops, low[2])
        array.push(vBearBots, high)
        array.push(vBearBoxes, box.new(bar_index - 2, low[2], bar_index + 5, high,
             border_color = color.new(i_shortCol, 30), bgcolor = color.new(i_shortCol, 85),
             border_width = 1, border_style = line.style_solid,
             text = "FVG", text_color = color.new(i_shortCol, 30), text_size = size.tiny,
             text_halign = text.align_left, text_valign = text.align_top))

    // Cleanup bull FVGs: filled → trim box, too far → delete box
    if array.size(vBullTops) > 0
        for i = array.size(vBullTops) - 1 to 0
            _bt = array.get(vBullTops, i)
            _bb = array.get(vBullBots, i)
            _bd = math.abs(close - (_bt + _bb) / 2.0) / close * 100
            if close < _bb
                box.set_right(array.get(vBullBoxes, i), bar_index)
                array.remove(vBullTops, i)
                array.remove(vBullBots, i)
                array.remove(vBullBoxes, i)
            else if _bd > i_maxFVGDist
                box.delete(array.get(vBullBoxes, i))
                array.remove(vBullTops, i)
                array.remove(vBullBots, i)
                array.remove(vBullBoxes, i)
            else
                box.set_right(array.get(vBullBoxes, i), bar_index + 5)

    // Cleanup bear FVGs: filled → trim box, too far → delete box
    if array.size(vBearTops) > 0
        for i = array.size(vBearTops) - 1 to 0
            _st = array.get(vBearTops, i)
            _sb = array.get(vBearBots, i)
            _sd = math.abs(close - (_st + _sb) / 2.0) / close * 100
            if close > _st
                box.set_right(array.get(vBearBoxes, i), bar_index)
                array.remove(vBearTops, i)
                array.remove(vBearBots, i)
                array.remove(vBearBoxes, i)
            else if _sd > i_maxFVGDist
                box.delete(array.get(vBearBoxes, i))
                array.remove(vBearTops, i)
                array.remove(vBearBots, i)
                array.remove(vBearBoxes, i)
            else
                box.set_right(array.get(vBearBoxes, i), bar_index + 5)

    // Enforce max count (remove oldest first)
    while array.size(vBullTops) > i_maxFVGs
        box.delete(array.shift(vBullBoxes))
        array.shift(vBullTops)
        array.shift(vBullBots)
    while array.size(vBearTops) > i_maxFVGs
        box.delete(array.shift(vBearBoxes))
        array.shift(vBearTops)
        array.shift(vBearBots)

// --- Info Dashboard (top-right table) ---
var table dash = na
if i_showDash and barstate.islast
    dash := table.new(position.top_right, 2, 4,
         bgcolor = color.new(#131722, 10),
         border_width = 1,
         border_color = color.new(#363A45, 50),
         frame_width  = 1,
         frame_color  = color.new(#363A45, 50))

    modeCol = isSelective ? color.new(#2962FF, 20) : color.new(#FF6D00, 20)
    table.cell(dash, 0, 0, "Mode",   text_color = color.new(color.white, 40), text_size = size.small, bgcolor = color.new(#131722, 10))
    table.cell(dash, 1, 0, i_mode,   text_color = color.white, text_size = size.small, bgcolor = modeCol)

    htfCol = htfBull ? i_longCol : htfBear ? i_shortCol : color.gray
    htfTxt = htfBull ? "Bullish" : htfBear ? "Bearish" : "Neutral"
    table.cell(dash, 0, 1, "4H",     text_color = color.new(color.white, 40), text_size = size.small, bgcolor = color.new(#131722, 10))
    table.cell(dash, 1, 1, htfTxt,   text_color = color.white, text_size = size.small, bgcolor = color.new(htfCol, 30))

    mtfCol = mtfBull ? i_longCol : mtfBear ? i_shortCol : color.gray
    mtfTxt = mtfBull ? "Bullish" : mtfBear ? "Bearish" : "Neutral"
    table.cell(dash, 0, 2, "1H",     text_color = color.new(color.white, 40), text_size = size.small, bgcolor = color.new(#131722, 10))
    table.cell(dash, 1, 2, mtfTxt,   text_color = color.white, text_size = size.small, bgcolor = color.new(mtfCol, 30))

    posText = strategy.position_size > 0 ? "LONG" : strategy.position_size < 0 ? "SHORT" : "FLAT"
    posCol  = strategy.position_size > 0 ? i_longCol : strategy.position_size < 0 ? i_shortCol : color.gray
    table.cell(dash, 0, 3, "Pos",    text_color = color.new(color.white, 40), text_size = size.small, bgcolor = color.new(#131722, 10))
    table.cell(dash, 1, 3, posText,  text_color = color.white, text_size = size.small, bgcolor = color.new(posCol, 30))

// =====================================================================
// ALERTS
// =====================================================================

alertcondition(longSignal,  title = "SMC Long Signal",  message = "SMC LONG on {{ticker}} at {{close}}")
alertcondition(shortSignal, title = "SMC Short Signal", message = "SMC SHORT on {{ticker}} at {{close}}")

if longSignal
    alert("SMC LONG " + syminfo.ticker +
         " @ " + str.tostring(close, format.mintick) +
         " | SL: " + str.tostring(activeSL, format.mintick) +
         " | TP: " + str.tostring(activeTP, format.mintick) +
         " | Mode: " + i_mode,
         alert.freq_once_per_bar)

if shortSignal
    alert("SMC SHORT " + syminfo.ticker +
         " @ " + str.tostring(close, format.mintick) +
         " | SL: " + str.tostring(activeSL, format.mintick) +
         " | TP: " + str.tostring(activeTP, format.mintick) +
         " | Mode: " + i_mode,
         alert.freq_once_per_bar)

// =====================================================================
// END OF STRATEGY
// =====================================================================