SMC MD

Wait 5 sec.

SMC MDGOLD (US$/OZ)TVC:GOLDmohd89ronaldo//@version=5 indicator("Smart Money Concepts (SMC) Pro - Ultimate Edition", overlay=true, max_boxes_count=500, max_lines_count=500, max_labels_count=500) // ========================================== // --- USER INPUTS --- // ========================================== // Group: Market Structure Configuration show_structure = input.bool(true, "Show Market Structure (BOS/CHoCH)", group="Market Structure Settings") left_len = input.int(5, "Pivot Left Hand Strength", minval=1, group="Market Structure Settings", tooltip="Number of candles on the left of the pivot") right_len = input.int(5, "Pivot Right Hand Strength", minval=1, group="Market Structure Settings", tooltip="Number of candles on the right of the pivot") break_type = input.string("Close", "Structure Break Trigger", options=, group="Market Structure Settings", tooltip="Trigger structure breaks on candle body Close or Wick High/Low") show_swings = input.bool(true, "Label Swing Points (HH, LH, HL, LL)", group="Market Structure Settings") // Colors for Structure color_bull_structure = input.color(color.emerald, "Bullish Structure Color", group="Market Structure Settings") color_bear_structure = input.color(color.rose, "Bearish Structure Color", group="Market Structure Settings") // Group: Order Blocks & Supply/Demand Zones show_obs = input.bool(true, "Show Order Blocks (Supply/Demand)", group="Order Block Settings") ob_max_count = input.int(5, "Max Active OBs (Per Trend)", minval=1, maxval=20, group="Order Block Settings", tooltip="Controls maximum active boxes to avoid visual clutter") color_demand = input.color(color.new(color.emerald, 92), "Demand Zone Fill", group="Order Block Settings") color_demand_b = input.color(color.new(color.emerald, 40), "Demand Zone Border", group="Order Block Settings") color_supply = input.color(color.new(color.rose, 92), "Supply Zone Fill", group="Order Block Settings") color_supply_b = input.color(color.new(color.rose, 40), "Supply Zone Border", group="Order Block Settings") // Group: Fair Value Gaps (FVG) show_fvgs = input.bool(true, "Show Fair Value Gaps (FVG)", group="Fair Value Gaps Settings") fvg_threshold = input.float(0.5, "FVG Minimum Size (ATR Multiplier)", minval=0.0, step=0.1, group="Fair Value Gaps Settings", tooltip="Filters out insignificant/minor imbalances") fvg_mitigation = input.string("Full", "FVG Mitigation Logic", options=, group="Fair Value Gaps Settings", tooltip="Touch: Price enters FVG. Full: Price fills FVG range completely.") fvg_max_count = input.int(10, "Max Active FVGs", minval=1, maxval=50, group="Fair Value Gaps Settings") color_bull_fvg = input.color(color.new(color.teal, 92), "Bullish FVG Fill", group="Fair Value Gaps Settings") color_bear_fvg = input.color(color.new(color.orange, 92), "Bearish FVG Fill", group="Fair Value Gaps Settings") // Group: Liquidity Settings show_liquidity = input.bool(true, "Show Equal Highs/Lows (EQH/EQL)", group="Liquidity Settings") eq_threshold = input.float(0.1, "Equal Highs/Lows Threshold (%)", minval=0.01, maxval=1.0, step=0.05, group="Liquidity Settings", tooltip="Max percentage difference to classify as equal") show_sweeps = input.bool(true, "Identify Liquidity Sweeps (Grabs)", group="Liquidity Settings") color_liq = input.color(color.new(color.blue, 30), "Liquidity Line Color", group="Liquidity Settings") // Group: Order Flow & Trading Ranges show_pd_zones = input.bool(true, "Show Premium/Discount (Order Flow)", group="Order Flow Settings") // Group: Classical Support & Resistance Zones show_sr = input.bool(true, "Show S/R Zones", group="Support & Resistance Settings") sr_lookback = input.int(50, "S/R Lookback Depth", minval=20, group="Support & Resistance Settings") sr_touches = input.int(3, "Required Touches for S/R Check", minval=2, group="Support & Resistance Settings") color_support = input.color(color.new(color.blue, 92), "Support Zone Fill", group="Support & Resistance Settings") color_resistance= input.color(color.new(color.purple, 92), "Resistance Zone Fill", group="Support & Resistance Settings") // ========================================== // --- TECHNICAL CALCULATIONS --- // ========================================== atr = ta.atr(14) // Find Pivots for Structure Analysis pHigh = ta.pivothigh(high, left_len, right_len) pLow = ta.pivotlow(low, left_len, right_len) // Dynamic Structure States var float ph_price = na var int ph_bar = na var float pl_price = na var int pl_bar = na var float prev_ph_val = na var float prev_pl_val = na var string swing_high_type = na var string swing_low_type = na var float struct_high = na var float struct_low = na var string structure_trend = "none" // "bull" or "bear" // Initialize structural bounds on the first confirmed pivot if na(struct_high) and not na(pHigh) struct_high := pHigh if na(struct_low) and not na(pLow) struct_low := pLow // Track Pivot High and label swing point types if not na(pHigh) prev_ph_val := ph_price ph_price := pHigh ph_bar := bar_index - right_len if show_swings if na(prev_ph_val) swing_high_type := "H" else if ph_price > prev_ph_val swing_high_type := "HH" else swing_high_type := "LH" label.new( x=ph_bar, y=ph_price, text=swing_high_type, color=color.new(color.red, 100), textcolor=color.red, style=label.style_label_down, size=size.small ) // Track Pivot Low and label swing point types if not na(pLow) prev_pl_val := pl_price pl_price := pLow pl_bar := bar_index - right_len if show_swings if na(prev_pl_val) swing_low_type := "L" else if pl_price < prev_pl_val swing_low_type := "LL" else swing_low_type := "HL" label.new( x=pl_bar, y=pl_price, text=swing_low_type, color=color.new(color.green, 100), textcolor=color.green, style=label.style_label_up, size=size.small ) // ========================================== // --- DETECT BOS / CHOCH & ORDER BLOCKS --- // ========================================== bool break_up = false bool break_down = false if not na(struct_high) if break_type == "Close" break_up := close > struct_high else break_up := high > struct_high if not na(struct_low) if break_type == "Close" break_down := close < struct_low else break_down := low < struct_low var int last_break_up_bar = na var int last_break_down_bar = na // Storage for Order Blocks (Dynamic Array Management) var box bullish_ob_boxes = array.new_box() var box bearish_ob_boxes = array.new_box() // Bullish Break of Structure (BOS) or Change of Character (CHoCH) if break_up and bar_index != last_break_up_bar string break_label = "" color break_color = color_bull_structure if structure_trend == "none" or structure_trend == "bear" break_label := "CHoCH" structure_trend := "bull" else break_label := "BOS" if show_structure line.new( x1=bar_index - 1, y1=struct_high, x2=bar_index, y2=struct_high, color=break_color, width=1, style=line.style_dashed, extend=extend.none ) label.new( x=bar_index, y=struct_high, text=break_label, color=color.new(break_color, 90), textcolor=break_color, style=label.style_label_down, size=size.small ) // --- Create Bullish Order Block (Demand Zone) --- int ob_bar = bar_index float ob_top = na float ob_bottom = na // Scan backwards to find the last down-close candle that originated the push for i = 1 to 30 if close < open ob_bar := bar_index - i ob_top := high ob_bottom := low break if show_obs and not na(ob_top) if array.size(bullish_ob_boxes) >= ob_max_count box.delete(array.shift(bullish_ob_boxes)) box new_ob = box.new( left=ob_bar, top=ob_top, right=bar_index, bottom=ob_bottom, bgcolor=color_demand, border_color=color_demand_b, border_style=line.style_solid, text="Demand", text_color=color_demand_b, text_size=size.small, text_align=text.align_left, text_valign=text.valign_bottom ) array.push(bullish_ob_boxes, new_ob) // Reset structure parameters safely struct_high := na(pHigh) ? high : pHigh float lowest_since = low for i = 1 to math.min(100, bar_index - nz(last_break_down_bar, 0)) if low < lowest_since lowest_since := low struct_low := lowest_since last_break_up_bar := bar_index // Bearish Break of Structure (BOS) or Change of Character (CHoCH) if break_down and bar_index != last_break_down_bar string break_label = "" color break_color = color_bear_structure if structure_trend == "none" or structure_trend == "bull" break_label := "CHoCH" structure_trend := "bear" else break_label := "BOS" if show_structure line.new( x1=bar_index - 1, y1=struct_low, x2=bar_index, y2=struct_low, color=break_color, width=1, style=line.style_dashed, extend=extend.none ) label.new( x=bar_index, y=struct_low, text=break_label, color=color.new(break_color, 90), textcolor=break_color, style=label.style_label_up, size=size.small ) // --- Create Bearish Order Block (Supply Zone) --- int ob_bar = bar_index float ob_top = na float ob_bottom = na // Scan backwards to find the last up-close candle that originated the push for i = 1 to 30 if close > open ob_bar := bar_index - i ob_top := high ob_bottom := low break if show_obs and not na(ob_top) if array.size(bearish_ob_boxes) >= ob_max_count box.delete(array.shift(bearish_ob_boxes)) box new_ob = box.new( left=ob_bar, top=ob_top, right=bar_index, bottom=ob_bottom, bgcolor=color_supply, border_color=color_supply_b, border_style=line.style_solid, text="Supply", text_color=color_supply_b, text_size=size.small, text_align=text.align_left, text_valign=text.valign_top ) array.push(bearish_ob_boxes, new_ob) // Reset structure parameters safely struct_low := na(pLow) ? low : pLow float highest_since = high for i = 1 to math.min(100, bar_index - nz(last_break_up_bar, 0)) if high > highest_since highest_since := high struct_high := highest_since last_break_down_bar := bar_index // ========================================== // --- RE-EVALUATE AND TRACK ORDER BLOCKS --- // ========================================== if show_obs // Check & update active Bullish Order Blocks if array.size(bullish_ob_boxes) > 0 for i = array.size(bullish_ob_boxes) - 1 to 0 box_id = array.get(bullish_ob_boxes, i) float top_level = box.get_top(box_id) float btm_level = box.get_bottom(box_id) // Mitigation: invalidated if closed below block bottom if close < btm_level box.delete(box_id) array.remove(bullish_ob_boxes, i) else box.set_right(box_id, bar_index) if low < top_level box.set_bgcolor(box_id, color.new(color_demand, 95)) box.set_text(box_id, "Demand (Tested)") // Check & update active Bearish Order Blocks if array.size(bearish_ob_boxes) > 0 for i = array.size(bearish_ob_boxes) - 1 to 0 box_id = array.get(bearish_ob_boxes, i) float top_level = box.get_top(box_id) float btm_level = box.get_bottom(box_id) // Mitigation: invalidated if closed above block top if close > top_level box.delete(box_id) array.remove(bearish_ob_boxes, i) else box.set_right(box_id, bar_index) if high > btm_level box.set_bgcolor(box_id, color.new(color_supply, 95)) box.set_text(box_id, "Supply (Tested)") // ========================================== // --- DETECT FAIR VALUE GAPS (FVG) --- // ========================================== var box bullish_fvg_boxes = array.new_box() var box bearish_fvg_boxes = array.new_box() if show_fvgs // Bullish FVG (Imbalance Zone: Low of Bar 0 > High of Bar 2) if low > high and (low - high) >= (fvg_threshold * atr) if array.size(bullish_fvg_boxes) >= fvg_max_count box.delete(array.shift(bullish_fvg_boxes)) box new_fvg = box.new( left=bar_index - 2, top=low, right=bar_index, bottom=high, bgcolor=color_bull_fvg, border_width=0, text="FVG", text_color=color.new(color_bull_fvg, 40), text_size=size.tiny, text_align=text.align_center, text_valign=text.valign_center ) array.push(bullish_fvg_boxes, new_fvg) // Bearish FVG (Imbalance Zone: High of Bar 0 < Low of Bar 2) if high < low and (low - high) >= (fvg_threshold * atr) if array.size(bearish_fvg_boxes) >= fvg_max_count box.delete(array.shift(bearish_fvg_boxes)) box new_fvg = box.new( left=bar_index - 2, top=low, right=bar_index, bottom=high, bgcolor=color_bear_fvg, border_width=0, text="FVG", text_color=color.new(color_bear_fvg, 40), text_size=size.tiny, text_align=text.align_center, text_valign=text.valign_center ) array.push(bearish_fvg_boxes, new_fvg) // --- MITIGATE ACTIVE FVGS --- if show_fvgs // Handle Bullish FVG Mitigation if array.size(bullish_fvg_boxes) > 0 for i = array.size(bullish_fvg_boxes) - 1 to 0 box_id = array.get(bullish_fvg_boxes, i) float top_val = box.get_top(box_id) float btm_val = box.get_bottom(box_id) bool is_mitigated = false if fvg_mitigation == "Touch" is_mitigated := low < top_val else // Full fill is_mitigated := low 0 for i = array.size(bearish_fvg_boxes) - 1 to 0 box_id = array.get(bearish_fvg_boxes, i) float top_val = box.get_top(box_id) float btm_val = box.get_bottom(box_id) bool is_mitigated = false if fvg_mitigation == "Touch" is_mitigated := high > btm_val else // Full fill is_mitigated := high >= top_val if is_mitigated box.delete(box_id) array.remove(bearish_fvg_boxes, i) else box.set_right(box_id, bar_index) // ========================================== // --- LIQUIDITY & LIQUIDITY SWEEPS --- // ========================================== // 1. Equal Highs (EQH) and Equal Lows (EQL) if show_liquidity if not na(pHigh) and not na(prev_ph_val) float diff_high = math.abs(ph_price - prev_ph_val) / prev_ph_val * 100 if diff_high struct_low label.new( x=bar_index, y=low, text="🧹 Bullish Liquidity Grab", color=color.new(color.blue, 100), textcolor=color.blue, style=label.style_label_up, size=size.small ) // ========================================== // --- ORDER FLOW: PREMIUM/DISCOUNT ZONES --- // ========================================== var line pd_premium_line = na var line pd_eq_line = na var line pd_discount_line = na var label pd_premium_label = na var label pd_eq_label = na var label pd_discount_label = na if show_pd_zones and not na(struct_high) and not na(struct_low) // Refresh structural range boundaries on each candle to maintain neat layout if not na(pd_premium_line) line.delete(pd_premium_line) line.delete(pd_eq_line) line.delete(pd_discount_line) label.delete(pd_premium_label) label.delete(pd_eq_label) label.delete(pd_discount_label) float eq_level = (struct_high + struct_low) / 2 // Render Horizontal Range Zones pd_premium_line := line.new(x1=bar_index - 30, y1=struct_high, x2=bar_index, y2=struct_high, color=color.new(color.red, 50), width=1, style=line.style_dashed) pd_eq_line := line.new(x1=bar_index - 30, y1=eq_level, x2=bar_index, y2=eq_level, color=color.new(color.gray, 30), width=2, style=line.style_solid) pd_discount_line := line.new(x1=bar_index - 30, y1=struct_low, x2=bar_index, y2=struct_low, color=color.new(color.green, 50), width=1, style=line.style_dashed) // Label Positions pd_premium_label := label.new(x=bar_index - 30, y=struct_high, text="Premium (Short)", color=color.new(color.red, 100), textcolor=color.red, style=label.style_label_down, size=size.small) pd_eq_label := label.new(x=bar_index - 30, y=eq_level, text="Equilibrium (0.50)", color=color.new(color.gray, 100), textcolor=color.gray, style=label.style_label_left, size=size.small) pd_discount_label := label.new(x=bar_index - 30, y=struct_low, text="Discount (Long)", color=color.new(color.green, 100), textcolor=color.green, style=label.style_label_up, size=size.small) // ========================================== // --- CLASSIC SUPPORT & RESISTANCE ZONES --- // ========================================== var box support_zone = na var box resistance_zone = na // Calculate S/R levels every 10 bars to conserve performance and optimize rendering if show_sr and bar_index % 10 == 0 float support_level = na float resistance_level = na int sup_touches = 0 int res_touches = 0 float tolerance = atr * 0.5 for i = 1 to sr_lookback float p_h = pHigh float p_l = pLow if not na(p_h) int count = 0 for j = 1 to sr_lookback if not na(pHigh) and math.abs(pHigh - p_h) = sr_touches and (na(resistance_level) or p_h > resistance_level) resistance_level := p_h res_touches := count if not na(p_l) int count = 0 for j = 1 to sr_lookback if not na(pLow) and math.abs(pLow - p_l) = sr_touches and (na(support_level) or p_l < support_level) support_level := p_l sup_touches := count // Draw Dynamic Support Zones if not na(support_level) if not na(support_zone) box.delete(support_zone) support_zone := box.new( left=bar_index - sr_lookback, top=support_level + tolerance, right=bar_index, bottom=support_level - tolerance, bgcolor=color_support, border_color=color.new(color_support, 30), border_style=line.style_dotted, text="Key Support Zone", text_color=color.new(color_support, 30), text_size=size.small, text_align=text.align_left, text_valign=text.valign_center ) // Draw Dynamic Resistance Zones if not na(resistance_level) if not na(resistance_zone) box.delete(resistance_zone) resistance_zone := box.new( left=bar_index - sr_lookback, top=resistance_level + tolerance, right=bar_index, bottom=resistance_level - tolerance, bgcolor=color_resistance, border_color=color.new(color_resistance, 30), border_style=line.style_dotted, text="Key Resistance Zone", text_color=color.new(color_resistance, 30), text_size=size.small, text_align=text.align_left, text_valign=text.valign_center )