Indicator · Pine Script v5 · On the chart

ICT Silver Bullet Flux Charts v2 - Claude

by alboogycOdR· code credited to fluxchart - Enhanced by Claude

This indicator implements an ICT Silver Bullet trading framework directly on the price chart.

View on GitHub

Repaints

GitHub stars6on the repository
Pine versionv5runs as is
Lines of code1,021
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 indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

1,021 lines of Pine Script v5 from tradingview/lux-silverbullet/silverbull-lux02-claude.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

silverbull-lux02-claude.pine
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © fluxchart - Enhanced by Claude

//@version=5
//https://claude.ai/chat/b83312a3-30c4-4410-a758-e93a6a11c1d2
const bool DEBUG = false
const int showLastXLiqs = 10
const int maxDistanceToLastBar = 50000 // Affects Running Time
const int atrLen = 5
const bool maxTPLastHour = false
const int extendFVG = 15

var initRun = true

indicator("ICT Silver Bullet | Flux Charts v2 -claude", shorttitle = "Silver Bullet Claude", overlay = true, max_boxes_count = 500, max_labels_count = 500, max_lines_count = 500)

// === SESSIONS CONFIGURATION ===
nySession1 = "1000-1100"  // New York Session 1
nySession2 = "1400-1500"  // New York Session 2
londonSession = "0300-0400"  // London Session
asiaSession = "1900-2000"  // Asia Session - ADDED
killZone1 = "0400-0600"  // London/New York overlap - ADDED
killZone2 = "1300-1500"  // US Open - ADDED

// === STRATEGY CONFIGURATION ===
executionType = input.string("FVG", "Execution Type", options = ["FVG", "MSS", "Order Block", "Breaker Block"], group = "General Configuration",     tooltip = "FVG -> Fair Value Gap detection.\nMSS -> Market Structure Shift.\nOrder Block -> ICT Order Block concept.\nBreaker Block -> ICT Breaker Block concept.")
htfPeriod = input.string("240", "Higher Timeframe", options = ["60", "240", "D", "W"], group = "General Configuration",    tooltip = "Higher timeframe for market structure analysis.")
mssOffset = input.int(10, "MSS Swing Length", group = "General Configuration")
breakoutMethod = input.string("Wick", "Breakout Method", options = ["Close", "Wick"], group = "General Configuration")
fvgBars = input.string("Same Type", "FVG Detection", options = ["Same Type", "All"],     tooltip = "Same Type -> All 3 bars that formed the FVG should be the same type. (Bullish / Bearish) \n\nAll -> Bar types may vary between bullish / bearish.",     group = "General Configuration")
fvgSensEnabled = input.bool(true, "", "", "sens", "General Configuration")
fvgSensitivityText = input.string("Extreme", "FVG Detection Sensitivity", options = ["Extreme", "High", "Normal", "Low"], inline = "sens", group = "General Configuration")
fvgEntry = DEBUG ? input.string("Along", "FVG Entry", options = ["All", "Along", "Inverse"], group = "General Configuration") : "Along"
allowGaps = true
fvgSensitivity = fvgSensitivityText == "Extreme" ? 6 : fvgSensitivityText == "High" ? 2 : fvgSensitivityText == "Normal" ? 1.5 : 1

// === DISPLAY CONFIGURATION ===
showSessions = input.bool(true, "Show Sessions", inline = "2", group = "General Configuration")
showHL = input.bool(false, "Highs / Lows", inline = "2", group = "General Configuration")
showFVGs = input.bool(true, "FVGs", inline = "2", group = "General Configuration")
showTPSL = input.bool(true, "TP / SL", inline = "2", group = "General Configuration")
showOB = input.bool(true, "Order Blocks", inline = "2", group = "General Configuration")  // ADDED
showBB = input.bool(true, "Breaker Blocks", inline = "2", group = "General Configuration")  // ADDED
showBOS = input.bool(true, "Break of Structure", inline = "3", group = "General Configuration")  // ADDED
showEQHL = input.bool(true, "Equal Highs/Lows", inline = "3", group = "General Configuration")  // ADDED

// === ENHANCED FILTER SETTINGS === (SPEC COMPLIANCE)
dailyBias = input.string("None", "Daily Bias", options = ["None", "Bullish", "Bearish"], group = "Smart Filters",     tooltip = "Sets a directional bias for the day")
useHigherTFliq = input.bool(true, "Higher TF Liquidity", inline = "4", group = "Smart Filters",    tooltip = "Considers previous daily/session highs/lows for liquidity sweeps")
requireDisplacement = input.bool(true, "Require Displacement", inline = "4", group = "Smart Filters",    tooltip = "Requires strong displacement after liquidity sweep for entry")
requireOBConfluence = input.bool(true, "Order Block Confluence", inline = "5", group = "Smart Filters",    tooltip = "Requires entry within a valid Order Block")
volumeFilter = input.bool(true, "Volume Filter", inline = "5", group = "Smart Filters")

// === ADVANCED MARKET STRUCTURE SETTINGS === (ADDED)
bos_lookback = input.int(10, "BOS Lookback", group = "Market Structure")
eqhl_threshold = input.float(0.05, "EQ H/L Threshold %", group = "Market Structure")
choch_confirmation = input.bool(true, "Require CHoCH", group = "Market Structure")
ob_lookback = input.int(20, "Order Block Lookback", group = "Market Structure")
bb_confirmation = input.bool(true, "Breaker Block Confirmation", group = "Market Structure")
msip_buffer = input.float(0.2, "MSIP Buffer ATR Multiplier", group = "Market Structure")

// === RISK MANAGEMENT ===
tpslMethod = input.string("Dynamic", "TP / SL Method", options = ["Dynamic", "Fixed", "MSIP"], group = "TP / SL",    tooltip = "Dynamic -> Based on ATR\nFixed -> Based on percentages\nMSIP -> Market Structure Invalidation Point")
riskAmount = input.string("Normal", "Risk", options = ["High", "Normal", "Low"], group = "TP / SL",     tooltip = "The risk amount when Dynamic TP / SL method is selected.")
tpPercent = input.float(0.3, "Take Profit %", group = "TP / SL")
slPercent = input.float(0.4, "Stop Loss %", group = "TP / SL")
closePositionAtEndSession = input.bool(true, "Close Position @ Session End", group = "TP / SL")
partialTP = input.bool(true, "Use Partial Take Profits", group = "TP / SL")  // ADDED
trailingStop = input.bool(true, "Use Trailing Stop", group = "TP / SL")  // ADDED

RR = DEBUG ? input.float(0.99, "Risk:Reward Ratio", group = "Debug") : 1.5  // INCREASED from 0.99
requireFVGRetracement = DEBUG ? input.bool(true, "[DBG] Require FVG Retracement", group = "Debug") : true
slATRMult = riskAmount == "High" ? 6.5 : riskAmount == "Normal" ? 5.5 : 3.5

executeInsideSession = DEBUG ? input.bool(true, "Must Execute Inside Session", group = "Debug", display = display.none) : true
ny1Enabled = DEBUG ? input.bool(true, "NY 1", group = "Debug", display = display.none) : true
ny2Enabled = DEBUG ? input.bool(true, "NY 2", group = "Debug", display = display.none) : true
lnEnabled = DEBUG ? input.bool(true, "London", group = "Debug", display = display.none) : true
asiaEnabled = input.bool(false, "Asia", group = "Sessions")  // ADDED
killZoneEnabled = input.bool(true, "Kill Zone Only", group = "Sessions")  // ADDED

// === BACKTESTING DASHBOARD ===
backtestDisplayEnabled = input.bool(true, "Enabled", group = "Backtesting Dashboard", display = display.none)
backtestingLocation = input.string("Top Center", "Position", options = ["Top Right", "Right Center", "Top Center"], group = "Backtesting Dashboard", display = display.none)
fillBackgrounds = input.bool(true, "Fill Backgrounds", group = "Backtesting Dashboard", display = display.none)
screenerColor = input.color(#1B1F2B, 'Background', inline = "1", group = 'Backtesting Dashboard', display = display.none)

// === VISUAL SETTINGS ===
highColor = input.color(color.green, "Buy", inline = "colors", group = "Visuals")
lowColor = input.color(color.red, "Sell", inline = "colors", group = "Visuals")
textColor = input.color(color.white, "Text", inline = "colors", group = "Visuals")
obColor = input.color(color.new(color.blue, 70), "Order Block", inline = "colors2", group = "Visuals")  // ADDED
bbColor = input.color(color.new(color.purple, 70), "Breaker Block", inline = "colors2", group = "Visuals")  // ADDED
bosColor = input.color(color.new(color.yellow, 70), "BOS", inline = "colors3", group = "Visuals")  // ADDED
eqhlColor = input.color(color.new(color.orange, 70), "EQ H/L", inline = "colors3", group = "Visuals")  // ADDED

// === ALERTS ===
buyAlertEnabled = input.bool(true, "Buy Signal", inline = "BS", group = "Alerts")
sellAlertEnabled = input.bool(true, "Sell Signal", inline = "BS", group = "Alerts")
tpAlertEnabled = input.bool(true, "Take-Profit Signal", inline = "TS", group = "Alerts")
slAlertEnabled = input.bool(true, "Stop-Loss Signal ", inline = "TS", group = "Alerts")
bosAlertEnabled = input.bool(true, "Break of Structure Alert", inline = "MS", group = "Alerts")  // ADDED
eqhlAlertEnabled = input.bool(true, "Equal High/Low Alert", inline = "MS", group = "Alerts")  // ADDED

buyAlertTick = false
sellAlertTick = false
tpAlertTick = false
slAlertTick = false
bosAlertTick = false  // ADDED
eqhlAlertTick = false  // ADDED

// === TYPE DEFINITIONS ===
type FVG
    int startTime
    int endTime
    float top
    float bottom
    bool isBull

type Sweep
    int startTime
    int endTime
    string side
    float price

type OrderBlock  // ADDED
    int startTime
    int endTime
    float top
    float bottom
    bool isBull
    bool isBOS
    bool isBreaker

type BOS  // ADDED
    int time
    float price
    bool isBull
    bool confirmed

type EQHL  // ADDED
    int time
    float price
    bool isHigh

type SilverBullet
    string state
    int startTime

    int lastHour = na
    float lastHourHigh = na
    float lastHourLow = na
    Sweep brokenSweep = na
    float slTarget
    float tpTarget
    float tp1Target  // ADDED
    float tp2Target  // ADDED
    float trailStop  // ADDED
    string entryType
    int entryTime
    int exitTime
    float entryPrice
    float exitPrice
    int dayEndedBeforeExit
    FVG fvg
    OrderBlock ob  // ADDED
    BOS bos  // ADDED
    bool htfAligned  // ADDED
    float msip  // ADDED

var lineX = array.new<line>()
var boxX = array.new<box>()
var labelX = array.new<label>()

var SilverBullet[] sbList = array.new<SilverBullet>(0)
var SilverBullet lastSB = na

var OrderBlock[] orderBlocks = array.new<OrderBlock>(0)  // ADDED
var BOS[] bosPoints = array.new<BOS>(0)  // ADDED
var EQHL[] eqhlPoints = array.new<EQHL>(0)  // ADDED

// === INDICATORS ===
atr = ta.atr(atrLen)
rsi = ta.rsi(close, 14)
htf_close = request.security(syminfo.tickerid, htfPeriod, close)
htf_high = request.security(syminfo.tickerid, htfPeriod, high)
htf_low = request.security(syminfo.tickerid, htfPeriod, low)
htf_open = request.security(syminfo.tickerid, htfPeriod, open)

// === HIGHER TIMEFRAME LIQUIDITY ===
daily_high = request.security(syminfo.tickerid, "D", high[1])
daily_low = request.security(syminfo.tickerid, "D", low[1])

// London session high/low from previous day
london_high = request.security(syminfo.tickerid, "60", high, lookahead=barmerge.lookahead_on)
london_low = request.security(syminfo.tickerid, "60", low, lookahead=barmerge.lookahead_on)
prev_london_high = request.security(syminfo.tickerid, "D", london_high[1])
prev_london_low = request.security(syminfo.tickerid, "D", london_low[1])

// NY1 session high/low from previous day
ny1_high = request.security(syminfo.tickerid, "60", high, lookahead=barmerge.lookahead_on)
ny1_low = request.security(syminfo.tickerid, "60", low, lookahead=barmerge.lookahead_on)
prev_ny1_high = request.security(syminfo.tickerid, "D", ny1_high[1])
prev_ny1_low = request.security(syminfo.tickerid, "D", ny1_low[1])

// NY2 session high/low from previous day
ny2_high = request.security(syminfo.tickerid, "60", high, lookahead=barmerge.lookahead_on)
ny2_low = request.security(syminfo.tickerid, "60", low, lookahead=barmerge.lookahead_on)
prev_ny2_high = request.security(syminfo.tickerid, "D", ny2_high[1])
prev_ny2_low = request.security(syminfo.tickerid, "D", ny2_low[1])

// === DISPLACEMENT DETECTION FUNCTION ===
isDisplacement(int lookback, bool isBullish) =>
    result = true
    // Check for consecutive candles
    for i = 0 to lookback-1
        if isBullish
            if not (close[i] > open[i] and (close[i] - open[i]) > 0.5 * atr[i])
                result := false
                break
        else
            if not (close[i] < open[i] and (open[i] - close[i]) > 0.5 * atr[i])
                result := false
                break
    
    // Check for FVG
    if isBullish
        if not (low > high[lookback+1])
            result := false
    else
        if not (high < low[lookback+1])
            result := false
    
    result

// === ORDER BLOCK IDENTIFICATION FUNCTION ===
findOrderBlock(int lookback, bool isBullish) =>
    var OrderBlock result = na
    
    for i = 0 to lookback
        // For bullish OB, find last bearish candle before bullish displacement
        if isBullish
            if close[i] < open[i]  // Bearish candle
                if isDisplacement(3, true) and i >= 3  // Check for bullish displacement starting 3 bars later
                    result := OrderBlock.new(time[i], na, high[i], low[i], true, false, false)
                    break
        // For bearish OB, find last bullish candle before bearish displacement
        else
            if close[i] > open[i]  // Bullish candle
                if isDisplacement(3, false) and i >= 3  // Check for bearish displacement starting 3 bars later
                    result := OrderBlock.new(time[i], na, high[i], low[i], false, false, false)
                    break
    
    result

// === HELPER FUNCTIONS ===
diffPercent(float val1, float val2) =>
    (math.abs(val1 - val2) / val2) * 100.0

getPosition(positionText) =>
    if positionText == "Top Right"
        position.top_right
    else if positionText == "Top Center"
        position.top_center
    else if positionText == "Right Center"
        position.middle_right
    else if positionText == "Left Center"
        position.middle_left
    else if positionText == "Bottom Center"
        position.bottom_center
    else if positionText == "Middle Center"
        position.middle_center

// === MSS VARIABLES FOR TP/SL ===
float highMSS = ta.highest(mssOffset)
float lowMSS = ta.lowest(mssOffset)

// === HELPER FUNCTION FOR TP/SL SETUP ===
setupTpSl(SilverBullet sb) =>
    if tpslMethod == "Fixed"
        if sb.entryType == "Long"
            sb.slTarget := sb.entryPrice * (1 - slPercent / 100.0)
            sb.tpTarget := sb.entryPrice * (1 + tpPercent / 100.0)
        else
            sb.slTarget := sb.entryPrice * (1 + slPercent / 100.0)
            sb.tpTarget := sb.entryPrice * (1 - tpPercent / 100.0)
    else if tpslMethod == "Dynamic"
        // If we have a valid Order Block, use it for SL placement
        if requireOBConfluence and not na(sb.ob)
            if sb.entryType == "Long"
                // Place SL just below the bullish Order Block with buffer
                sb.slTarget := sb.ob.bottom - (atr * 0.5)
                
                // For TP, use higher timeframe liquidity levels if enabled
                if useHigherTFliq
                    // Target the nearest higher timeframe liquidity level (daily/session high)
                    htf_target = math.max(daily_high, math.max(prev_london_high, math.max(prev_ny1_high, prev_ny2_high)))
                    sb.tpTarget := htf_target
                else
                    // Default to RR-based TP
                    sb.tpTarget := sb.entryPrice + (math.abs(sb.entryPrice - sb.slTarget) * RR)
            else
                // Place SL just above the bearish Order Block with buffer
                sb.slTarget := sb.ob.top + (atr * 0.5)
                
                // For TP, use higher timeframe liquidity levels if enabled
                if useHigherTFliq
                    // Target the nearest higher timeframe liquidity level (daily/session low)
                    htf_target = math.min(daily_low, math.min(prev_london_low, math.min(prev_ny1_low, prev_ny2_low)))
                    sb.tpTarget := htf_target
                else
                    // Default to RR-based TP
                    sb.tpTarget := sb.entryPrice - (math.abs(sb.entryPrice - sb.slTarget) * RR)
        else
            // No valid Order Block, use default ATR-based SL
            if sb.entryType == "Long"
                sb.slTarget := low - (atr * slATRMult)
                
                // For TP, use higher timeframe liquidity levels if enabled
                if useHigherTFliq
                    // Target the nearest higher timeframe liquidity level (daily/session high)
                    htf_target = math.max(daily_high, math.max(prev_london_high, math.max(prev_ny1_high, prev_ny2_high)))
                    sb.tpTarget := htf_target
                else
                    // Default to RR-based TP
                    sb.tpTarget := sb.entryPrice + (math.abs(sb.entryPrice - sb.slTarget) * RR)
            else
                sb.slTarget := high + (atr * slATRMult)
                
                // For TP, use higher timeframe liquidity levels if enabled
                if useHigherTFliq
                    // Target the nearest higher timeframe liquidity level (daily/session low)
                    htf_target = math.min(daily_low, math.min(prev_london_low, math.min(prev_ny1_low, prev_ny2_low)))
                    sb.tpTarget := htf_target
                else
                    // Default to RR-based TP
                    sb.tpTarget := sb.entryPrice - (math.abs(sb.entryPrice - sb.slTarget) * RR)
    else  // MSIP or other methods
        if sb.entryType == "Long"
            sb.slTarget := lowMSS - atr * slATRMult
            sb.tpTarget := sb.entryPrice + (math.abs(sb.entryPrice - sb.slTarget) * RR)
        else
            sb.slTarget := highMSS + atr * slATRMult
            sb.tpTarget := sb.entryPrice - (math.abs(sb.entryPrice - sb.slTarget) * RR)

// === TIMEFRAME VALIDATION ===
tfInMin = timeframe.in_seconds() / 60
if tfInMin > 5
    runtime.error("Silver Bullet indicator only works timeframes <= 5 Minutes.")

// === SESSION MANAGEMENT ===
int barLength = 60 / tfInMin
float high12 = ta.highest(barLength)
float low12 = ta.lowest(barLength)
int lastHourTime = time[barLength]

// === SESSION DETECTION ===
sessionBegins(sess) =>
    t = time("1440", sess, "America/New_York")
    is_first = na(t[1]) and not na(t) or t[1] < t

inKillZone = not na(time("", killZone1, "America/New_York")) or not na(time("", killZone2, "America/New_York"))
newSession = (ny1Enabled and sessionBegins(nySession1)) or (ny2Enabled and sessionBegins(nySession2)) or 
             (lnEnabled and sessionBegins(londonSession)) or (asiaEnabled and sessionBegins(asiaSession))
insideSession = (ny1Enabled and not na(time("", nySession1, "America/New_York"))) or                 (ny2Enabled and not na (time("", nySession2, "America/New_York"))) or                (lnEnabled and not na(time("", londonSession, "America/New_York"))) or                (asiaEnabled and not na(time("", asiaSession, "America/New_York")))
endSession = (not insideSession and insideSession[1])

// === MARKET STRUCTURE DETECTION === (ADDED)

// Higher Timeframe Market Structure
htf_swing_high = ta.pivothigh(htf_high, bos_lookback, bos_lookback)
htf_swing_low = ta.pivotlow(htf_low, bos_lookback, bos_lookback)
htf_higher_high = not na(htf_swing_high) and htf_swing_high > ta.valuewhen(not na(htf_swing_high[1]), htf_swing_high[1], 1)
htf_lower_high = not na(htf_swing_high) and htf_swing_high < ta.valuewhen(not na(htf_swing_high[1]), htf_swing_high[1], 1)
htf_higher_low = not na(htf_swing_low) and htf_swing_low > ta.valuewhen(not na(htf_swing_low[1]), htf_swing_low[1], 1)
htf_lower_low = not na(htf_swing_low) and htf_swing_low < ta.valuewhen(not na(htf_swing_low[1]), htf_swing_low[1], 1)

// Higher timeframe trend detection
htfUptrend = htf_higher_high and htf_higher_low
htfDowntrend = htf_lower_high and htf_lower_low

// Current timeframe trend detection
inUptrend = close > open and close > close[1]
inDowntrend = close < open and close < close[1]

// Current Timeframe Market Structure
swing_high = ta.pivothigh(high, bos_lookback/2, bos_lookback/2)
swing_low = ta.pivotlow(low, bos_lookback/2, bos_lookback/2)
higher_high = not na(swing_high) and swing_high > ta.valuewhen(not na(swing_high[1]), swing_high[1], 1)
lower_high = not na(swing_high) and swing_high < ta.valuewhen(not na(swing_high[1]), swing_high[1], 1)
higher_low = not na(swing_low) and swing_low > ta.valuewhen(not na(swing_low[1]), swing_low[1], 1)
lower_low = not na(swing_low) and swing_low < ta.valuewhen(not na(swing_low[1]), swing_low[1], 1)

// Break of Structure Detection
bullish_bos = lower_low and higher_low
bearish_bos = higher_high and lower_high

// Equal Highs/Lows Detection
eq_high_detected = not na(swing_high) and math.abs(diffPercent(swing_high, ta.valuewhen(not na(swing_high[1]), swing_high[1], 1))) < eqhl_threshold
eq_low_detected = not na(swing_low) and math.abs(diffPercent(swing_low, ta.valuewhen(not na(swing_low[1]), swing_low[1], 1))) < eqhl_threshold

// Order Block Detection
create_bull_ob = bearish_bos and barstate.isconfirmed
create_bear_ob = bullish_bos and barstate.isconfirmed

// Breaker Block Detection
bull_breaker = false
bear_breaker = false

if orderBlocks.size() > 0
    for i = 0 to orderBlocks.size() - 1
        ob = orderBlocks.get(i)
        if not na(ob)
            if not ob.isBreaker
                if ob.isBull and low <= ob.bottom
                    bull_breaker := true
                    var OrderBlock tempOB = orderBlocks.get(i)
                    tempOB.isBreaker := true
                    orderBlocks.set(i, tempOB)
                if not ob.isBull and high >= ob.top
                    bear_breaker := true
                    var OrderBlock tempOB2 = orderBlocks.get(i)
                    tempOB2.isBreaker := true
                    orderBlocks.set(i, tempOB2)

// Update BOS array
if bullish_bos
    newBOS = BOS.new(time, low[bos_lookback/2], true, false)
    bosPoints.unshift(newBOS)
    bosAlertTick := true
if bearish_bos
    newBOS = BOS.new(time, high[bos_lookback/2], false, false)
    bosPoints.unshift(newBOS)
    bosAlertTick := true

// Update EQHL array
if eq_high_detected
    newEQHL = EQHL.new(time, swing_high, true)
    eqhlPoints.unshift(newEQHL)
    eqhlAlertTick := true
if eq_low_detected
    newEQHL = EQHL.new(time, swing_low, false)
    eqhlPoints.unshift(newEQHL)
    eqhlAlertTick := true

// Update Order Blocks array
if create_bull_ob
    for i = 1 to ob_lookback
        if open[i] > close[i]  // Bearish candle
            newOB = OrderBlock.new(time[i], na, high[i], low[i], true, true, false)
            orderBlocks.unshift(newOB)
            break
if create_bear_ob
    for i = 1 to ob_lookback
        if open[i] < close[i]  // Bullish candle
            newOB = OrderBlock.new(time[i], na, high[i], low[i], false, true, false)
            orderBlocks.unshift(newOB)
            break

// === MAIN STRATEGY LOGIC ===
if bar_index > last_bar_index - maxDistanceToLastBar
    // FVG End
    if not na(lastSB) and endSession
        if not na(lastSB.fvg)
            if na(lastSB.fvg.endTime)
                lastSB.fvg.endTime := time
    
    if not na(lastSB)
        if not na(lastSB.fvg)
            if na(lastSB.fvg.endTime) and ((lastSB.fvg.isBull and low <= lastSB.fvg.bottom) or (not lastSB.fvg.isBull and high >= lastSB.fvg.top))
                lastSB.fvg.endTime := time
    
    // Order Block End (ADDED)
    if orderBlocks.size() > 0
        for i = 0 to orderBlocks.size() - 1
            ob = orderBlocks.get(i)
            if not na(ob) and na(ob.endTime)
                if (ob.isBull and low <= ob.bottom) or (not ob.isBull and high >= ob.top)
                    var OrderBlock tempOB3 = orderBlocks.get(i)
                    tempOB3.endTime := time
                    orderBlocks.set(i, tempOB3)
    
    if true
        // Find Session Start
        if newSession
            createNewSB = true
            if not na(lastSB)
                if not na(lastSB.entryPrice) and na(lastSB.exitPrice)
                    if closePositionAtEndSession
                        lastSB.dayEndedBeforeExit := time[1]
                        lastSB.exitTime := time
                        lastSB.exitPrice := close
                    else
                        createNewSB := false // Don't enter if a trade is already entered
                    
            if createNewSB
                newSB = SilverBullet.new("Waiting For Liquidity Break", time)
                newSB.lastHourHigh := high12
                newSB.lastHourLow := low12
                newSB.lastHour := lastHourTime
                // HTF Alignment (ADDED)
                newSB.htfAligned := (htfUptrend and inUptrend) or (htfDowntrend and inDowntrend)
                sbList.unshift(newSB)
                lastSB := newSB

        if not na(lastSB)
            // === FVG DETECTION ===
            fvgEnter = false
            if na(lastSB.fvg) and lastSB.state != "Waiting For Liquidity Break" and ((not executeInsideSession) or insideSession)
                bearCondition = false
                bullCondition = false

                firstBarSize = math.max(open, close) - math.min(open, close)
                secondBarSize = math.max(open[1], close[1]) - math.min(open[1], close[1])
                thirdBarSize = math.max(open[2], close[2]) - math.min(open[2], close[2])
                barSizeSum = firstBarSize + secondBarSize + thirdBarSize

                barSizeCheck = true
                //if (secondBarSize * fvgSensitivity < (firstBarSize + thirdBarSize) * 1.5)
                    //barSizeCheck := false

                fvgBarsCheck = false
                if fvgBars == "Same Type"
                    if (open > close and open[1] > close[1] and open[2] > close[2]) or (open <= close and open[1] <= close[1] and open[2] <= close[2])
                        fvgBarsCheck := true
                else
                    fvgBarsCheck := true

                if fvgBarsCheck and barSizeCheck
                    maxCODiff = math.max(math.abs(close[2] - open[1]), math.abs(close[1] - open))
                    bearCondition := ((not fvgSensEnabled) or (barSizeSum * fvgSensitivity > atr / 1.5)) and (allowGaps or (maxCODiff <= atr))
                    bullCondition := ((not fvgSensEnabled) or (barSizeSum * fvgSensitivity > atr / 1.5)) and (allowGaps or (maxCODiff <= atr))

                bearFVG = high < low[2] and close[1] < low[2] and bearCondition
                bullFVG = low > high[2] and close[1] > high[2] and bullCondition

                FVGSize = bearFVG ? math.abs(low[2] - high) : bullFVG ? math.abs(low - high[2]) : 0
                FVGSizeEnough = (FVGSize * fvgSensitivity > atr)
            
                if (bearFVG or bullFVG) and (FVGSizeEnough or (not fvgSensEnabled))
                    if (fvgEntry == "All")
                        fvgEnter := true
                    
                    if (fvgEntry == "Along")
                        if (lastSB.entryType == "Long" and bullFVG) or (lastSB.entryType == "Short" and bearFVG)
                            fvgEnter := true
                    
                    if (fvgEntry == "Inverse")
                        if (lastSB.entryType == "Long" and bearFVG) or (lastSB.entryType == "Short" and bullFVG)
                            fvgEnter := true
                    lastSB.fvg := FVG.new(time, na, bearFVG ? low[2] : low, bearFVG ? high : high[2], bullFVG)

            // === FIND LIQUIDITY BREAKS ===
            if lastSB.state == "Waiting For Liquidity Break"
                if time > lastSB.startTime
                    // Check for standard liquidity break
                    standardLiquidityBreak = false
                    standardBreakBullish = false
                    standardBreakBearish = false
                    
                    if (breakoutMethod == "Close" ? close : low) < lastSB.lastHourLow
                        standardLiquidityBreak := true
                        standardBreakBullish := true
                    else if (breakoutMethod == "Close" ? close : high) > lastSB.lastHourHigh
                        standardLiquidityBreak := true
                        standardBreakBearish := true
                    
                    // Check for higher timeframe liquidity break
                    htfLiquidityBreak = false
                    htfBreakBullish = false
                    htfBreakBearish = false
                    
                    if useHigherTFliq
                        // Check for daily/session lows (for bullish entry)
                        if (breakoutMethod == "Close" ? close : low) < daily_low or
                           (breakoutMethod == "Close" ? close : low) < prev_london_low or
                           (breakoutMethod == "Close" ? close : low) < prev_ny1_low or
                           (breakoutMethod == "Close" ? close : low) < prev_ny2_low
                            htfLiquidityBreak := true
                            htfBreakBullish := true
                        
                        // Check for daily/session highs (for bearish entry)
                        if (breakoutMethod == "Close" ? close : high) > daily_high or
                           (breakoutMethod == "Close" ? close : high) > prev_london_high or
                           (breakoutMethod == "Close" ? close : high) > prev_ny1_high or
                           (breakoutMethod == "Close" ? close : high) > prev_ny2_high
                            htfLiquidityBreak := true
                            htfBreakBearish := true
                    
                    // Daily bias filter
                    biasCheck = dailyBias == "None" or             (dailyBias == "Bullish" and (standardBreakBullish or htfBreakBullish)) or       (dailyBias == "Bearish" and (standardBreakBearish or htfBreakBearish))
                    
                    // Volume filter
                    volumeCheck = not volumeFilter or volume > ta.sma(volume, 20)
                    
                    // Combined check for Bullish entry
                    if (standardBreakBullish or htfBreakBullish) and biasCheck and volumeCheck
                        // Check for displacement if required
                        displacementCheck = not requireDisplacement or isDisplacement(3, true)
                        
                        if displacementCheck
                            // Set up for bullish trade
                            lastSB.brokenSweep := Sweep.new(lastSB.lastHour, time, "Sellside", standardBreakBullish ? lastSB.lastHourLow : 
                                                           math.min(daily_low, math.min(prev_london_low, math.min(prev_ny1_low, prev_ny2_low))))
                            lastSB.entryType := "Long"
                            lastSB.state := "Waiting For Execution"
                            
                            // Find bullish Order Block if required
                            if requireOBConfluence
                                lastSB.ob := findOrderBlock(20, true)  // Look back 20 bars for bullish OB
                    
                    // Combined check for Bearish entry
                    else if (standardBreakBearish or htfBreakBearish) and biasCheck and volumeCheck
                        // Check for displacement if required
                        displacementCheck = not requireDisplacement or isDisplacement(3, false)
                        
                        if displacementCheck
                            // Set up for bearish trade
                            lastSB.brokenSweep := Sweep.new(lastSB.lastHour, time, "Buyside", standardBreakBearish ? lastSB.lastHourHigh : 
                                                           math.max(daily_high, math.max(prev_london_high, math.max(prev_ny1_high, prev_ny2_high))))
                            lastSB.entryType := "Short"
                            lastSB.state := "Waiting For Execution"
                            
                            // Find bearish Order Block if required
                            if requireOBConfluence
                                lastSB.ob := findOrderBlock(20, false)  // Look back 20 bars for bearish OB

            // === EXECUTE ENTRY ===
            if lastSB.state == "Waiting For Execution" and ((not executeInsideSession) or insideSession)
                if time > lastSB.brokenSweep.endTime
                    // Order Block Confluence Check
                    obConfluenceCheck = true
                    if requireOBConfluence and not na(lastSB.ob)
                        // For long entry, price should be within bullish Order Block
                        if lastSB.entryType == "Long"
                            obConfluenceCheck := low <= lastSB.ob.top and high >= lastSB.ob.bottom
                        // For short entry, price should be within bearish Order Block
                        else
                            obConfluenceCheck := high >= lastSB.ob.bottom and low <= lastSB.ob.top
                    
                    // MSS Execution
                    if executionType == "MSS" and obConfluenceCheck
                        if lastSB.brokenSweep.side == "Buyside" // Short
                            if (breakoutMethod == "Close" ? close : low) < lowMSS[1]
                                sellAlertTick := true
                                lastSB.state := "Entry Taken"
                                lastSB.entryTime := time
                                lastSB.entryPrice := (breakoutMethod == "Close" ? close : lowMSS[1])
                                setupTpSl(lastSB)
                        else // Long
                            if (breakoutMethod == "Close" ? close : high) > highMSS[1]
                                buyAlertTick := true
                                lastSB.state := "Entry Taken"
                                lastSB.entryTime := time
                                lastSB.entryPrice := (breakoutMethod == "Close" ? close : highMSS[1])
                                setupTpSl(lastSB)
                    
                    // FVG Execution
                    else if fvgEnter and executionType == "FVG" and obConfluenceCheck
                        if not requireFVGRetracement
                            lastSB.state := "Entry Taken"
                            lastSB.entryTime := time
                            lastSB.entryPrice := close
                            if lastSB.entryType == "Long"
                                buyAlertTick := true
                                setupTpSl(lastSB)
                            else
                                sellAlertTick := true
                                setupTpSl(lastSB)
                        else
                            lastSB.state := "FVG Retracement"
                    
                    // Order Block Execution
                    else if executionType == "Order Block" and obConfluenceCheck
                        lastSB.state := "Entry Taken"
                        lastSB.entryTime := time
                        lastSB.entryPrice := close
                        if lastSB.entryType == "Long"
                            buyAlertTick := true
                            setupTpSl(lastSB)
                        else
                            sellAlertTick := true
                            setupTpSl(lastSB)

    // === FVG RETRACEMENT ===
    if not na(lastSB)
        if lastSB.state == "FVG Retracement" and ((not executeInsideSession) or insideSession)
            if (lastSB.fvg.isBull and (breakoutMethod == "Close" ? close : low) < lastSB.fvg.top) or (not lastSB.fvg.isBull and (breakoutMethod == "Close" ? close : high) > lastSB.fvg.bottom)
                lastSB.state := "Entry Taken"
                lastSB.entryTime := time
                lastSB.entryPrice := close
                if lastSB.entryType == "Long"
                    buyAlertTick := true
                    setupTpSl(lastSB)
                else
                    sellAlertTick := true
                    setupTpSl(lastSB)
    
    // === POSITION MANAGEMENT ===
    if not na(lastSB)
        if lastSB.state == "Entry Taken"
            if tpslMethod == "Fixed"
                // Take Profit
                if lastSB.entryType == "Long" and ((high / lastSB.entryPrice) - 1) * 100 >= tpPercent
                    tpAlertTick := true
                    lastSB.exitPrice := lastSB.entryPrice * (1 + tpPercent / 100.0)
                    lastSB.exitTime := time
                    lastSB.state := "Take Profit"
                if lastSB.entryType == "Short" and ((low / lastSB.entryPrice) - 1) * 100 <= -tpPercent
                    tpAlertTick := true
                    lastSB.exitPrice := lastSB.entryPrice * (1 - tpPercent / 100.0)
                    lastSB.exitTime := time
                    lastSB.state := "Take Profit"
                
                // Stop Loss
                if lastSB.entryType == "Long" and ((low / lastSB.entryPrice) - 1) * 100 <= -slPercent
                    slAlertTick := true
                    lastSB.exitPrice := lastSB.entryPrice * (1 - slPercent / 100.0)
                    lastSB.exitTime := time
                    lastSB.state := "Stop Loss"
                if lastSB.entryType == "Short" and ((high / lastSB.entryPrice) - 1) * 100 >= slPercent
                    slAlertTick := true
                    lastSB.exitPrice := lastSB.entryPrice * (1 + slPercent / 100.0)
                    lastSB.exitTime := time
                    lastSB.state := "Stop Loss"
            else if tpslMethod == "MSIP"
                // Take Profit with MSIP method
                if lastSB.entryType == "Long" and high >= lastSB.tpTarget
                    tpAlertTick := true
                    lastSB.exitPrice := lastSB.tpTarget
                    lastSB.exitTime := time
                    lastSB.state := "Take Profit"
                if lastSB.entryType == "Short" and low <= lastSB.tpTarget
                    tpAlertTick := true
                    lastSB.exitPrice := lastSB.tpTarget
                    lastSB.exitTime := time
                    lastSB.state := "Take Profit"
                
                // Stop Loss with MSIP
                if lastSB.entryType == "Long" and low <= lastSB.msip
                    slAlertTick := true
                    lastSB.exitPrice := lastSB.msip
                    lastSB.exitTime := time
                    lastSB.state := "Stop Loss"
                if lastSB.entryType == "Short" and high >= lastSB.msip
                    slAlertTick := true
                    lastSB.exitPrice := lastSB.msip
                    lastSB.exitTime := time
                    lastSB.state := "Stop Loss"
            else
                // Dynamic Take Profit
                if lastSB.entryType == "Long" and ((maxTPLastHour and high >= lastSB.lastHourHigh) or high >= lastSB.tpTarget)
                    tpAlertTick := true
                    lastSB.exitPrice := (high >= math.max(lastSB.lastHourHigh, lastSB.tpTarget) ? math.max(lastSB.lastHourHigh, lastSB.tpTarget) : math.min(lastSB.lastHourHigh, lastSB.tpTarget))
                    lastSB.exitTime := time
                    lastSB.state := "Take Profit"
                if lastSB.entryType == "Short" and ((maxTPLastHour and low <= lastSB.lastHourLow) or low <= lastSB.tpTarget)
                    tpAlertTick := true
                    lastSB.exitPrice := (low <= math.min(lastSB.lastHourLow, lastSB.tpTarget) ? math.min(lastSB.lastHourLow, lastSB.tpTarget) : math.max(lastSB.lastHourLow, lastSB.tpTarget))
                    lastSB.exitTime := time
                    lastSB.state := "Take Profit"
                
                // Dynamic Stop Loss
                if lastSB.entryType == "Long" and low <= lastSB.slTarget
                    slAlertTick := true
                    lastSB.exitPrice := lastSB.slTarget
                    lastSB.exitTime := time
                    lastSB.state := "Stop Loss"
                if lastSB.entryType == "Short" and high >= lastSB.slTarget
                    slAlertTick := true
                    lastSB.exitPrice := lastSB.slTarget
                    lastSB.exitTime := time
                    lastSB.state := "Stop Loss"
                
                // Trailing Stop (ADDED)
                if trailingStop
                    if lastSB.entryType == "Long"
                        lastSB.trailStop := math.max(lastSB.trailStop, high - atr * 2)
                        if close < lastSB.trailStop and lastSB.trailStop > lastSB.entryPrice
                            slAlertTick := true
                            lastSB.exitPrice := lastSB.trailStop
                            lastSB.exitTime := time
                            lastSB.state := "Trailing Stop"
                    else
                        lastSB.trailStop := math.min(lastSB.trailStop, low + atr * 2)
                        if close > lastSB.trailStop and lastSB.trailStop < lastSB.entryPrice
                            slAlertTick := true
                            lastSB.exitPrice := lastSB.trailStop
                            lastSB.exitTime := time
                            lastSB.state := "Trailing Stop"

// === PLOTTING VISUALIZATION ===
tfs = (30 / (timeframe.in_seconds(timeframe.period) / 60))

plotColor = color.new(textColor, 60)
plotchar(not na(time("", nySession1, "America/New_York")) and newSession and showSessions, title = 'NY Session 1', location = location.top, text='10-11 AM\nNY', color=color.new(color.black, 100), textcolor=plotColor, offset= +tfs)
plotchar(not na(time("", nySession2, "America/New_York")) and newSession and showSessions, title = 'NY Session 2', location = location.top, text='2-3 PM\nNY', color=color.new(color.black, 100), textcolor=plotColor, offset= +tfs)
plotchar(not na(time("", londonSession, "America/New_York")) and newSession and showSessions, title = 'London Session', location = location.top, text='3-4 AM\nNY', color=color.new(color.black, 100), textcolor=plotColor, offset= +tfs)
plotchar(not na(time("", asiaSession, "America/New_York")) and newSession and showSessions, title = 'Asia Session', location = location.top, text='7-8 PM\nNY', color=color.new(color.black, 100), textcolor=plotColor, offset= +tfs)
plotchar(not na(time("", killZone1, "America/New_York")) and newSession and showSessions, title = 'Kill Zone 1', location = location.top, text='4-6 AM\nKZ', color=color.new(color.black, 100), textcolor=color.new(color.yellow, 60), offset= +tfs)
plotchar(not na(time("", killZone2, "America/New_York")) and newSession and showSessions, title = 'Kill Zone 2', location = location.top, text='1-3 PM\nKZ', color=color.new(color.black, 100), textcolor=color.new(color.yellow, 60), offset= +tfs)

if (newSession or endSession) and showSessions
    line.new(bar_index, close, bar_index, close + syminfo.mintick, color = plotColor, extend=extend.both)

// === RENDER TRADE SIGNALS ===
renderTopSL = false
renderBottomSL = false
renderTopTP = false
renderBottomTP = false

if not na(lastSB)
    if (lastSB.state == "Stop Loss" or lastSB.state == "Trailing Stop") and time > lastSB.exitTime
        if lastSB.entryType == "Long"
            renderBottomSL := true
        else
            renderTopSL := true
        lastSB.state := "Done"
    if lastSB.state == "Take Profit"
        if lastSB.entryType == "Long"
            renderTopTP := true
        else
            renderBottomTP := true
        lastSB.state := "Done"

plotshape(renderTopSL, "", shape.circle, location.abovebar, color.red, textcolor = textColor, text = "SL", size = size.tiny)
plotshape(renderBottomSL, "", shape.circle, location.belowbar, color.red, textcolor = textColor, text = "SL", size = size.tiny)
plotshape(renderTopTP, "", shape.xcross, location.abovebar, color.blue, textcolor = textColor, text = "TP", size = size.tiny)
plotshape(renderBottomTP, "", shape.xcross, location.belowbar, color.blue, textcolor = textColor, text = "TP", size = size.tiny)

// === PLOTTING MARKET STRUCTURE === (ADDED)
plotshape(showBOS and bullish_bos, title="Bullish BOS", style=shape.triangleup, location=location.belowbar, 
          color=bosColor, size=size.tiny, text="BOS")
plotshape(showBOS and bearish_bos, title="Bearish BOS", style=shape.triangledown, location=location.abovebar, 
          color=bosColor, size=size.tiny, text="BOS")
plotshape(showEQHL and eq_high_detected, title="Equal High", style=shape.diamond, location=location.abovebar, 
          color=eqhlColor, size=size.tiny, text="EQH")
plotshape(showEQHL and eq_low_detected, title="Equal Low", style=shape.diamond, location=location.belowbar, 
          color=eqhlColor, size=size.tiny, text="EQL")

// === ALERTS ===
if barstate.islastconfirmedhistory
    initRun := false

alertcondition(buyAlertTick and not initRun, "Buy Signal", "")
alertcondition(sellAlertTick and not initRun, "Sell Signal", "")
alertcondition(tpAlertTick and not initRun, "Take-Profit Signal", "")
alertcondition(slAlertTick and not initRun, "Stop-Loss Signal", "")
alertcondition(bosAlertTick and not initRun, "Break of Structure Signal", "")  // ADDED
alertcondition(eqhlAlertTick and not initRun, "Equal High/Low Signal", "")  // ADDED

if not initRun
    if buyAlertTick and buyAlertEnabled
        alert("Buy Signal")
    if sellAlertTick and sellAlertEnabled
        alert("Sell Signal")
    
    if tpAlertTick and tpAlertEnabled
        alert("Take-Profit Signal")
    if slAlertTick and slAlertEnabled
        alert("Stop-Loss Signal")
    
    if bosAlertTick and bosAlertEnabled
        alert("Break of Structure Signal")
    if eqhlAlertTick and eqhlAlertEnabled
        alert("Equal High/Low Signal")

// === RENDER VISUAL ELEMENTS ===
if barstate.isconfirmed
    if lineX.size() > 0
        for i = 0 to lineX.size() - 1
            line.delete(lineX.get(i))

    if boxX.size() > 0
        for i = 0 to boxX.size() - 1
            box.delete(boxX.get(i))
    
    if labelX.size() > 0
        for i = 0 to labelX.size() - 1
            label.delete(labelX.get(i))

    lineX.clear()
    boxX.clear()
    labelX.clear()
    
    if sbList.size() > 0
        for i = 0 to sbList.size() - 1
            curSB = sbList.get(i)

            // Last Hour
            if not na(curSB.brokenSweep) and showHL
                lineX.push(line.new(curSB.brokenSweep.startTime, curSB.lastHourHigh, curSB.brokenSweep.endTime, curSB.lastHourHigh, xloc = xloc.bar_time, color = lowColor, style = (curSB.brokenSweep.price == curSB.lastHourHigh ? line.style_dashed : line.style_solid)))
                lineX.push(line.new(curSB.brokenSweep.startTime, curSB.lastHourLow, curSB.brokenSweep.endTime, curSB.lastHourLow, xloc = xloc.bar_time, color =highColor, style = (curSB.brokenSweep.price == curSB.lastHourLow ? line.style_dashed : line.style_solid)))

            if not na(curSB.entryTime)
                // Entry Label
                if curSB.entryType == "Long"
                    labelX.push(label.new(curSB.entryTime, close, "Buy", xloc = xloc.bar_time, yloc = yloc.belowbar, textcolor = textColor, color = highColor, style = label.style_label_up, size = size.small))
                else
                    labelX.push(label.new(curSB.entryTime, close, "Sell", xloc = xloc.bar_time, yloc = yloc.abovebar, textcolor = textColor, color = lowColor, style = label.style_label_down, size = size.small))
            
                // FVG
                if showFVGs
                    if not na(curSB.fvg)
                        boxX.push(box.new(curSB.fvg.startTime, curSB.fvg.top, nz(curSB.fvg.endTime, time("", -extendFVG)), curSB.fvg.bottom, border_width = 0, xloc = xloc.bar_time, bgcolor = (curSB.fvg.isBull ? highColor : lowColor)))

                // Order Block (ADDED)
                if showOB
                    if not na(curSB.ob)
                        boxX.push(box.new(curSB.ob.startTime, curSB.ob.top, nz(curSB.ob.endTime, time("", -extendFVG)), curSB.ob.bottom, border_width = 1, xloc = xloc.bar_time, bgcolor = color.new(obColor, 80), border_color = obColor))

            // TP / SL
            if not na(curSB.entryTime)
                if showTPSL
                    offset = atr / 3.0
                    boxX.push(box.new(curSB.entryTime, curSB.tpTarget + offset, nz(curSB.exitTime, time("", -extendFVG)), curSB.tpTarget - offset, text = "TAKE PROFIT (" + str.tostring(curSB.tpTarget, format.mintick) + ")", text_color = textColor, xloc = xloc.bar_time, border_width = 0, bgcolor = color.new(highColor, 50), text_size = size.small))
                    boxX.push(box.new(curSB.entryTime, curSB.slTarget + offset, nz(curSB.exitTime, time("", -extendFVG)), curSB.slTarget - offset, text = "STOP LOSS (" + str.tostring(curSB.slTarget, format.mintick) + ")", text_color = textColor, xloc = xloc.bar_time, border_width = 0, bgcolor = color.new(lowColor, 50) , text_size = size.small))
                    
                    // Partial TP (ADDED)
                    if partialTP
                        boxX.push(box.new(curSB.entryTime, curSB.tp1Target + offset/2, nz(curSB.exitTime, time("", -extendFVG)), curSB.tp1Target - offset/2, text = "TP1", text_color = textColor, xloc = xloc.bar_time, border_width = 0, bgcolor = color.new(color.blue, 50), text_size = size.tiny))

            if not na(curSB.dayEndedBeforeExit)
                labelX.push(label.new(curSB.dayEndedBeforeExit, close, "Exit", xloc = xloc.bar_time, yloc = yloc.belowbar, textcolor = textColor, color = color.yellow, style = label.style_circle, size = size.tiny))

    // Render Order Blocks (ADDED)
    if orderBlocks.size() > 0 and showOB
        for i = 0 to math.min(orderBlocks.size() - 1, 10)  // Show last 10 order blocks max
            ob = orderBlocks.get(i)
            if not na(ob) and not ob.isBreaker
                boxX.push(box.new(ob.startTime, ob.top, nz(ob.endTime, time("", -extendFVG)), ob.bottom,  border_width = 1, xloc = xloc.bar_time,      bgcolor = color.new(obColor, 80), border_color = obColor))

    // Render Breaker Blocks (ADDED)
    if orderBlocks.size() > 0 and showBB
        for i = 0 to math.min(orderBlocks.size() - 1, 10)  // Show last 10 blocks max
            ob = orderBlocks.get(i)
            if not na(ob) and ob.isBreaker
                boxX.push(box.new(ob.startTime, ob.top, nz(ob.endTime, time("", -extendFVG)), ob.bottom,                 border_width = 1, xloc = xloc.bar_time,         bgcolor = color.new(bbColor, 80),                      border_color = bbColor))

// === BACKTESTING DASHBOARD ===
if barstate.islast and backtestDisplayEnabled
    var table backtestDisplay = table.new(getPosition(backtestingLocation), 2, 12, bgcolor = screenerColor, frame_width = 2, frame_color = color.black, border_width = 1, border_color = color.black)
    
    float totalSBProfitPercent = 0
    int successfulTrades = 0
    int unsuccessfulTrades = 0
    int longTrades = 0
    int shortTrades = 0
    int longWins = 0
    int shortWins = 0

    if sbList.size() > 0
        for i = 0 to sbList.size() - 1
            curSB = sbList.get(i)
            if not na(curSB.entryPrice)
                isSuccess = false
                if curSB.entryType == "Long"
                    longTrades += 1
                else
                    shortTrades += 1
                    
                if not na(curSB.exitPrice)
                    if (curSB.entryType == "Long" and curSB.exitPrice > curSB.entryPrice) or (curSB.entryType == "Short" and curSB.exitPrice < curSB.entryPrice)
                        totalSBProfitPercent += math.abs(diffPercent(curSB.entryPrice, curSB.exitPrice))
                        isSuccess := true
                        if curSB.entryType == "Long"
                            longWins += 1
                        else
                            shortWins += 1
                    else
                        totalSBProfitPercent -= math.abs(diffPercent(curSB.entryPrice, curSB.exitPrice))
                        isSuccess := false

                if isSuccess
                    successfulTrades += 1
                else
                    unsuccessfulTrades += 1
    
    // Header
    table.merge_cells(backtestDisplay, 0, 0, 1, 0)
    table.cell(backtestDisplay, 0, 0, "ICT Silver Bullet Enhanced", text_color = color.white, bgcolor = screenerColor)

    // Total Entries
    table.cell(backtestDisplay, 0, 1, "Total Entries", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 1, str.tostring(successfulTrades + unsuccessfulTrades), text_color = color.white, bgcolor = screenerColor)

    // Wins
    table.cell(backtestDisplay, 0, 2, "Wins", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 2, str.tostring(successfulTrades), text_color = color.white, bgcolor = screenerColor)

    // Losses
    table.cell(backtestDisplay, 0, 3, "Losses", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 3, str.tostring(unsuccessfulTrades), text_color = color.white, bgcolor = screenerColor)

    // Winrate
    table.cell(backtestDisplay, 0, 4, "Winrate", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 4, str.tostring(100.0 * (successfulTrades / math.max(1, (successfulTrades + unsuccessfulTrades))), "#.##") + "%", text_color = color.white, bgcolor = screenerColor)

    // Long Stats
    table.cell(backtestDisplay, 0, 5, "Long Trades", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 5, str.tostring(longTrades), text_color = color.white, bgcolor = screenerColor)

    // Long Winrate
    table.cell(backtestDisplay, 0, 6, "Long Winrate", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 6, str.tostring(100.0 * (longWins / math.max(1, longTrades)), "#.##") + "%", text_color = color.white, bgcolor = screenerColor)

    // Short Stats
    table.cell(backtestDisplay, 0, 7, "Short Trades", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 7, str.tostring(shortTrades), text_color = color.white, bgcolor = screenerColor)

    // Short Winrate
    table.cell(backtestDisplay, 0, 8, "Short Winrate", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 8, str.tostring(100.0 * (shortWins / math.max(1, shortTrades)), "#.##") + "%", text_color = color.white, bgcolor = screenerColor)

    // Average Profit %
    table.cell(backtestDisplay, 0, 9, "Average Profit", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 9, str.tostring(totalSBProfitPercent / math.max(1, (successfulTrades + unsuccessfulTrades)), "#.##") + "%", text_color = color.white, bgcolor = screenerColor)

    // Total Profit %
    table.cell(backtestDisplay, 0, 10, "Total Profit", text_color = color.white, bgcolor = screenerColor)
    table.cell(backtestDisplay, 1, 10, str.tostring(totalSBProfitPercent, "#.##") + "%", text_color = color.white, bgcolor = screenerColor)

Overview

ICT Silver Bullet Flux Charts v2 - Claude detects and visualizes Fair Value Gaps (FVG), Market Structure Shifts (MSS), Order Blocks, Breaker Blocks, Breaks of Structure (BOS), and Equal Highs/Lows across designated London, New York, and Asian sessions. Users can configure execution modes, higher-timeframe filters, volume confirmations, and displacement criteria, with dynamic take-profit and stop-loss projections plotted on chart. It relies on multi-timeframe requests that introduce lookahead risk.

Details

Published by

alboogycOdR on GitHub

Code credit

fluxchart - Enhanced by Claude, as written in the script's header

Type

Indicator, Pine Script v5

Draws

On the price chart

Category

SMC / ICT / price action, Sessions & time, Support & resistance, Scalping

Markets

Any symbol

Timeframes

M1-M5, M15-H1

Risk Notes

  • Reads higher-timeframe data with lookahead on, so the history can show signals that were not there in real time

Settings

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

SettingTypeDefaultVariable
Execution TypestringFVGexecutionType
Higher Timeframestring240htfPeriod
MSS Swing Lengthint10mssOffset
Breakout MethodstringWickbreakoutMethod
FVG DetectionstringSame TypefvgBars
fvgSensEnabledbooltruefvgSensEnabled
FVG Detection SensitivitystringExtremefvgSensitivityText
FVG EntrystringAlongFVG Entry
Show SessionsbooltrueshowSessions
Highs / LowsboolfalseshowHL
FVGsbooltrueshowFVGs
TP / SLbooltrueshowTPSL
Show all 40 settings
SettingTypeDefaultVariable
Order BlocksbooltrueshowOB
Breaker BlocksbooltrueshowBB
Break of StructurebooltrueshowBOS
Equal Highs/LowsbooltrueshowEQHL
Daily BiasstringNonedailyBias
Higher TF LiquiditybooltrueuseHigherTFliq
Require DisplacementbooltruerequireDisplacement
Order Block ConfluencebooltruerequireOBConfluence
Volume FilterbooltruevolumeFilter
BOS Lookbackint10bos_lookback
EQ H/L Threshold %float0.05eqhl_threshold
Require CHoCHbooltruechoch_confirmation
Order Block Lookbackint20ob_lookback
Breaker Block Confirmationbooltruebb_confirmation
MSIP Buffer ATR Multiplierfloat0.2msip_buffer
TP / SL MethodstringDynamictpslMethod
RiskstringNormalriskAmount
Take Profit %float0.3tpPercent
Stop Loss %float0.4slPercent
Close Position @ Session EndbooltrueclosePositionAtEndSession
Use Partial Take ProfitsbooltruepartialTP
Use Trailing StopbooltruetrailingStop
Risk:Reward Ratiofloat0.99Risk:Reward Ratio
[DBG] Require FVG Retracementbooltrue[DBG] Require FVG Retracement
Must Execute Inside SessionbooltrueMust Execute Inside Session
NY 1booltrueNY 1
NY 2booltrueNY 2
LondonbooltrueLondon
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

Golden Bullet Strategy

by TradersPost
218 stars

The Golden Bullet Strategy is an overlay signal indicator based on Smart Money Concepts and time-based liquidity models. It identifies liquidity sweeps of a designated reference session range during a specified hunt window. It then confirms Market Structure Sh

Indicator v6 SMC / ICT / price actionSessions & time
Updated 3 months ago · None stated GitHub repository of Golden Bullet Strategy

This indicator detects and draws the first Fair Value Gap (FVG) that forms in each hourly session based on a selected lower timeframe, with specialized handling for Regular Trading Hours (RTH) confluence windows. It draws FVG range boxes, midpoint lines, hourl

Indicator v5 SMC / ICT / price actionSupport & resistance Repaints

This indicator combines six trading tools into a single chart overlay to optimize indicator limits. It calculates Bollinger Bands, projects weekend price boundaries, plots market structure elements like order blocks, breaker blocks, and MSB lines, marks New Yo

Indicator v6 Support & resistanceSMC / ICT / price action Repaints
19 stars

This indicator highlights Inner Circle Trader (ICT) killzones and key session pivot points directly on the price chart. It projects shaded boxes for specific trading sessions, including Asia, London, NY AM, NY Lunch, and NY PM, to help traders identify high-li

Indicator v5 SMC / ICT / price actionSessions & time
Updated 3 years ago · MIT GitHub repository of ICT Killzones & Pivots

Bandz Session Ranges + ORG + Opening Prices plots trading session ranges, killzones, opening RTH gaps, standard deviation projections, and key opening prices directly on the price chart. It calculates gap ranges based on prior regular trading hours close sourc

Indicator v6 Sessions & timeSupport & resistance
Updated 2 weeks ago · MPL-2.0 GitHub repository of Bandz Session Ranges + ORG + Opening Prices

More indicators

Trade Your Charts With a Regulated Broker

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

Compare brokers