//@version=5 indicator("Session Range & Advanced Analysis Tools", overlay=true, max_boxes_count=150, max_lines_count=500, max_labels_count=100) // ============================================================================ // INPUT PARAMETERS // ============================================================================ // Session Settings sessionStartHour = input.int(7, "Session Start Hour", minval=0, maxval=23) sessionStartMinute = input.int(30, "Session Start Minute", minval=0, maxval=59) sessionEndHour = input.int(10, "Session End Hour", minval=0, maxval=23) sessionEndMinute = input.int(0, "Session End Minute", minval=0, maxval=59) extendLines = input(true, "Extend Lines") rangeOpacity = input.int(80, "Range Box Opacity", minval=0, maxval=100) showLabels = input(true, "Show Labels") maxBarsExtend = input.int(50, "Max Bars to Extend", minval=10, maxval=200) // Moving Averages showMA = input.bool(true, "Show Moving Averages", group="Moving Averages") ma1_length = input.int(21, "MA1 Length", minval=1, group="Moving Averages") ma2_length = input.int(50, "MA2 Length", minval=1, group="Moving Averages") ma3_length = input.int(200, "MA3 Length", minval=1, group="Moving Averages") ma_type = input.string("EMA", "MA Type", options=["SMA", "EMA", "WMA"], group="Moving Averages") // RSI Settings showRSI = input.bool(true, "Show RSI Levels", group="RSI") rsi_length = input.int(14, "RSI Length", minval=1, group="RSI") rsi_overbought = input.float(70.0, "RSI Overbought", group="RSI") rsi_oversold = input.float(30.0, "RSI Oversold", group="RSI") show_rsi_divergence = input.bool(true, "Show RSI Divergence", group="RSI") divergence_lookback = input.int(5, "Divergence Lookback", minval=3, maxval=20, group="RSI") // VWAP Settings showVWAP = input.bool(true, "Show VWAP", group="VWAP") vwap_bands = input.bool(true, "Show VWAP Bands", group="VWAP") vwap_std_dev = input.float(2.0, "VWAP Standard Deviation", group="VWAP") // Volume Profile showVP = input.bool(true, "Show Volume at Session Levels", group="Volume") min_volume_multiplier = input.float(1.3, "Min Volume Multiplier for Signals", minval=1.0, maxval=3.0, step=0.1, group="Volume") // Support/Resistance showSR = input.bool(true, "Show Key S/R Levels", group="Support/Resistance") lookback_period = input.int(20, "S/R Lookback Period", minval=5, group="Support/Resistance") max_sr_lines = input.int(20, "Max S/R Lines", minval=5, maxval=50, group="Support/Resistance") // ATR Settings use_atr_threshold = input.bool(true, "Use ATR-Based Thresholds", group="Advanced") atr_length = input.int(14, "ATR Length", minval=1, group="Advanced") atr_multiplier = input.float(0.5, "ATR Threshold Multiplier", minval=0.1, maxval=5.0, step=0.1, group="Advanced") // Confluence Settings min_confluence_score = input.int(70, "Minimum Confluence Score", minval=0, maxval=100, group="Advanced") show_confluence_score = input.bool(true, "Show Confluence Score", group="Advanced") // Multi-Timeframe enable_mtf_filter = input.bool(true, "Enable MTF Trend Filter", group="Multi-Timeframe") htf_timeframe = input.timeframe("60", "Higher Timeframe", group="Multi-Timeframe") // Risk Management show_risk_levels = input.bool(true, "Show Risk Levels", group="Risk Management") risk_reward_ratio = input.float(2.0, "Risk/Reward Ratio", minval=1.0, maxval=10.0, step=0.5, group="Risk Management") atr_stop_multiplier = input.float(1.5, "ATR Stop Loss Multiplier", minval=0.5, maxval=5.0, step=0.1, group="Risk Management") // Multiple Sessions enable_multi_sessions = input.bool(false, "Enable Multiple Sessions", group="Sessions") asian_start_hour = input.int(0, "Asian Start Hour", minval=0, maxval=23, group="Sessions") asian_end_hour = input.int(8, "Asian End Hour", minval=0, maxval=23, group="Sessions") london_start_hour = input.int(8, "London Start Hour", minval=0, maxval=23, group="Sessions") london_end_hour = input.int(16, "London End Hour", minval=0, maxval=23, group="Sessions") ny_start_hour = input.int(13, "NY Start Hour", minval=0, maxval=23, group="Sessions") ny_end_hour = input.int(22, "NY End Hour", minval=0, maxval=23, group="Sessions") // Liquidity Zones show_liquidity_zones = input.bool(true, "Show Liquidity Zones", group="Liquidity") liquidity_lookback = input.int(50, "Liquidity Lookback", minval=20, maxval=200, group="Liquidity") // Order Blocks show_order_blocks = input.bool(true, "Show Order Blocks", group="Order Blocks") ob_lookback = input.int(10, "Order Block Lookback", minval=3, maxval=30, group="Order Blocks") // Fair Value Gaps show_fvg = input.bool(true, "Show Fair Value Gaps", group="Fair Value Gaps") fvg_min_size = input.float(0.5, "Min FVG Size (ATR Multiple)", minval=0.1, maxval=3.0, step=0.1, group="Fair Value Gaps") // FALSE POSITIVE FILTERS enable_filters = input.bool(true, "Enable False Positive Filters", group="Filters") require_structure_break = input.bool(true, "Require Structure Break", group="Filters") require_candle_close_confirm = input.bool(true, "Require Candle Close Confirmation", group="Filters") filter_choppy_markets = input.bool(true, "Filter Choppy Markets (ADX)", group="Filters") adx_threshold = input.float(20.0, "Min ADX for Trend", minval=10.0, maxval=40.0, step=1.0, group="Filters") require_htf_alignment = input.bool(true, "Require HTF Trend Alignment", group="Filters") min_bars_since_signal = input.int(5, "Min Bars Between Signals", minval=1, maxval=20, group="Filters") // ============================================================================ // INPUT VALIDATION // ============================================================================ sessionStart = sessionStartHour * 60 + sessionStartMinute sessionEnd = sessionEndHour * 60 + sessionEndMinute if sessionStart >= sessionEnd runtime.error("Session start must be before session end") if risk_reward_ratio < 1 runtime.error("Risk/Reward ratio should be >= 1") // ============================================================================ // HELPER FUNCTIONS // ============================================================================ // Check if two prices are near each other within a threshold isNear(price1, price2, threshold) => math.abs(price1 - price2) / price1 < threshold // Calculate dynamic threshold based on ATR calculateDynamicThreshold(useATR, atrValue, multiplier, defaultValue) => useATR ? atrValue * multiplier / close : defaultValue // ============================================================================ // COLORS // ============================================================================ rangeColor = color.new(color.blue, 70) ma1_color = color.new(color.orange, 0) ma2_color = color.new(color.purple, 0) ma3_color = color.new(color.red, 0) vwap_color = color.new(color.yellow, 0) vwap_band_color = color.new(color.yellow, 80) sr_color = color.new(color.gray, 40) // ============================================================================ // SESSION TRACKING // ============================================================================ currentTimeMinutes = hour * 60 + minute isInSession = currentTimeMinutes >= sessionStart and currentTimeMinutes <= sessionEnd // Variables to store session data with proper initialization var float sessionHigh = float(na) var float sessionLow = float(na) var int sessionStartBar = na var int sessionEndBar = na var bool newSession = false var float sessionVWAP_numerator = 0.0 var float sessionVWAP_denominator = 0.0 var float sessionVWAP = float(na) // Detect new session start/end sessionJustStarted = not isInSession[1] and isInSession sessionJustEnded = isInSession[1] and not isInSession // Reset session values on new session if sessionJustStarted sessionHigh := high sessionLow := low sessionStartBar := bar_index newSession := true sessionVWAP_numerator := 0.0 sessionVWAP_denominator := 0.0 else newSession := false // Update session high/low and VWAP during session (IMPROVED) if isInSession if high > sessionHigh sessionHigh := high if low < sessionLow sessionLow := low // Calculate session VWAP with proper accumulation typical_price = hlc3 sessionVWAP_numerator += (typical_price * volume) sessionVWAP_denominator += volume // Calculate final VWAP on session end if sessionJustEnded sessionEndBar := bar_index - 1 sessionVWAP := sessionVWAP_denominator > 0 ? sessionVWAP_numerator / sessionVWAP_denominator : close // ============================================================================ // ATR & VOLATILITY // ============================================================================ atr = ta.atr(atr_length) dynamic_threshold = calculateDynamicThreshold(use_atr_threshold, atr, atr_multiplier, 0.001) // ADX for trend strength (filter choppy markets) [diPlus, diMinus, adx] = ta.dmi(14, 14) is_trending = adx > adx_threshold is_choppy = not is_trending // ============================================================================ // MULTI-TIMEFRAME ANALYSIS (IMPROVED) // ============================================================================ htf_ma = request.security(syminfo.tickerid, htf_timeframe, ta.ema(close, 50), lookahead=barmerge.lookahead_off) htf_close = request.security(syminfo.tickerid, htf_timeframe, close, lookahead=barmerge.lookahead_off) htf_trend_up = htf_close > htf_ma htf_trend_down = htf_close < htf_ma htf_trend_color = htf_trend_up ? color.new(color.green, 90) : color.new(color.red, 90) // Plot HTF trend background bgcolor(enable_mtf_filter ? htf_trend_color : na, title="HTF Trend") // ============================================================================ // MOVING AVERAGES // ============================================================================ ma_function(src, length, type) => switch type "SMA" => ta.sma(src, length) "EMA" => ta.ema(src, length) "WMA" => ta.wma(src, length) => ta.ema(src, length) ma1 = ma_function(close, ma1_length, ma_type) ma2 = ma_function(close, ma2_length, ma_type) ma3 = ma_function(close, ma3_length, ma_type) plot(showMA ? ma1 : na, "MA1", color=ma1_color, linewidth=2) plot(showMA ? ma2 : na, "MA2", color=ma2_color, linewidth=2) plot(showMA ? ma3 : na, "MA3", color=ma3_color, linewidth=3) // ============================================================================ // RSI & DIVERGENCE // ============================================================================ rsi = ta.rsi(close, rsi_length) rsi_bull_signal = rsi < rsi_oversold and rsi[1] >= rsi_oversold rsi_bear_signal = rsi > rsi_overbought and rsi[1] <= rsi_overbought // RSI DIVERGENCE DETECTION // Regular Bullish: Price lower low + RSI higher low = Reversal signal // Hidden Bullish: Price higher low + RSI lower low = Continuation signal // Regular Bearish: Price higher high + RSI lower high = Reversal signal // Hidden Bearish: Price lower high + RSI higher high = Continuation signal var float prev_price_low = float(na) var float prev_rsi_low = float(na) var float prev_price_high = float(na) var float prev_rsi_high = float(na) var int prev_low_bar = na var int prev_high_bar = na pivot_rsi_low = ta.pivotlow(rsi, divergence_lookback, divergence_lookback) pivot_rsi_high = ta.pivothigh(rsi, divergence_lookback, divergence_lookback) pivot_price_low = ta.pivotlow(low, divergence_lookback, divergence_lookback) pivot_price_high = ta.pivothigh(high, divergence_lookback, divergence_lookback) bullish_divergence = false bearish_divergence = false if not na(pivot_rsi_low) and not na(pivot_price_low) if not na(prev_rsi_low) and not na(prev_price_low) // Regular Bullish Divergence if pivot_price_low < prev_price_low and pivot_rsi_low > prev_rsi_low bullish_divergence := true // Hidden Bullish Divergence if pivot_price_low > prev_price_low and pivot_rsi_low < prev_rsi_low bullish_divergence := true prev_rsi_low := pivot_rsi_low prev_price_low := pivot_price_low prev_low_bar := bar_index - divergence_lookback if not na(pivot_rsi_high) and not na(pivot_price_high) if not na(prev_rsi_high) and not na(prev_price_high) // Regular Bearish Divergence if pivot_price_high > prev_price_high and pivot_rsi_high < prev_rsi_high bearish_divergence := true // Hidden Bearish Divergence if pivot_price_high < prev_price_high and pivot_rsi_high > prev_rsi_high bearish_divergence := true prev_rsi_high := pivot_rsi_high prev_price_high := pivot_price_high prev_high_bar := bar_index - divergence_lookback // Plot RSI signals plotshape(showRSI and rsi_bull_signal, "RSI Oversold Signal", shape.triangleup, location.belowbar, color.new(color.green, 0), size=size.small) plotshape(showRSI and rsi_bear_signal, "RSI Overbought Signal", shape.triangledown, location.abovebar, color.new(color.red, 0), size=size.small) // Plot RSI Divergence plotshape(show_rsi_divergence and bullish_divergence, "Bullish Divergence", shape.circle, location.belowbar, color.new(color.aqua, 0), size=size.normal, text="DIV") plotshape(show_rsi_divergence and bearish_divergence, "Bearish Divergence", shape.circle, location.abovebar, color.new(color.orange, 0), size=size.normal, text="DIV") // ============================================================================ // VWAP // ============================================================================ vwap_value = ta.vwap(hlc3) vwap_dev = ta.stdev(hlc3, 20) vwap_upper = vwap_value + vwap_std_dev * vwap_dev vwap_lower = vwap_value - vwap_std_dev * vwap_dev plot(showVWAP ? vwap_value : na, "VWAP", color=vwap_color, linewidth=2) plot(showVWAP and vwap_bands ? vwap_upper : na, "VWAP Upper", color=vwap_band_color, linewidth=1) plot(showVWAP and vwap_bands ? vwap_lower : na, "VWAP Lower", color=vwap_band_color, linewidth=1) fill(plot(showVWAP and vwap_bands ? vwap_upper : na), plot(showVWAP and vwap_bands ? vwap_lower : na), color=color.new(vwap_band_color, 90)) // ============================================================================ // PIVOT CALCULATIONS (Used by S/R, Confluence, and Liquidity) // ============================================================================ float pivot_high = ta.pivothigh(high, lookback_period, lookback_period) float pivot_low = ta.pivotlow(low, lookback_period, lookback_period) // ============================================================================ // SUPPORT/RESISTANCE LEVELS // ============================================================================ var line[] sr_lines = array.new_line() // Draw S/R lines with automatic cleanup if showSR and not na(pivot_high) if array.size(sr_lines) >= max_sr_lines line oldest_line = array.shift(sr_lines) line.delete(oldest_line) line new_line = line.new(bar_index - lookback_period, pivot_high, bar_index + maxBarsExtend, pivot_high, extend=extend.right, color=sr_color, style=line.style_dotted, width=1) array.push(sr_lines, new_line) if showSR and not na(pivot_low) if array.size(sr_lines) >= max_sr_lines line oldest_line = array.shift(sr_lines) line.delete(oldest_line) line new_line = line.new(bar_index - lookback_period, pivot_low, bar_index + maxBarsExtend, pivot_low, extend=extend.right, color=sr_color, style=line.style_dotted, width=1) array.push(sr_lines, new_line) // ============================================================================ // VOLUME ANALYSIS (IMPROVED) // ============================================================================ avg_volume = ta.sma(volume, 20) high_volume = volume > avg_volume * min_volume_multiplier volume_color = high_volume ? color.new(color.orange, 60) : color.new(color.gray, 80) bgcolor(showVP and high_volume ? volume_color : na) // ============================================================================ // ORDER BLOCKS DETECTION (NEW) // ============================================================================ var box[] bullish_ob_boxes = array.new_box() var box[] bearish_ob_boxes = array.new_box() if show_order_blocks // Bullish Order Block: Last down candle before strong bullish move strong_bull_move = close > high[3] and volume > avg_volume * 1.2 and close > open if strong_bull_move for i = 1 to ob_lookback if close[i] < open[i] // Found bearish candle // Limit boxes if array.size(bullish_ob_boxes) >= 20 old_box = array.shift(bullish_ob_boxes) box.delete(old_box) new_box = box.new(bar_index - i, high[i], bar_index + 20, low[i], border_color=color.new(color.green, 70), bgcolor=color.new(color.green, 90), extend=extend.right) array.push(bullish_ob_boxes, new_box) break // Bearish Order Block: Last up candle before strong bearish move strong_bear_move = close < low[3] and volume > avg_volume * 1.2 and close < open if strong_bear_move for i = 1 to ob_lookback if close[i] > open[i] // Found bullish candle // Limit boxes if array.size(bearish_ob_boxes) >= 20 old_box = array.shift(bearish_ob_boxes) box.delete(old_box) new_box = box.new(bar_index - i, high[i], bar_index + 20, low[i], border_color=color.new(color.red, 70), bgcolor=color.new(color.red, 90), extend=extend.right) array.push(bearish_ob_boxes, new_box) break // ============================================================================ // FAIR VALUE GAPS DETECTION (NEW) // ============================================================================ var box[] bullish_fvg_boxes = array.new_box() var box[] bearish_fvg_boxes = array.new_box() // Bullish FVG: Gap between high[2] and low[0], with bullish candle[1] bullish_fvg = show_fvg and low > high[2] and close[1] > open[1] and (low - high[2]) > (atr * fvg_min_size) // Bearish FVG: Gap between low[2] and high[0], with bearish candle[1] bearish_fvg = show_fvg and high < low[2] and close[1] < open[1] and (low[2] - high) > (atr * fvg_min_size) if bullish_fvg // Limit boxes if array.size(bullish_fvg_boxes) >= 30 old_box = array.shift(bullish_fvg_boxes) box.delete(old_box) new_box = box.new(bar_index - 2, high[2], bar_index + 20, low, border_color=color.new(color.aqua, 60), bgcolor=color.new(color.aqua, 92), extend=extend.right) array.push(bullish_fvg_boxes, new_box) if bearish_fvg // Limit boxes if array.size(bearish_fvg_boxes) >= 30 old_box = array.shift(bearish_fvg_boxes) box.delete(old_box) new_box = box.new(bar_index - 2, high, bar_index + 20, low[2], border_color=color.new(color.orange, 60), bgcolor=color.new(color.orange, 92), extend=extend.right) array.push(bearish_fvg_boxes, new_box) // ============================================================================ // SESSION RANGE DRAWING // ============================================================================ if sessionJustEnded and not na(sessionHigh) and not na(sessionLow) and not na(sessionStartBar) box.new(sessionStartBar, sessionHigh, sessionEndBar, sessionLow, border_color=rangeColor, bgcolor=color.new(rangeColor, rangeOpacity), extend=extend.none) if showLabels label.new(sessionEndBar, sessionHigh, "SH: " + str.tostring(sessionHigh, "#.####"), style=label.style_label_lower_left, color=color.blue, textcolor=color.white, size=size.small) label.new(sessionEndBar, sessionLow, "SL: " + str.tostring(sessionLow, "#.####"), style=label.style_label_upper_left, color=color.blue, textcolor=color.white, size=size.small) if not na(sessionVWAP) label.new(sessionEndBar, sessionVWAP, "SVWAP: " + str.tostring(sessionVWAP, "#.####"), style=label.style_label_left, color=color.yellow, textcolor=color.black, size=size.small) // Draw extending lines for current session var line currentHighLine = na var line currentLowLine = na var line sessionVWAPLine = na if extendLines and not na(sessionHigh) and not na(sessionLow) if newSession if not na(currentHighLine) line.delete(currentHighLine) if not na(currentLowLine) line.delete(currentLowLine) if not na(sessionVWAPLine) line.delete(sessionVWAPLine) if isInSession or sessionJustEnded if not na(currentHighLine) line.delete(currentHighLine) if not na(currentLowLine) line.delete(currentLowLine) if not na(sessionVWAPLine) line.delete(sessionVWAPLine) extendType = sessionJustEnded ? extend.right : extend.none endBar = sessionJustEnded ? bar_index + maxBarsExtend : bar_index currentHighLine := line.new(bar_index, sessionHigh, endBar, sessionHigh, extend=extendType, color=color.new(color.blue, 20), style=line.style_dashed, width=2) currentLowLine := line.new(bar_index, sessionLow, endBar, sessionLow, extend=extendType, color=color.new(color.blue, 20), style=line.style_dashed, width=2) if sessionJustEnded and not na(sessionVWAP) sessionVWAPLine := line.new(sessionEndBar, sessionVWAP, bar_index + maxBarsExtend, sessionVWAP, extend=extend.right, color=color.new(color.yellow, 30), style=line.style_solid, width=2) // ============================================================================ // STRUCTURE BREAK DETECTION (NEW - False Positive Filter) // ============================================================================ var float last_swing_high = float(na) var float last_swing_low = float(na) var int bars_since_high_break = 999 var int bars_since_low_break = 999 // Update swing points if not na(pivot_high) last_swing_high := pivot_high if not na(pivot_low) last_swing_low := pivot_low // Detect structure breaks bullish_structure_break = false bearish_structure_break = false if not na(last_swing_high) and close > last_swing_high bullish_structure_break := true bars_since_high_break := 0 else bars_since_high_break += 1 if not na(last_swing_low) and close < last_swing_low bearish_structure_break := true bars_since_low_break := 0 else bars_since_low_break += 1 // Check if structure was recently broken recent_bullish_break = bars_since_high_break < 10 recent_bearish_break = bars_since_low_break < 10 // ============================================================================ // LIQUIDITY ZONES DETECTION (IMPROVED - OPTIMIZED) // ============================================================================ var float[] recent_highs = array.new_float() var float[] recent_lows = array.new_float() var int[] high_bars = array.new_int() var int[] low_bars = array.new_int() // Store recent pivot highs and lows if not na(pivot_high) if array.size(recent_highs) >= 10 array.shift(recent_highs) array.shift(high_bars) array.push(recent_highs, pivot_high) array.push(high_bars, bar_index - lookback_period) if not na(pivot_low) if array.size(recent_lows) >= 10 array.shift(recent_lows) array.shift(low_bars) array.push(recent_lows, pivot_low) array.push(low_bars, bar_index - lookback_period) // Detect liquidity sweeps (OPTIMIZED) liquidity_grab_up = false liquidity_grab_down = false high_swept = false low_swept = false // Only check if there's significant movement if array.size(recent_highs) > 0 and high > high[1] for i = array.size(recent_highs) - 1 to 0 prev_high = array.get(recent_highs, i) if high > prev_high * 1.001 // Small buffer to avoid noise high_swept := true if close < prev_high liquidity_grab_up := true break if not high_swept and array.size(recent_lows) > 0 and low < low[1] for i = array.size(recent_lows) - 1 to 0 prev_low = array.get(recent_lows, i) if low < prev_low * 0.999 low_swept := true if close > prev_low liquidity_grab_down := true break plotshape(show_liquidity_zones and liquidity_grab_up, "Liquidity Grab Up", shape.xcross, location.abovebar, color.new(color.yellow, 0), size=size.tiny, text="LQ") plotshape(show_liquidity_zones and liquidity_grab_down, "Liquidity Grab Down", shape.xcross, location.belowbar, color.new(color.yellow, 0), size=size.tiny, text="LQ") // ============================================================================ // MULTIPLE SESSIONS SUPPORT (FIXED - Memory optimized) // ============================================================================ var float asianHigh = float(na) var float asianLow = float(na) var float londonHigh = float(na) var float londonLow = float(na) var float nyHigh = float(na) var float nyLow = float(na) var int last_asian_end_bar = na var int last_london_end_bar = na var int last_ny_end_bar = na if enable_multi_sessions isAsianSession = hour >= asian_start_hour and hour < asian_end_hour isLondonSession = hour >= london_start_hour and hour < london_end_hour isNYSession = hour >= ny_start_hour and hour < ny_end_hour asianSessionEnded = not isAsianSession and isAsianSession[1] londonSessionEnded = not isLondonSession and isLondonSession[1] nySessionEnded = not isNYSession and isNYSession[1] // Track Asian session if isAsianSession if na(asianHigh) or high > asianHigh asianHigh := high if na(asianLow) or low < asianLow asianLow := low else if asianSessionEnded and bar_index != last_asian_end_bar line.new(bar_index - 1, asianHigh, bar_index + 20, asianHigh, color=color.new(color.blue, 50), style=line.style_dotted, width=1) line.new(bar_index - 1, asianLow, bar_index + 20, asianLow, color=color.new(color.blue, 50), style=line.style_dotted, width=1) last_asian_end_bar := bar_index asianHigh := float(na) asianLow := float(na) // Track London session if isLondonSession if na(londonHigh) or high > londonHigh londonHigh := high if na(londonLow) or low < londonLow londonLow := low else if londonSessionEnded and bar_index != last_london_end_bar line.new(bar_index - 1, londonHigh, bar_index + 20, londonHigh, color=color.new(color.orange, 50), style=line.style_dotted, width=1) line.new(bar_index - 1, londonLow, bar_index + 20, londonLow, color=color.new(color.orange, 50), style=line.style_dotted, width=1) last_london_end_bar := bar_index londonHigh := float(na) londonLow := float(na) // Track NY session if isNYSession if na(nyHigh) or high > nyHigh nyHigh := high if na(nyLow) or low < nyLow nyLow := low else if nySessionEnded and bar_index != last_ny_end_bar line.new(bar_index - 1, nyHigh, bar_index + 20, nyHigh, color=color.new(color.purple, 50), style=line.style_dotted, width=1) line.new(bar_index - 1, nyLow, bar_index + 20, nyLow, color=color.new(color.purple, 50), style=line.style_dotted, width=1) last_ny_end_bar := bar_index nyHigh := float(na) nyLow := float(na) // ============================================================================ // CONFLUENCE DETECTION WITH IMPROVED SCORING // ============================================================================ threshold = use_atr_threshold ? dynamic_threshold : 0.001 // Individual confluence factors near_session_high = not na(sessionHigh) and isNear(close, sessionHigh, atr / sessionHigh) near_session_low = not na(sessionLow) and isNear(close, sessionLow, atr / sessionLow) near_vwap = isNear(close, vwap_value, threshold) near_ma1 = isNear(close, ma1, threshold) near_ma2 = isNear(close, ma2, threshold) near_ma3 = isNear(close, ma3, threshold) at_sr_level = not na(pivot_high) or not na(pivot_low) // Calculate confluence score (0-100) bullish_score = 0 bearish_score = 0 // Bullish scoring if near_session_low bullish_score += 20 if near_vwap and close < vwap_value bullish_score += 15 if near_ma1 and close < ma1 bullish_score += 10 if near_ma2 and close < ma2 bullish_score += 10 if near_ma3 and close < ma3 bullish_score += 5 if rsi < 30 bullish_score += 20 else if rsi < 40 bullish_score += 10 if high_volume bullish_score += 10 if bullish_divergence bullish_score += 15 if enable_mtf_filter and htf_trend_up bullish_score += 10 if bullish_fvg bullish_score += 10 if liquidity_grab_down bullish_score += 15 // Bearish scoring if near_session_high bearish_score += 20 if near_vwap and close > vwap_value bearish_score += 15 if near_ma1 and close > ma1 bearish_score += 10 if near_ma2 and close > ma2 bearish_score += 10 if near_ma3 and close > ma3 bearish_score += 5 if rsi > 70 bearish_score += 20 else if rsi > 60 bearish_score += 10 if high_volume bearish_score += 10 if bearish_divergence bearish_score += 15 if enable_mtf_filter and htf_trend_down bearish_score += 10 if bearish_fvg bearish_score += 10 if liquidity_grab_up bearish_score += 15 // ============================================================================ // FALSE POSITIVE FILTERS (NEW) // ============================================================================ // Track last signal bar to prevent spam var int last_bull_signal_bar = na var int last_bear_signal_bar = na // Calculate bars since last signal bars_since_bull_signal = na(last_bull_signal_bar) ? 999 : bar_index - last_bull_signal_bar bars_since_bear_signal = na(last_bear_signal_bar) ? 999 : bar_index - last_bear_signal_bar // Apply filters bullish_filters_passed = true bearish_filters_passed = true if enable_filters // Filter 1: Require HTF alignment if require_htf_alignment and enable_mtf_filter if not htf_trend_up bullish_filters_passed := false if not htf_trend_down bearish_filters_passed := false // Filter 2: Filter choppy markets if filter_choppy_markets and is_choppy bullish_filters_passed := false bearish_filters_passed := false // Filter 3: Require structure break if require_structure_break if not recent_bullish_break bullish_filters_passed := false if not recent_bearish_break bearish_filters_passed := false // Filter 4: Require candle close confirmation if require_candle_close_confirm bullish_candle = close > open bearish_candle = close < open if not bullish_candle bullish_filters_passed := false if not bearish_candle bearish_filters_passed := false // Filter 5: Min bars between signals if bars_since_bull_signal < min_bars_since_signal bullish_filters_passed := false if bars_since_bear_signal < min_bars_since_signal bearish_filters_passed := false // Filter 6: Require minimum volume if not high_volume bullish_filters_passed := false bearish_filters_passed := false // Generate signals based on minimum score AND filters confluence_bull = bullish_score >= min_confluence_score and bullish_filters_passed confluence_bear = bearish_score >= min_confluence_score and bearish_filters_passed // Update last signal bars if confluence_bull last_bull_signal_bar := bar_index if confluence_bear last_bear_signal_bar := bar_index // Color code by strength bull_color = bullish_score >= 90 ? color.new(color.lime, 0) : bullish_score >= 80 ? color.new(color.green, 0) : bullish_score >= 70 ? color.new(color.green, 30) : color.new(color.green, 50) bear_color = bearish_score >= 90 ? color.new(color.fuchsia, 0) : bearish_score >= 80 ? color.new(color.red, 0) : bearish_score >= 70 ? color.new(color.red, 30) : color.new(color.red, 50) plotshape(confluence_bull, "Bullish Confluence", shape.diamond, location.belowbar, bull_color, size=size.normal) plotshape(confluence_bear, "Bearish Confluence", shape.diamond, location.abovebar, bear_color, size=size.normal) // ============================================================================ // RISK MANAGEMENT MODULE // ============================================================================ atr_stop = atr * atr_stop_multiplier // For bullish setups bull_stop_loss = close - atr_stop bull_take_profit = close + (atr_stop * risk_reward_ratio) bull_risk_reward = (bull_take_profit - close) / (close - bull_stop_loss) // For bearish setups bear_stop_loss = close + atr_stop bear_take_profit = close - (atr_stop * risk_reward_ratio) bear_risk_reward = (close - bear_take_profit) / (bear_stop_loss - close) // Plot risk levels for active signals var line bull_sl_line = na var line bull_tp_line = na var line bear_sl_line = na var line bear_tp_line = na var label bull_risk_label = na var label bear_risk_label = na if show_risk_levels and confluence_bull if not na(bull_sl_line) line.delete(bull_sl_line) if not na(bull_tp_line) line.delete(bull_tp_line) if not na(bull_risk_label) label.delete(bull_risk_label) bull_sl_line := line.new(bar_index, bull_stop_loss, bar_index + 10, bull_stop_loss, color=color.new(color.red, 30), style=line.style_dashed, width=2) bull_tp_line := line.new(bar_index, bull_take_profit, bar_index + 10, bull_take_profit, color=color.new(color.green, 30), style=line.style_dashed, width=2) risk_text = "SL: " + str.tostring(bull_stop_loss, "#.####") + "\nTP: " + str.tostring(bull_take_profit, "#.####") + "\nR:R " + str.tostring(risk_reward_ratio, "#.#") + "\nScore: " + str.tostring(bullish_score) bull_risk_label := label.new(bar_index, bull_take_profit, risk_text, style=label.style_label_down, color=color.green, textcolor=color.white, size=size.small) if show_risk_levels and confluence_bear if not na(bear_sl_line) line.delete(bear_sl_line) if not na(bear_tp_line) line.delete(bear_tp_line) if not na(bear_risk_label) label.delete(bear_risk_label) bear_sl_line := line.new(bar_index, bear_stop_loss, bar_index + 10, bear_stop_loss, color=color.new(color.red, 30), style=line.style_dashed, width=2) bear_tp_line := line.new(bar_index, bear_take_profit, bar_index + 10, bear_take_profit, color=color.new(color.green, 30), style=line.style_dashed, width=2) risk_text = "SL: " + str.tostring(bear_stop_loss, "#.####") + "\nTP: " + str.tostring(bear_take_profit, "#.####") + "\nR:R " + str.tostring(risk_reward_ratio, "#.#") + "\nScore: " + str.tostring(bearish_score) bear_risk_label := label.new(bar_index, bear_take_profit, risk_text, style=label.style_label_up, color=color.red, textcolor=color.white, size=size.small) // ============================================================================ // TREND STRENGTH INDICATOR // ============================================================================ ma_aligned_bullish = close > ma1 and ma1 > ma2 and ma2 > ma3 ma_aligned_bearish = close < ma1 and ma1 < ma2 and ma2 < ma3 trend_strength = 0 if ma_aligned_bullish trend_strength := close > ma1 ? 3 : 2 else if ma_aligned_bearish trend_strength := close < ma1 ? -3 : -2 else if close > ma1 trend_strength := 1 else if close < ma1 trend_strength := -1 trend_strength_text = trend_strength >= 3 ? "Strong Bull" : trend_strength == 2 ? "Bullish" : trend_strength == 1 ? "Weak Bull" : trend_strength == -1 ? "Weak Bear" : trend_strength == -2 ? "Bearish" : "Strong Bear" trend_strength_color = trend_strength >= 2 ? color.new(color.green, 0) : trend_strength >= 1 ? color.new(color.green, 50) : trend_strength <= -2 ? color.new(color.red, 0) : trend_strength <= -1 ? color.new(color.red, 50) : color.gray // ============================================================================ // ANALYSIS TABLE (IMPROVED) // ============================================================================ var table analysisTable = na if barstate.islast and showLabels if na(analysisTable) analysisTable := table.new(position.top_right, 2, 14, bgcolor=color.new(color.white, 10), border_width=1) // Update all cells table.cell(analysisTable, 0, 0, "Session High", text_color=color.white, bgcolor=color.new(color.blue, 50)) table.cell(analysisTable, 1, 0, str.tostring(sessionHigh, "#.####"), text_color=color.white, bgcolor=color.new(color.blue, 70)) table.cell(analysisTable, 0, 1, "Session Low", text_color=color.white, bgcolor=color.new(color.blue, 50)) table.cell(analysisTable, 1, 1, str.tostring(sessionLow, "#.####"), text_color=color.white, bgcolor=color.new(color.blue, 70)) table.cell(analysisTable, 0, 2, "Session VWAP", text_color=color.black, bgcolor=color.new(color.yellow, 50)) table.cell(analysisTable, 1, 2, str.tostring(sessionVWAP, "#.####"), text_color=color.black, bgcolor=color.new(color.yellow, 70)) table.cell(analysisTable, 0, 3, "RSI", text_color=color.white, bgcolor=color.new(color.gray, 50)) rsi_color = rsi > rsi_overbought ? color.red : rsi < rsi_oversold ? color.green : color.white table.cell(analysisTable, 1, 3, str.tostring(rsi, "#.##"), text_color=rsi_color, bgcolor=color.new(color.gray, 70)) table.cell(analysisTable, 0, 4, "ADX", text_color=color.white, bgcolor=color.new(color.gray, 50)) adx_color = is_trending ? color.green : color.orange table.cell(analysisTable, 1, 4, str.tostring(adx, "#.##"), text_color=adx_color, bgcolor=color.new(color.gray, 70)) table.cell(analysisTable, 0, 5, "VWAP", text_color=color.black, bgcolor=color.new(color.yellow, 50)) table.cell(analysisTable, 1, 5, str.tostring(vwap_value, "#.####"), text_color=color.black, bgcolor=color.new(color.yellow, 70)) table.cell(analysisTable, 0, 6, "MA1", text_color=color.white, bgcolor=color.new(color.orange, 50)) table.cell(analysisTable, 1, 6, str.tostring(ma1, "#.####"), text_color=color.white, bgcolor=color.new(color.orange, 70)) table.cell(analysisTable, 0, 7, "MA2", text_color=color.white, bgcolor=color.new(color.purple, 50)) table.cell(analysisTable, 1, 7, str.tostring(ma2, "#.####"), text_color=color.white, bgcolor=color.new(color.purple, 70)) table.cell(analysisTable, 0, 8, "Volume", text_color=color.white, bgcolor=color.new(color.gray, 50)) table.cell(analysisTable, 1, 8, high_volume ? "HIGH" : "NORMAL", text_color=high_volume ? color.orange : color.white, bgcolor=color.new(color.gray, 70)) table.cell(analysisTable, 0, 9, "Trend", text_color=color.white, bgcolor=trend_strength_color) table.cell(analysisTable, 1, 9, trend_strength_text, text_color=color.white, bgcolor=trend_strength_color) table.cell(analysisTable, 0, 10, "ATR", text_color=color.white, bgcolor=color.new(color.gray, 50)) table.cell(analysisTable, 1, 10, str.tostring(atr, "#.####"), text_color=color.white, bgcolor=color.new(color.gray, 70)) table.cell(analysisTable, 0, 11, "HTF Trend", text_color=color.white, bgcolor=color.new(color.gray, 50)) htf_text = htf_trend_up ? "BULLISH" : "BEARISH" htf_color = htf_trend_up ? color.green : color.red table.cell(analysisTable, 1, 11, htf_text, text_color=htf_color, bgcolor=color.new(color.gray, 70)) table.cell(analysisTable, 0, 12, "Bull Score", text_color=color.white, bgcolor=color.new(color.green, 50)) bull_score_color = bullish_score >= min_confluence_score ? color.lime : color.gray table.cell(analysisTable, 1, 12, str.tostring(bullish_score), text_color=bull_score_color, bgcolor=color.new(color.green, 70)) table.cell(analysisTable, 0, 13, "Bear Score", text_color=color.white, bgcolor=color.new(color.red, 50)) bear_score_color = bearish_score >= min_confluence_score ? color.orange : color.gray table.cell(analysisTable, 1, 13, str.tostring(bearish_score), text_color=bear_score_color, bgcolor=color.new(color.red, 70)) // ============================================================================ // ALERTS // ============================================================================ alertcondition(confluence_bull, title="Bullish Confluence", message="HIGH PROBABILITY Bullish Setup - Score: {{plot_0}}") alertcondition(confluence_bear, title="Bearish Confluence", message="HIGH PROBABILITY Bearish Setup - Score: {{plot_1}}") alertcondition(rsi_bull_signal, title="RSI Oversold", message="RSI moving out of oversold territory") alertcondition(rsi_bear_signal, title="RSI Overbought", message="RSI moving out of overbought territory") alertcondition(bullish_divergence, title="Bullish Divergence", message="RSI Bullish Divergence detected") alertcondition(bearish_divergence, title="Bearish Divergence", message="RSI Bearish Divergence detected") alertcondition(liquidity_grab_up or liquidity_grab_down, title="Liquidity Grab", message="Liquidity sweep detected") alertcondition(bullish_fvg, title="Bullish FVG", message="Bullish Fair Value Gap formed") alertcondition(bearish_fvg, title="Bearish FVG", message="Bearish Fair Value Gap formed")