Not a member of gistpad yet?
Sign Up,
it unlocks many cool features!
- //@version=5
- indicator("Phidias Master Engine [v9.6.1] - Fixed Tick Auction Visual", overlay=true, max_lines_count=500, max_boxes_count=500, max_labels_count=500)
- // ═══════════════════════════════════════════════════════════════════════════════
- // v9.6.1 CHANGELOG (from v9.6):
- // FIX #1: Performance — max_bins 500→300, VA recalc every 10 bars
- // FIX #5: Sweep — wick vs body, displacement confirm, sweep quality score
- // FIX #6: Mitigation — swept boxes invalidated, touch count tracked, box cleanup
- // BUG: vol_std zero-division guard added
- // BUG: box_touches now actually incremented on touch
- // BUG: old visual boxes cleaned up via array tracking
- // ═══════════════════════════════════════════════════════════════════════════════
- // ═══════════════════════════════════════════════════════════════════════════════
- // 1. INPUTS & CONSTANTS
- // ═══════════════════════════════════════════════════════════════════════════════
- group_engine = "Auction Engine Settings"
- bin_res = input.float(1.0, "Bin Resolution (Points)", step=0.25, group=group_engine)
- va_perc = input.float(70.0, "Value Area %", minval=10, maxval=100, group=group_engine) / 100
- // FIX #1: Reduced from 500 to 300 — covers ±150 pts, more than enough for MES
- max_bins = 300
- group_sessions = "Session Settings (UTC)"
- tok_sess = input.session("0000-0100:1234567", "Tokyo 1st Hour", group=group_sessions)
- lon_sess = input.session("0800-0900:1234567", "London 1st Hour", group=group_sessions)
- ny_sess = input.session("1430-1530:1234567", "NY 1st Hour", group=group_sessions)
- lon_window = input.session("0800-1429:1234567", "London Active Window", group=group_sessions)
- ny_window = input.session("1430-2100:1234567", "NY Active Window", group=group_sessions)
- group_display = "Display Settings"
- show_tok = input.bool(true, "Show Tokyo Lines (Background)", group=group_display)
- show_lon = input.bool(true, "Show London Lines", group=group_display)
- show_ny = input.bool(true, "Show NY Lines", group=group_display)
- group_boxes = "Institutional Anchor Boxes"
- z_threshold = input.float(2.5, "Z-Score Volume Threshold", minval=0.5, step=0.1, group=group_boxes)
- box_length = input.int(15, "Box Projection Length (bars)", minval=5, group=group_boxes)
- show_levels = input.bool(true, "Show 1/3 and 2/3 Box Levels", group=group_boxes)
- // FIX #6: Box expiry input
- box_expire_bars = input.int(200, "Box Expires After (bars)", minval=50, maxval=500, group=group_boxes, tooltip="Boxes older than this are removed from chart and tracking.")
- group_touch = "Box Touch & Sweep Detection"
- touch_zone_ticks = input.int(2, "Touch Zone (ticks from boundary)", minval=0, maxval=10, group=group_touch)
- tick_size_input = input.float(0.25, "Tick Size", step=0.25, group=group_touch)
- max_tracked = input.int(10, "Max Tracked Boxes", minval=5, maxval=20, group=group_touch)
- // FIX #5: Displacement threshold
- displacement_pts = input.float(1.0, "Displacement Threshold (Pts)", minval=0.25, step=0.25, group=group_touch)
- // Colors
- c_tok_bg = #ff9800
- c_lon_va = #5DADE2
- c_ny_va = #00FFFF
- c_demand = #7CFC00
- c_supply = #FF0000
- c_poc = color.white
- c_level_1_3 = color.yellow
- c_level_2_3 = color.orange
- // ═══════════════════════════════════════════════════════════════════════════════
- // 2. SESSION-BASED OPACITY ENGINE
- // ═══════════════════════════════════════════════════════════════════════════════
- in_london_active = not na(time(timeframe.period, lon_window, "UTC"))
- in_ny_active = not na(time(timeframe.period, ny_window, "UTC"))
- opacity_tok = 30
- opacity_lon = in_london_active ? 100 : (in_ny_active ? 50 : 30)
- opacity_ny = in_ny_active ? 100 : (in_london_active ? 50 : 30)
- alpha_tok = 100 - opacity_tok
- alpha_lon = 100 - opacity_lon
- alpha_ny = 100 - opacity_ny
- // ═══════════════════════════════════════════════════════════════════════════════
- // 3. FIXED DAILY ANCHORING & PRICE-TO-INDEX MAPPING
- // ═══════════════════════════════════════════════════════════════════════════════
- var float tok_anchor = na
- var float lon_anchor = na
- var float ny_anchor = na
- if ta.change(time("D"))
- tok_anchor := open
- lon_anchor := open
- ny_anchor := open
- f_get_idx(price, anchor) =>
- if na(anchor) or price < anchor - (max_bins / 2) * bin_res or price > anchor + (max_bins / 2) * bin_res
- -1
- else
- idx = math.floor((price - anchor) / bin_res) + (max_bins / 2)
- math.min(max_bins - 1, math.max(0, int(idx)))
- // ═══════════════════════════════════════════════════════════════════════════════
- // 4. SHARED VA CALCULATION FUNCTION
- // FIX #1: Extracted to avoid triple code duplication
- // ═══════════════════════════════════════════════════════════════════════════════
- // Note: Pine v5 doesn't support passing arrays to functions easily, so we use
- // a shared calculation approach with explicit index tracking per session.
- // The actual loops remain per-session but are optimised with max_bins=300.
- // ═══════════════════════════════════════════════════════════════════════════════
- // 5. TOKYO SESSION: TICK AUCTION
- // ═══════════════════════════════════════════════════════════════════════════════
- var float[] tok_bins = array.new_float(max_bins, 0.0)
- var float tok_poc = na
- var float tok_val = na
- var float tok_vah = na
- bool in_tok = not na(time(timeframe.period, tok_sess, "UTC"))
- bool tok_start = in_tok and not in_tok[1]
- bool tok_end = not in_tok and in_tok[1]
- if tok_start
- for j = 0 to max_bins - 1
- array.set(tok_bins, j, 0.0)
- if in_tok
- idx = f_get_idx(hlc3, tok_anchor)
- if idx >= 0
- array.set(tok_bins, idx, array.get(tok_bins, idx) + volume)
- // FIX #1: Recalc every 10 bars instead of 5
- if tok_end or (in_tok and bar_index % 10 == 0)
- max_vol = 0.0
- poc_idx = 0
- for j = 0 to max_bins - 1
- bv = array.get(tok_bins, j)
- if bv > max_vol
- max_vol := bv
- poc_idx := j
- if max_vol > 0
- total_vol = 0.0
- for j = 0 to max_bins - 1
- total_vol += array.get(tok_bins, j)
- if total_vol > 0
- captured = max_vol
- lo_idx = poc_idx
- hi_idx = poc_idx
- target_vol = total_vol * va_perc
- while captured < target_vol and (lo_idx > 0 or hi_idx < max_bins - 1)
- vol_below = lo_idx > 0 ? array.get(tok_bins, lo_idx - 1) : 0.0
- vol_above = hi_idx < max_bins - 1 ? array.get(tok_bins, hi_idx + 1) : 0.0
- if lo_idx <= 0
- hi_idx += 1
- captured += vol_above
- else if hi_idx >= max_bins - 1
- lo_idx -= 1
- captured += vol_below
- else if vol_below >= vol_above
- lo_idx -= 1
- captured += vol_below
- else
- hi_idx += 1
- captured += vol_above
- tok_poc := tok_anchor + (poc_idx - (max_bins / 2)) * bin_res + (bin_res / 2)
- tok_val := tok_anchor + (lo_idx - (max_bins / 2)) * bin_res
- tok_vah := tok_anchor + (hi_idx + 1 - (max_bins / 2)) * bin_res
- // ═══════════════════════════════════════════════════════════════════════════════
- // 6. LONDON SESSION: TICK AUCTION
- // ═══════════════════════════════════════════════════════════════════════════════
- var float[] lon_bins = array.new_float(max_bins, 0.0)
- var float lon_poc = na
- var float lon_val = na
- var float lon_vah = na
- bool in_lon = not na(time(timeframe.period, lon_sess, "UTC"))
- bool lon_start = in_lon and not in_lon[1]
- bool lon_end = not in_lon and in_lon[1]
- if lon_start
- for j = 0 to max_bins - 1
- array.set(lon_bins, j, 0.0)
- if in_lon
- idx = f_get_idx(hlc3, lon_anchor)
- if idx >= 0
- array.set(lon_bins, idx, array.get(lon_bins, idx) + volume)
- if lon_end or (in_lon and bar_index % 10 == 0)
- max_vol = 0.0
- poc_idx = 0
- for j = 0 to max_bins - 1
- bv = array.get(lon_bins, j)
- if bv > max_vol
- max_vol := bv
- poc_idx := j
- if max_vol > 0
- total_vol = 0.0
- for j = 0 to max_bins - 1
- total_vol += array.get(lon_bins, j)
- if total_vol > 0
- captured = max_vol
- lo_idx = poc_idx
- hi_idx = poc_idx
- target_vol = total_vol * va_perc
- while captured < target_vol and (lo_idx > 0 or hi_idx < max_bins - 1)
- vol_below = lo_idx > 0 ? array.get(lon_bins, lo_idx - 1) : 0.0
- vol_above = hi_idx < max_bins - 1 ? array.get(lon_bins, hi_idx + 1) : 0.0
- if lo_idx <= 0
- hi_idx += 1
- captured += vol_above
- else if hi_idx >= max_bins - 1
- lo_idx -= 1
- captured += vol_below
- else if vol_below >= vol_above
- lo_idx -= 1
- captured += vol_below
- else
- hi_idx += 1
- captured += vol_above
- lon_poc := lon_anchor + (poc_idx - (max_bins / 2)) * bin_res + (bin_res / 2)
- lon_val := lon_anchor + (lo_idx - (max_bins / 2)) * bin_res
- lon_vah := lon_anchor + (hi_idx + 1 - (max_bins / 2)) * bin_res
- // ═══════════════════════════════════════════════════════════════════════════════
- // 7. NEW YORK SESSION: TICK AUCTION
- // ═══════════════════════════════════════════════════════════════════════════════
- var float[] ny_bins = array.new_float(max_bins, 0.0)
- var float ny_poc = na
- var float ny_val = na
- var float ny_vah = na
- bool in_ny = not na(time(timeframe.period, ny_sess, "UTC"))
- bool ny_start = in_ny and not in_ny[1]
- bool ny_end = not in_ny and in_ny[1]
- if ny_start
- for j = 0 to max_bins - 1
- array.set(ny_bins, j, 0.0)
- if in_ny
- idx = f_get_idx(hlc3, ny_anchor)
- if idx >= 0
- array.set(ny_bins, idx, array.get(ny_bins, idx) + volume)
- if ny_end or (in_ny and bar_index % 10 == 0)
- max_vol = 0.0
- poc_idx = 0
- for j = 0 to max_bins - 1
- bv = array.get(ny_bins, j)
- if bv > max_vol
- max_vol := bv
- poc_idx := j
- if max_vol > 0
- total_vol = 0.0
- for j = 0 to max_bins - 1
- total_vol += array.get(ny_bins, j)
- if total_vol > 0
- captured = max_vol
- lo_idx = poc_idx
- hi_idx = poc_idx
- target_vol = total_vol * va_perc
- while captured < target_vol and (lo_idx > 0 or hi_idx < max_bins - 1)
- vol_below = lo_idx > 0 ? array.get(ny_bins, lo_idx - 1) : 0.0
- vol_above = hi_idx < max_bins - 1 ? array.get(ny_bins, hi_idx + 1) : 0.0
- if lo_idx <= 0
- hi_idx += 1
- captured += vol_above
- else if hi_idx >= max_bins - 1
- lo_idx -= 1
- captured += vol_below
- else if vol_below >= vol_above
- lo_idx -= 1
- captured += vol_below
- else
- hi_idx += 1
- captured += vol_above
- ny_poc := ny_anchor + (poc_idx - (max_bins / 2)) * bin_res + (bin_res / 2)
- ny_val := ny_anchor + (lo_idx - (max_bins / 2)) * bin_res
- ny_vah := ny_anchor + (hi_idx + 1 - (max_bins / 2)) * bin_res
- // ═══════════════════════════════════════════════════════════════════════════════
- // 8. PERSISTENT HORIZONTAL LINES WITH OPACITY CONTROL
- // ═══════════════════════════════════════════════════════════════════════════════
- var line tvah_line = na
- var line tval_line = na
- var line tpoc_line = na
- if show_tok and not na(tok_vah)
- line.delete(tvah_line[1])
- line.delete(tval_line[1])
- line.delete(tpoc_line[1])
- tvah_line := line.new(bar_index[1], tok_vah, bar_index, tok_vah,
- extend=extend.right, color=color.new(c_tok_bg, alpha_tok), width=2)
- tval_line := line.new(bar_index[1], tok_val, bar_index, tok_val,
- extend=extend.right, color=color.new(c_tok_bg, alpha_tok), width=2)
- tpoc_line := line.new(bar_index[1], tok_poc, bar_index, tok_poc,
- extend=extend.right, color=color.new(c_poc, alpha_tok), style=line.style_dashed, width=1)
- var line lvah_line = na
- var line lval_line = na
- var line lpoc_line = na
- if show_lon and not na(lon_vah)
- line.delete(lvah_line[1])
- line.delete(lval_line[1])
- line.delete(lpoc_line[1])
- lvah_line := line.new(bar_index[1], lon_vah, bar_index, lon_vah,
- extend=extend.right, color=color.new(c_lon_va, alpha_lon), width=2)
- lval_line := line.new(bar_index[1], lon_val, bar_index, lon_val,
- extend=extend.right, color=color.new(c_lon_va, alpha_lon), width=2)
- lpoc_line := line.new(bar_index[1], lon_poc, bar_index, lon_poc,
- extend=extend.right, color=color.new(c_poc, alpha_lon), style=line.style_dashed, width=1)
- var line nvah_line = na
- var line nval_line = na
- var line npoc_line = na
- if show_ny and not na(ny_vah)
- line.delete(nvah_line[1])
- line.delete(nval_line[1])
- line.delete(npoc_line[1])
- nvah_line := line.new(bar_index[1], ny_vah, bar_index, ny_vah,
- extend=extend.right, color=color.new(c_ny_va, alpha_ny), width=2)
- nval_line := line.new(bar_index[1], ny_val, bar_index, ny_val,
- extend=extend.right, color=color.new(c_ny_va, alpha_ny), width=2)
- npoc_line := line.new(bar_index[1], ny_poc, bar_index, ny_poc,
- extend=extend.right, color=color.new(c_poc, alpha_ny), style=line.style_dashed, width=1)
- // ═══════════════════════════════════════════════════════════════════════════════
- // 9. INSTITUTIONAL ANCHOR BOXES + TOUCH TRACKING
- // FIX: zero-division guard, visual box tracking for cleanup
- // ═══════════════════════════════════════════════════════════════════════════════
- float vol_sma = ta.sma(volume, 20)
- float vol_std = ta.stdev(volume, 20)
- // BUG FIX: Guard against zero standard deviation
- float z_vol = vol_std != 0 ? (volume - vol_sma) / vol_std : 0
- bool high_vol = z_vol >= z_threshold
- bool bullish = close > open
- color box_color = high_vol ? (bullish ? c_demand : c_supply) : na
- color box_bg = high_vol ? color.new(box_color, 85) : na
- var float[] box_tops = array.new_float(0)
- var float[] box_bottoms = array.new_float(0)
- var int[] box_dirs = array.new_int(0)
- var int[] box_births = array.new_int(0)
- var int[] box_touches = array.new_int(0)
- var bool[] box_swept = array.new_bool(0)
- // FIX #5: Track sweep type per box — true = wick only
- var bool[] box_sweep_wick = array.new_bool(0)
- // FIX #6: Track visual box IDs for cleanup
- var box[] box_visuals = array.new_box(0)
- float touch_zone = touch_zone_ticks * tick_size_input
- if high_vol
- // Create visual box
- box new_box = box.new(left=bar_index, top=high, right=bar_index + box_length, bottom=low,
- border_color=box_color, bgcolor=box_bg, border_width=2)
- if show_levels
- float box_height = high - low
- float level_1_3 = low + box_height / 3
- float level_2_3 = low + (box_height * 2) / 3
- line.new(bar_index + box_length - 1, level_1_3,
- bar_index + box_length, level_1_3,
- color=color.new(c_level_1_3, 40), width=2, style=line.style_solid)
- line.new(bar_index + box_length - 1, level_2_3,
- bar_index + box_length, level_2_3,
- color=color.new(c_level_2_3, 40), width=2, style=line.style_solid)
- float level_1_4 = bullish ? (low + box_height / 4) : (high - box_height / 4)
- color mark_col = bullish ? c_level_1_3 : c_level_2_3
- line.new(bar_index + box_length - 2, level_1_4,
- bar_index + box_length + 1, level_1_4,
- color=color.new(mark_col, 40), width=2, style=line.style_solid)
- // Push to tracking arrays
- array.push(box_tops, high)
- array.push(box_bottoms, low)
- array.push(box_dirs, bullish ? 1 : -1)
- array.push(box_births, bar_index)
- array.push(box_touches, 0)
- array.push(box_swept, false)
- array.push(box_sweep_wick, false)
- array.push(box_visuals, new_box)
- // Enforce max tracked — clean up oldest
- if array.size(box_tops) > max_tracked
- array.shift(box_tops)
- array.shift(box_bottoms)
- array.shift(box_dirs)
- array.shift(box_births)
- array.shift(box_touches)
- array.shift(box_swept)
- array.shift(box_sweep_wick)
- // FIX #6: Delete the oldest visual box from chart
- box old_box = array.shift(box_visuals)
- box.delete(old_box)
- string session_context = in_ny_active ? "NY ACTIVE" : (in_london_active ? "LONDON ACTIVE" : "ASIA BACKGROUND")
- string box_type = bullish ? "DEMAND (LIME)" : "SUPPLY (RED)"
- string msg = "Phidias " + box_type + " Box | " + session_context + " | Z=" + str.tostring(z_vol, "#.##") + " @ " + str.tostring(close)
- alert(msg, alert.freq_once_per_bar)
- // ═══════════════════════════════════════════════════════════════════════════════
- // 10. TOUCH & SWEEP DETECTION ENGINE
- // FIX #5: Wick vs body classification, displacement tracking
- // FIX #6: Mitigated/expired boxes removed from chart + tracking
- // ═══════════════════════════════════════════════════════════════════════════════
- var bool touch_demand_alert = false
- var bool touch_supply_alert = false
- var bool sweep_demand_alert = false
- var bool sweep_supply_alert = false
- // FIX #5: Sweep quality tracking (most recent sweep)
- var bool last_sweep_wick = false
- var bool last_sweep_displaced = false
- var int last_sweep_bar = 0
- var int last_sweep_dir = 0
- var float last_sweep_level = na
- touch_demand_alert := false
- touch_supply_alert := false
- sweep_demand_alert := false
- sweep_supply_alert := false
- int n_boxes = array.size(box_tops)
- // FIX #6: Collect indices to remove (iterate backwards so indices stay valid)
- if n_boxes > 0
- for i = n_boxes - 1 to 0
- float b_top = array.get(box_tops, i)
- float b_bottom = array.get(box_bottoms, i)
- int b_dir = array.get(box_dirs, i)
- int b_birth = array.get(box_births, i)
- bool b_swept = array.get(box_swept, i)
- int b_touch = array.get(box_touches, i)
- // FIX #6: Remove expired boxes from chart and arrays
- if bar_index - b_birth > box_expire_bars
- box old_vis = array.get(box_visuals, i)
- box.delete(old_vis)
- array.remove(box_tops, i)
- array.remove(box_bottoms, i)
- array.remove(box_dirs, i)
- array.remove(box_births, i)
- array.remove(box_touches, i)
- array.remove(box_swept, i)
- array.remove(box_sweep_wick, i)
- array.remove(box_visuals, i)
- continue
- // FIX #6: Skip already-swept boxes but keep them visible (faded)
- if b_swept
- // Fade the swept box visual
- box swept_vis = array.get(box_visuals, i)
- box.set_bgcolor(swept_vis, color.new(color.gray, 92))
- box.set_border_color(swept_vis, color.new(color.gray, 70))
- continue
- if b_dir == 1
- bool near_bottom = low <= (b_bottom + touch_zone) and low >= (b_bottom - touch_zone)
- bool closed_above = close > b_bottom
- bool swept_below = low < (b_bottom - touch_zone)
- // BUG FIX: Actually increment touch count
- if near_bottom and closed_above and not swept_below
- array.set(box_touches, i, b_touch + 1)
- touch_demand_alert := true
- if swept_below
- array.set(box_swept, i, true)
- sweep_demand_alert := true
- // FIX #5: Classify wick vs body
- bool is_wick = close > b_bottom
- array.set(box_sweep_wick, i, is_wick)
- last_sweep_wick := is_wick
- last_sweep_bar := bar_index
- last_sweep_dir := 1
- last_sweep_level := b_bottom
- last_sweep_displaced := false
- if b_dir == -1
- bool near_top = high >= (b_top - touch_zone) and high <= (b_top + touch_zone)
- bool closed_below = close < b_top
- bool swept_above = high > (b_top + touch_zone)
- // BUG FIX: Actually increment touch count
- if near_top and closed_below and not swept_above
- array.set(box_touches, i, b_touch + 1)
- touch_supply_alert := true
- if swept_above
- array.set(box_swept, i, true)
- sweep_supply_alert := true
- // FIX #5: Classify wick vs body
- bool is_wick = close < b_top
- array.set(box_sweep_wick, i, is_wick)
- last_sweep_wick := is_wick
- last_sweep_bar := bar_index
- last_sweep_dir := -1
- last_sweep_level := b_top
- last_sweep_displaced := false
- // FIX #5: Check displacement on bar after sweep
- if bar_index == last_sweep_bar + 1 and last_sweep_bar > 0
- if last_sweep_dir == 1
- last_sweep_displaced := (close - last_sweep_level) >= displacement_pts
- else if last_sweep_dir == -1
- last_sweep_displaced := (last_sweep_level - close) >= displacement_pts
- // FIX #5: Sweep quality score (0-2 for visual indicator, no FVG check here)
- int sweep_quality = 0
- bool sweep_active = last_sweep_bar > 0 and (bar_index - last_sweep_bar) <= 30
- if sweep_active
- if last_sweep_wick
- sweep_quality += 1
- if last_sweep_displaced
- sweep_quality += 1
- // ═══════════════════════════════════════════════════════════════════════════════
- // 11. SWEEP QUALITY LABEL (on-chart visual)
- // ═══════════════════════════════════════════════════════════════════════════════
- // Show a small label at sweep location indicating quality
- if sweep_demand_alert or sweep_supply_alert
- string sw_type = last_sweep_wick ? "WICK" : "BODY"
- string sw_lbl = "SW:" + sw_type
- color sw_col = last_sweep_wick ? color.new(c_demand, 20) : color.new(color.orange, 20)
- label.new(bar_index, last_sweep_dir == 1 ? low : high, sw_lbl,
- color=sw_col, textcolor=color.white, size=size.tiny,
- style=last_sweep_dir == 1 ? label.style_label_up : label.style_label_down)
- // Displacement confirmation label (fires one bar after sweep)
- if bar_index == last_sweep_bar + 1 and last_sweep_bar > 0 and sweep_active
- if last_sweep_displaced
- label.new(bar_index, last_sweep_dir == 1 ? low : high, "DISP ✓",
- color=color.new(c_demand, 30), textcolor=color.white, size=size.tiny,
- style=last_sweep_dir == 1 ? label.style_label_up : label.style_label_down)
- // ═══════════════════════════════════════════════════════════════════════════════
- // 12. ALERTS
- // ═══════════════════════════════════════════════════════════════════════════════
- alertcondition(high_vol, title="Institutional Box Detected",
- message="Phidias Box Forming - Check Session Context")
- alertcondition(touch_demand_alert, title="Demand Box Touch — Sweep Incoming",
- message="Price touched Demand Box boundary — liquidity building below.")
- alertcondition(touch_supply_alert, title="Supply Box Touch — Sweep Incoming",
- message="Price touched Supply Box boundary — liquidity building above.")
- // FIX #5: Separate wick and body sweep alerts
- alertcondition(sweep_demand_alert and last_sweep_wick, title="Demand WICK Sweep — High Probability",
- message="Demand Box wick sweep — liquidity grabbed, price rejected. Check for reversal.")
- alertcondition(sweep_demand_alert and not last_sweep_wick, title="Demand BODY Sweep — Breakout Watch",
- message="Demand Box body sweep — potential breakdown, not a clean liquidity grab.")
- alertcondition(sweep_supply_alert and last_sweep_wick, title="Supply WICK Sweep — High Probability",
- message="Supply Box wick sweep — liquidity grabbed, price rejected. Check for reversal.")
- alertcondition(sweep_supply_alert and not last_sweep_wick, title="Supply BODY Sweep — Breakout Watch",
- message="Supply Box body sweep — potential breakout, not a clean liquidity grab.")
- // ═══════════════════════════════════════════════════════════════════════════════
- // 13. INFO TABLE (compact sweep status)
- // ═══════════════════════════════════════════════════════════════════════════════
- var table info = table.new(position.top_right, 3, 2, bgcolor=color.new(#000000, 80), border_width=1)
- if barstate.islast
- table.cell(info, 0, 0, "SWEEP", text_color=#888888, text_size=size.tiny)
- table.cell(info, 1, 0, "TYPE", text_color=#888888, text_size=size.tiny)
- table.cell(info, 2, 0, "SQ", text_color=#888888, text_size=size.tiny)
- string sw_status = sweep_active ? (last_sweep_dir == 1 ? "BULL ↓" : "BEAR ↑") : "NONE"
- string sw_type = sweep_active ? (last_sweep_wick ? "WICK" : "BODY") : "-"
- string sq_text = sweep_active ? str.tostring(sweep_quality) + "/2" : "-"
- color sw_bg = sweep_active ? (last_sweep_wick ? color.new(c_demand, 30) : color.new(color.orange, 30)) : color.new(#000000, 40)
- color sq_bg = sweep_quality >= 2 ? color.new(#00e676, 15) : sweep_quality >= 1 ? color.new(#448aff, 25) : color.new(#444455, 50)
- color sq_tc = sweep_quality >= 1 ? color.white : color.gray
- table.cell(info, 0, 1, sw_status, bgcolor=sw_bg, text_color=color.white, text_size=size.tiny)
- table.cell(info, 1, 1, sw_type, bgcolor=sw_bg, text_color=color.white, text_size=size.tiny)
- table.cell(info, 2, 1, sq_text, bgcolor=sweep_active ? sq_bg : color.new(#000000, 40), text_color=sweep_active ? sq_tc : color.gray, text_size=size.tiny)
RAW Gist Data
Copied
