//@version=5 indicator("Phidias Master Engine [v9.5 TITAN]", shorttitle="Phidias_v9.5", overlay=true, max_labels_count=500) // ═══════════════════════════════════════════════════════════════════════════════ // 1. GLOBAL INPUTS // ═══════════════════════════════════════════════════════════════════════════════ nq_sym = input.symbol("NQ1!", "NQ Symbol", group="Institutional Sync") pl_input = input.float(0, "Current P&L ($)", step=50, group="Preservation Gate") stop_pts = input.float(4.0, "Stop Loss (Pts)", group="Risk Audit") target_pts = input.float(8.0, "Target (Pts)", group="Risk Audit") rr_floor = 1.5 // Silent Sweep Detection grp_sweep = "Sweep Detection (Silent)" z_threshold = input.float(2.5, "Z-Score Volume Threshold", minval=0.5, step=0.1, group=grp_sweep) touch_zone_ticks = input.int(2, "Touch Zone (ticks from boundary)", minval=0, maxval=10, group=grp_sweep) tick_size_input = input.float(0.25, "Tick Size", step=0.25, group=grp_sweep) max_tracked = input.int(10, "Max Tracked Boxes", minval=5, maxval=20, group=grp_sweep) sweep_stale_bars = input.int(15, "Sweep Stale After (bars)", minval=5, maxval=60, group=grp_sweep) sweep_expire_bars = input.int(30, "Sweep Expires After (bars)", minval=10, maxval=120, group=grp_sweep) // RSI Settings grp_rsi = "RSI Divergence" rsi_len = input.int(14, "RSI Length", minval=5, maxval=30, group=grp_rsi) rsi_ob = input.float(70.0, "Overbought", minval=60, maxval=90, group=grp_rsi) rsi_os = input.float(30.0, "Oversold", minval=10, maxval=40, group=grp_rsi) div_lookback = input.int(20, "Divergence Lookback (bars)", minval=5, maxval=30, group=grp_rsi) div_confirm = input.int(2, "Divergence Confirm (bars)", minval=1, maxval=5, group=grp_rsi) // ═══════════════════════════════════════════════════════════════════════════════ // 2. CURRENT PRICE DATA // ═══════════════════════════════════════════════════════════════════════════════ mes_c = close mes_v = volume nq_c = request.security(nq_sym, timeframe.period, close) // ═══════════════════════════════════════════════════════════════════════════════ // 3. LONDON MIDPOINT (08:00 UTC) // ═══════════════════════════════════════════════════════════════════════════════ var float lon_mid = na var bool lon_tested = false is_lon_start = not na(time(timeframe.period, "0800-0805", "UTC")) if is_lon_start lon_mid := (high + low) / 2 lon_tested := false if not na(lon_mid) and not lon_tested if low <= lon_mid and high >= lon_mid lon_tested := true // ═══════════════════════════════════════════════════════════════════════════════ // 4. ZONE MEMORY // ═══════════════════════════════════════════════════════════════════════════════ vol_ma = ta.sma(mes_v, 20) atr_val = ta.atr(14) atr_ma = ta.sma(atr_val, 20) is_climax = mes_v > vol_ma * 1.8 or atr_val > atr_ma * 1.5 var red_highs = array.new_float(3, na) var red_lows = array.new_float(3, na) var grn_highs = array.new_float(3, na) var grn_lows = array.new_float(3, na) var int r_ghosts = 0 var int g_ghosts = 0 if is_lon_start r_ghosts := 0 g_ghosts := 0 if is_climax if close < open array.unshift(red_highs, high) array.unshift(red_lows, low) array.pop(red_highs) array.pop(red_lows) else array.unshift(grn_highs, high) array.unshift(grn_lows, low) array.pop(grn_highs) array.pop(grn_lows) // ═══════════════════════════════════════════════════════════════════════════════ // 5. REFINED ZONE ANALYSIS — nearest = immediate structural threat // ═══════════════════════════════════════════════════════════════════════════════ bool in_red = false bool in_grn = false bool box_broken = false string break_type = "" float nearest_resistance = na // closest red zone top above price (immediate threat for longs) float nearest_support = na // closest green zone bottom below price (immediate threat for shorts) for i = 0 to 2 rh = array.get(red_highs, i) rl = array.get(red_lows, i) gh = array.get(grn_highs, i) gl = array.get(grn_lows, i) if not na(rh) if mes_c >= rl and mes_c <= rh in_red := true float red_edge = rh if red_edge > mes_c if na(nearest_resistance) or (red_edge - mes_c) < (nearest_resistance - mes_c) nearest_resistance := red_edge if not na(gh) if mes_c >= gl and mes_c <= gh in_grn := true float grn_edge = gl if grn_edge < mes_c if na(nearest_support) or (mes_c - grn_edge) < (mes_c - nearest_support) nearest_support := grn_edge if not na(rh) and close < rl box_broken := true break_type := "SUPPLY" if not na(gh) and close > gh box_broken := true break_type := "DEMAND" if not na(rh) and close > rh array.set(red_highs, i, na) array.set(red_lows, i, na) r_ghosts += 1 if not na(gh) and close < gl array.set(grn_highs, i, na) array.set(grn_lows, i, na) g_ghosts += 1 // ═══════════════════════════════════════════════════════════════════════════════ // 6. SILENT SWEEP DETECTION ENGINE // ═══════════════════════════════════════════════════════════════════════════════ float vol_sma_z = ta.sma(volume, 20) float vol_std_z = ta.stdev(volume, 20) float z_vol = vol_std_z != 0 ? (volume - vol_sma_z) / vol_std_z : 0 bool high_vol = z_vol >= z_threshold bool bullish_candle = close > open var float[] s_box_tops = array.new_float(0) var float[] s_box_bottoms = array.new_float(0) var int[] s_box_dirs = array.new_int(0) var int[] s_box_births = array.new_int(0) var int[] s_box_touches = array.new_int(0) var bool[] s_box_swept = array.new_bool(0) if high_vol array.push(s_box_tops, high) array.push(s_box_bottoms, low) array.push(s_box_dirs, bullish_candle ? 1 : -1) array.push(s_box_births, bar_index) array.push(s_box_touches, 0) array.push(s_box_swept, false) if array.size(s_box_tops) > max_tracked array.shift(s_box_tops) array.shift(s_box_bottoms) array.shift(s_box_dirs) array.shift(s_box_births) array.shift(s_box_touches) array.shift(s_box_swept) var int last_sweep_bar = 0 var int last_sweep_dir = 0 var int last_sweep_touches = 0 var float last_sweep_level = na float touch_zone = touch_zone_ticks * tick_size_input int n_sboxes = array.size(s_box_tops) if n_sboxes > 0 for i = n_sboxes - 1 to 0 float b_top = array.get(s_box_tops, i) float b_bottom = array.get(s_box_bottoms, i) int b_dir = array.get(s_box_dirs, i) int b_birth = array.get(s_box_births, i) bool b_swept = array.get(s_box_swept, i) int b_touch = array.get(s_box_touches, i) if bar_index - b_birth > 200 or b_swept 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) if near_bottom and closed_above and not swept_below array.set(s_box_touches, i, b_touch + 1) if swept_below array.set(s_box_swept, i, true) last_sweep_bar := bar_index last_sweep_dir := 1 last_sweep_touches := b_touch last_sweep_level := b_bottom 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) if near_top and closed_below and not swept_above array.set(s_box_touches, i, b_touch + 1) if swept_above array.set(s_box_swept, i, true) last_sweep_bar := bar_index last_sweep_dir := -1 last_sweep_touches := b_touch last_sweep_level := b_top int sweep_age = bar_index - last_sweep_bar bool sweep_active = last_sweep_bar > 0 and sweep_age <= sweep_expire_bars bool sweep_fresh = sweep_active and sweep_age <= sweep_stale_bars bool sweep_stale = sweep_active and sweep_age > sweep_stale_bars int pending_touches = 0 int active_boxes = 0 if array.size(s_box_tops) > 0 for i = 0 to array.size(s_box_tops) - 1 if bar_index - array.get(s_box_births, i) <= 200 and not array.get(s_box_swept, i) active_boxes += 1 pending_touches += array.get(s_box_touches, i) // ═══════════════════════════════════════════════════════════════════════════════ // 7. RSI DIVERGENCE ENGINE // ═══════════════════════════════════════════════════════════════════════════════ float rsi_val = ta.rsi(close, rsi_len) float price_low_1 = ta.lowest(low, div_lookback) float price_low_2 = ta.lowest(low, div_lookback)[div_lookback] float price_high_1 = ta.highest(high, div_lookback) float price_high_2 = ta.highest(high, div_lookback)[div_lookback] float rsi_low_1 = ta.lowest(rsi_val, div_lookback) float rsi_low_2 = ta.lowest(rsi_val, div_lookback)[div_lookback] float rsi_high_1 = ta.highest(rsi_val, div_lookback) float rsi_high_2 = ta.highest(rsi_val, div_lookback)[div_lookback] bool raw_bull_div = price_low_1 < price_low_2 and rsi_low_1 > rsi_low_2 bool raw_bear_div = price_high_1 > price_high_2 and rsi_high_1 < rsi_high_2 var int bull_div_count = 0 var int bear_div_count = 0 if raw_bull_div bull_div_count += 1 else bull_div_count := 0 if raw_bear_div bear_div_count += 1 else bear_div_count := 0 bool bull_div_confirmed = bull_div_count >= div_confirm bool bear_div_confirmed = bear_div_count >= div_confirm string rsi_state = "" color rsi_bg = color.new(#000000, 40) color rsi_tc = color.gray if bull_div_confirmed and rsi_val < rsi_os rsi_state := "OS + BULL DIV" rsi_bg := color.new(color.green, 10) rsi_tc := color.white else if bear_div_confirmed and rsi_val > rsi_ob rsi_state := "OB + BEAR DIV" rsi_bg := color.new(color.red, 10) rsi_tc := color.white else if bull_div_confirmed rsi_state := "BULL DIV" rsi_bg := color.new(color.green, 40) rsi_tc := color.green else if bear_div_confirmed rsi_state := "BEAR DIV" rsi_bg := color.new(color.red, 40) rsi_tc := color.red else if rsi_val > rsi_ob rsi_state := "OB " + str.tostring(rsi_val, "#.#") rsi_bg := color.new(color.red, 60) rsi_tc := color.red else if rsi_val < rsi_os rsi_state := "OS " + str.tostring(rsi_val, "#.#") rsi_bg := color.new(color.green, 60) rsi_tc := color.green else rsi_state := str.tostring(rsi_val, "#.#") rsi_bg := color.new(#000000, 40) rsi_tc := color.gray // ═══════════════════════════════════════════════════════════════════════════════ // 8. TARGET CALCULATIONS // ═══════════════════════════════════════════════════════════════════════════════ float long_target = mes_c + target_pts float short_target = mes_c - target_pts float dyn_rr = target_pts / stop_pts // ═══════════════════════════════════════════════════════════════════════════════ // 9. DUAL GATE AUDIT ENGINE — refined proximity // ═══════════════════════════════════════════════════════════════════════════════ bool is_rsw = not na(time(timeframe.period, "1430-1445", "UTC")) bool rr_fail = dyn_rr < rr_floor bool loss_limit = pl_input <= -500 bool long_trap = in_red bool long_nq_fail = nq_c < nq_c[1] and not box_broken bool long_target_blocked = not na(nearest_resistance) and nearest_resistance < long_target string long_veto = "" if loss_limit long_veto := "LOSS" else if is_rsw long_veto := "RSW" else if rr_fail long_veto := "R:R" else if long_trap long_veto := "ZONE" else if long_nq_fail long_veto := "NQ" else if long_target_blocked long_veto := "BLOCKED" bool long_pass = long_veto == "" bool short_trap = in_grn bool short_nq_fail = nq_c > nq_c[1] and not box_broken bool short_target_blocked = not na(nearest_support) and nearest_support > short_target string short_veto = "" if loss_limit short_veto := "LOSS" else if is_rsw short_veto := "RSW" else if rr_fail short_veto := "R:R" else if short_trap short_veto := "ZONE" else if short_nq_fail short_veto := "NQ" else if short_target_blocked short_veto := "BLOCKED" bool short_pass = short_veto == "" // ═══════════════════════════════════════════════════════════════════════════════ // 10. SETUP GRADING ENGINE // ═══════════════════════════════════════════════════════════════════════════════ bool sweep_long_aligned = sweep_fresh and last_sweep_dir == 1 bool sweep_short_aligned = sweep_fresh and last_sweep_dir == -1 bool rsi_supports_long = bull_div_confirmed or rsi_val < rsi_os bool rsi_supports_short = bear_div_confirmed or rsi_val > rsi_ob bool rsi_warns_long = bear_div_confirmed bool rsi_warns_short = bull_div_confirmed bool rsi_neutral = not rsi_supports_long and not rsi_supports_short and not rsi_warns_long and not rsi_warns_short string long_grade = "X" if not long_pass long_grade := "X" else if sweep_long_aligned and (rsi_supports_long or (rsi_neutral and not rsi_warns_long)) long_grade := "A+" else if rsi_warns_long long_grade := "C" else if sweep_long_aligned or rsi_supports_long long_grade := "B+" else long_grade := "B+" string short_grade = "X" if not short_pass short_grade := "X" else if sweep_short_aligned and (rsi_supports_short or (rsi_neutral and not rsi_warns_short)) short_grade := "A+" else if rsi_warns_short short_grade := "C" else if sweep_short_aligned or rsi_supports_short short_grade := "B+" else short_grade := "B+" f_grade_bg(string grade) => grade == "A+" ? color.new(#00e676, 15) : grade == "B+" ? color.new(#448aff, 25) : grade == "C" ? color.new(#ffd600, 25) : color.new(#444455, 50) f_grade_tc(string grade) => grade == "A+" ? color.white : grade == "B+" ? color.white : grade == "C" ? color.black : color.gray // ═══════════════════════════════════════════════════════════════════════════════ // 11. CANDLE COLOURING // ═══════════════════════════════════════════════════════════════════════════════ color candle_col = na if long_pass and not short_pass candle_col := color.new(color.green, 60) else if short_pass and not long_pass candle_col := color.new(color.red, 60) else if long_pass and short_pass candle_col := color.new(color.yellow, 60) else candle_col := color.new(color.gray, 80) barcolor(candle_col) // ═══════════════════════════════════════════════════════════════════════════════ // 12. VISUALS // ═══════════════════════════════════════════════════════════════════════════════ plot(lon_mid, "London Mid", color=lon_tested ? color.gray : color.aqua, linewidth=2) plotshape(box_broken, "Box Break", shape.diamond, location.belowbar, color=break_type == "DEMAND" ? color.green : color.red, size=size.small) plot(long_target, "Long Target", color=color.new(color.green, 70), style=plot.style_linebr, linewidth=1) plot(short_target, "Short Target", color=color.new(color.red, 70), style=plot.style_linebr, linewidth=1) // ═══════════════════════════════════════════════════════════════════════════════ // 13. GRADED ALERTS // ═══════════════════════════════════════════════════════════════════════════════ var string prev_long_grade = "X" var string prev_short_grade = "X" bool long_a_plus_new = long_grade == "A+" and prev_long_grade != "A+" bool long_b_plus_new = long_grade == "B+" and prev_long_grade == "X" bool long_c_new = long_grade == "C" and prev_long_grade == "X" bool short_a_plus_new = short_grade == "A+" and prev_short_grade != "A+" bool short_b_plus_new = short_grade == "B+" and prev_short_grade == "X" bool short_c_new = short_grade == "C" and prev_short_grade == "X" bool long_gate_closed = long_grade == "X" and prev_long_grade != "X" bool short_gate_closed = short_grade == "X" and prev_short_grade != "X" prev_long_grade := long_grade prev_short_grade := short_grade alertcondition(long_a_plus_new, title="⚡ A+ LONG", message="A+ LONG SETUP — Gate open, sweep aligned, RSI supports.") alertcondition(short_a_plus_new, title="⚡ A+ SHORT", message="A+ SHORT SETUP — Gate open, sweep aligned, RSI supports.") alertcondition(long_b_plus_new, title="📈 B+ LONG", message="B+ LONG SETUP — Gate open.") alertcondition(short_b_plus_new, title="📉 B+ SHORT", message="B+ SHORT SETUP — Gate open.") alertcondition(long_c_new, title="⚠️ C LONG", message="C LONG SETUP — RSI divergence warning.") alertcondition(short_c_new, title="⚠️ C SHORT", message="C SHORT SETUP — RSI divergence warning.") // ═══════════════════════════════════════════════════════════════════════════════ // 14. UI TABLE // ═══════════════════════════════════════════════════════════════════════════════ var table t = table.new(position.bottom_left, 9, 3, bgcolor=color.new(#000000, 80), border_width=1) if barstate.islast // Row 0: Headers table.cell(t, 0, 0, "SYM", text_color=#888888, text_size=size.tiny) table.cell(t, 1, 0, "R:R", text_color=#888888, text_size=size.tiny) table.cell(t, 2, 0, "LONG", text_color=#888888, text_size=size.tiny) table.cell(t, 3, 0, "SHORT", text_color=#888888, text_size=size.tiny) table.cell(t, 4, 0, "ZONE", text_color=#888888, text_size=size.tiny) table.cell(t, 5, 0, "GATE", text_color=#888888, text_size=size.tiny) table.cell(t, 6, 0, "CANDLE", text_color=#888888, text_size=size.tiny) table.cell(t, 7, 0, "SWEEP", text_color=#888888, text_size=size.tiny) table.cell(t, 8, 0, "RSI", text_color=#888888, text_size=size.tiny) // Row 1: Data string candle_status = long_pass and short_pass ? "BOTH" : long_pass ? "GREEN" : short_pass ? "RED" : "DEAD" color candle_bg = long_pass and short_pass ? color.yellow : long_pass ? color.green : short_pass ? color.red : color.gray // Create GATE status text string gate_status = "" color gate_bg = color.new(#000000, 40) if long_pass and short_pass gate_status := "BOTH OPEN" gate_bg := color.new(color.yellow, 30) else if long_pass gate_status := "LONG OPEN" gate_bg := color.new(color.green, 30) else if short_pass gate_status := "SHORT OPEN" gate_bg := color.new(color.red, 30) else // Gate is closed - show the primary veto reason if loss_limit gate_status := "LOSS LIMIT" else if is_rsw gate_status := "RSW" else if rr_fail gate_status := "R:R FAIL" else if long_trap or short_trap gate_status := "ZONE TRAP" else if long_nq_fail or short_nq_fail gate_status := "NQ FAIL" else if long_target_blocked or short_target_blocked gate_status := "BLOCKED" else gate_status := "CLOSED" gate_bg := color.new(color.gray, 30) table.cell(t, 0, 1, "MES", text_color=#FF9800, text_size=size.tiny) table.cell(t, 1, 1, str.tostring(dyn_rr, "#.#") + "R", bgcolor=dyn_rr < rr_floor ? color.red : color.green, text_color=color.black, text_size=size.tiny) table.cell(t, 2, 1, str.tostring(long_target, "#.##"), text_color=color.green, bgcolor=color.new(#000000, 40), text_size=size.tiny) table.cell(t, 3, 1, str.tostring(short_target, "#.##"), text_color=color.red, bgcolor=color.new(#000000, 40), text_size=size.tiny) string zone_text = in_red ? "RED" : in_grn ? "GREEN" : "CLEAN" zone_text += " | G:" + str.tostring(r_ghosts) + "/" + str.tostring(g_ghosts) table.cell(t, 4, 1, zone_text, bgcolor=(in_red or in_grn) ? color.new(color.red, 40) : color.new(color.green, 40), text_color=color.white, text_size=size.tiny) // GATE cell - PROPERLY POPULATED table.cell(t, 5, 1, gate_status, bgcolor=gate_bg, text_color=color.white, text_size=size.tiny) // CANDLE cell table.cell(t, 6, 1, candle_status, bgcolor=candle_bg, text_color=color.black, text_size=size.tiny) // Sweep cell string sweep_text = sweep_fresh ? "SWEEP " + (last_sweep_dir == 1 ? "↓ DEMAND" : "↑ SUPPLY") : sweep_stale ? "STALE" : "NO SWEEP" color sweep_bg = sweep_fresh ? color.new(color.green, 20) : color.new(#000000, 40) table.cell(t, 7, 1, sweep_text, bgcolor=sweep_bg, text_color=color.white, text_size=size.tiny) // RSI cell table.cell(t, 8, 1, rsi_state, bgcolor=rsi_bg, text_color=rsi_tc, text_size=size.tiny) // Row 2: Grades table.cell(t, 2, 2, long_grade + " LONG", bgcolor=f_grade_bg(long_grade), text_color=f_grade_tc(long_grade), text_size=size.tiny) table.cell(t, 3, 2, short_grade + " SHORT", bgcolor=f_grade_bg(short_grade), text_color=f_grade_tc(short_grade), text_size=size.tiny)