Code: Select all
//@version=5
indicator("Terminal Gatekeeper: Risk & Context", overlay=true)
// =========================================================================
// 🎛️ SETTINGS & INPUTS
// =========================================================================
grp_time = "Session Parameters"
killzone_session = input.session("10:00-11:30", title="Killzone (Audit Window)", group=grp_time)
deadzone_session = input.session("11:30-13:00", title="Dead Zone (Hard Stop)", group=grp_time)
timezone = input.string("America/New_York", title="Timezone", group=grp_time)
grp_check = "Manual Process Checklist"
news_cleared = input.bool(false, title="[1] Macro Cleared?", group=grp_check)
levels_cleared = input.bool(false, title="[2] Inventory Flat?", group=grp_check)
risk_cleared = input.bool(false, title="[3] Risk Intact?", group=grp_check)
grp_ui = "Terminal Appearance"
hud_position = input.string("Bottom Right", title="HUD Position", options=["Top Right", "Bottom Right", "Bottom Left", "Top Left"], group=grp_ui)
// =========================================================================
// 📊 CONTEXT METRICS (ADR, VWAP, RVOL)
// =========================================================================
// 1. ADR Exhaustion
day_high = request.security(syminfo.tickerid, "D", high, lookahead=barmerge.lookahead_on)
day_low = request.security(syminfo.tickerid, "D", low, lookahead=barmerge.lookahead_on)
adr_14 = request.security(syminfo.tickerid, "D", ta.sma(high - low, 14), lookahead=barmerge.lookahead_on)
adr_exhaustion = adr_14 > 0 ? ((day_high - day_low) / adr_14) * 100 : 0
is_exhausted = adr_exhaustion > 90
// 2. Daily VWAP & Z-Score (Standard Deviation)
var float sumSrcVol = 0.0, var float sumVol = 0.0, var float sumSrcSrcVol = 0.0
if timeframe.change("D")
sumSrcVol := 0.0, sumVol := 0.0, sumSrcSrcVol := 0.0
sumSrcVol += hlcc4 * volume
sumVol += volume
sumSrcSrcVol += volume * math.pow(hlcc4, 2)
vwap_val = sumVol > 0 ? sumSrcVol / sumVol : close
variance = sumVol > 0 ? (sumSrcSrcVol / sumVol) - math.pow(vwap_val, 2) : 0
stdev = math.sqrt(math.max(0, variance))
z_score = stdev > 0 ? math.abs(close - vwap_val) / stdev : 0
is_extended = z_score > 2.0 // > 2 Standard Deviations is dangerous late in session
// 3. RVOL (Relative Volume)
avg_vol = ta.sma(volume, 50)
rvol = avg_vol > 0 ? volume / avg_vol : 0
is_thin = rvol < 0.75 // Liquidity drying up
// =========================================================================
// ⏱️ STATE MACHINE LOGIC
// =========================================================================
in_killzone = not na(time(timeframe.period, killzone_session, timezone))
in_deadzone = not na(time(timeframe.period, deadzone_session, timezone))
all_passed = news_cleared and levels_cleared and risk_cleared
// State Definition
string sys_state = "MONITORING"
color hdr_bg = color.new(#2A2E39, 0)
color hdr_txt = #D1D4DC
if in_deadzone
sys_state := "DESK CLOSED"
hdr_bg := color.new(#000000, 0)
hdr_txt := #808080
else if in_killzone and not all_passed
sys_state := "DANGER ZONE"
hdr_bg := color.new(#F23645, 20)
hdr_txt := #F23645
else if all_passed and in_killzone
sys_state := "GATE LOCKED"
hdr_bg := color.new(#089981, 20)
hdr_txt := #089981
// Background Dimming
bg_color = in_deadzone ? color.new(#000000, 85) : (in_killzone and not all_passed ? color.new(#F23645, 94) : (all_passed ? color.new(#089981, 96) : na))
bgcolor(bg_color, title="Zone Background")
// =========================================================================
// 🖥️ TERMINAL HUD RENDERING
// =========================================================================
var pos = hud_position == "Top Right" ? position.top_right :
hud_position == "Bottom Right" ? position.bottom_right :
hud_position == "Bottom Left" ? position.bottom_left : position.top_left
var table hud = table.new(pos, 2, 8, border_width=1, border_color=color.new(#434651, 50), frame_color=color.new(#434651, 50), frame_width=1)
row_bg = color.new(#131722, 10)
if barstate.islast
// Header
table.cell(hud, 0, 0, "LDN CLOSE: " + sys_state, bgcolor=hdr_bg, text_color=hdr_txt, text_font_family=font.family_monospace, colspan=2, text_size=size.small, text_halign=text.align_center)
// Divider: Process
table.cell(hud, 0, 1, "--- PROCESS ---", bgcolor=color.new(#131722, 0), text_color=#434651, text_font_family=font.family_monospace, colspan=2, text_size=size.tiny, text_halign=text.align_center)
// Checks
table.cell(hud, 0, 2, "Macro Cleared", bgcolor=row_bg, text_color=#D1D4DC, text_font_family=font.family_monospace, text_size=size.small, text_halign=text.align_left)
table.cell(hud, 1, 2, news_cleared ? "PASS" : "WAIT", bgcolor=row_bg, text_color=news_cleared ? #089981 : #F23645, text_font_family=font.family_monospace, text_size=size.small)
table.cell(hud, 0, 3, "Inventory Flat", bgcolor=row_bg, text_color=#D1D4DC, text_font_family=font.family_monospace, text_size=size.small, text_halign=text.align_left)
table.cell(hud, 1, 3, levels_cleared ? "PASS" : "WAIT", bgcolor=row_bg, text_color=levels_cleared ? #089981 : #F23645, text_font_family=font.family_monospace, text_size=size.small)
table.cell(hud, 0, 4, "Risk Limits", bgcolor=row_bg, text_color=#D1D4DC, text_font_family=font.family_monospace, text_size=size.small, text_halign=text.align_left)
table.cell(hud, 1, 4, risk_cleared ? "PASS" : "WAIT", bgcolor=row_bg, text_color=risk_cleared ? #089981 : #F23645, text_font_family=font.family_monospace, text_size=size.small)
// Divider: Context
table.cell(hud, 0, 5, "--- CONTEXT ---", bgcolor=color.new(#131722, 0), text_color=#434651, text_font_family=font.family_monospace, colspan=2, text_size=size.tiny, text_halign=text.align_center)
// Data Metrics
table.cell(hud, 0, 6, "ADR Exhst / RVOL", bgcolor=row_bg, text_color=#D1D4DC, text_font_family=font.family_monospace, text_size=size.small, text_halign=text.align_left)
table.cell(hud, 1, 6, str.tostring(math.round(adr_exhaustion, 0)) + "% / " + str.tostring(math.round(rvol, 2)), bgcolor=row_bg, text_color=(is_exhausted or is_thin) ? #E0B354 : #D1D4DC, text_font_family=font.family_monospace, text_size=size.small)
table.cell(hud, 0, 7, "VWAP Extension", bgcolor=row_bg, text_color=#D1D4DC, text_font_family=font.family_monospace, text_size=size.small, text_halign=text.align_left)
table.cell(hud, 1, 7, str.tostring(math.round(z_score, 2)) + " SD", bgcolor=row_bg, text_color=is_extended ? #F23645 : #D1D4DC, text_font_family=font.family_monospace, text_size=size.small)