Code: Select all
//@version=5
indicator("Institutional Execution & Risk Engine", overlay=true)
// =========================================================================
// INPUTS: STRICT ENTRY PROTOCOL
// =========================================================================
grp_exec = "1. Hard Execution Parameters"
invalPrice = input.float(0.0, title="[REQUIRED] Invalidation Price", group=grp_exec, tooltip="0.0 locks the execution HUD.")
targetPrice = input.float(0.0, title="[OPTIONAL] Target Price", group=grp_exec)
spreadPips = input.float(1.2, title="Spread + Slippage Est. (Pips)", group=grp_exec, step=0.1)
grp_risk = "2. Capital Allocation"
acctSize = input.float(100000.0, title="Account Balance ($)", group=grp_risk)
riskPct = input.float(1.0, title="Risk Exposure (%)", group=grp_risk, step=0.1)
// =========================================================================
// VOLATILITY & TICK DYNAMICS
// =========================================================================
isJpy = str.contains(syminfo.currency, "JPY") or str.contains(syminfo.tickerid, "JPY")
pipSize = syminfo.mintick * (syminfo.type == "forex" ? (isJpy ? 100 : 10) : 1)
tickVal = syminfo.pointvalue
// State Flags
isArmed = invalPrice != 0.0
isLong = isArmed and (invalPrice < close)
isShort = isArmed and (invalPrice > close)
// =========================================================================
// RISK MATHEMATICS
// =========================================================================
riskCap = acctSize * (riskPct / 100)
distPipsRaw = isArmed ? math.abs(close - invalPrice) / pipSize : 0.0
totalRiskPips = distPipsRaw + spreadPips
// Institutional position sizing (Contract / Lot normalization)
pipValuePerLot = tickVal * (syminfo.type == "forex" ? (isJpy ? 1000 : 100000) : 1) * syminfo.mintick
lotSize = (totalRiskPips > 0 and pipValuePerLot > 0) ? riskCap / (totalRiskPips * (pipValuePerLot / pipSize)) : 0.0
// Expectancy (Net of Spread)
distTargetRaw = targetPrice != 0.0 ? math.abs(targetPrice - close) / pipSize : 0.0
netRewardPips = math.max(0.0, distTargetRaw - spreadPips)
netRMultiple = totalRiskPips > 0 ? netRewardPips / totalRiskPips : 0.0
// =========================================================================
// VISUALS: STRUCTURAL LEVELS
// =========================================================================
lineColor = isArmed ? (isLong ? color.new(color.maroon, 0) : color.new(color.maroon, 0)) : na
plot(isArmed ? invalPrice : na, color=lineColor, style=plot.style_cross, linewidth=2, title="Hard Invalidation")
plot(targetPrice != 0.0 ? targetPrice : na, color=color.new(color.teal, 30), style=plot.style_circles, linewidth=2, title="Take Profit")
// =========================================================================
// VISUALS: INSTITUTIONAL HUD
// =========================================================================
var tbl = table.new(position.bottom_right, 2, 7, border_width=1, border_color=color.rgb(30, 30, 30), frame_color=color.rgb(15, 15, 15), frame_width=2)
if barstate.islast
// Header
table.cell(tbl, 0, 0, "SYSTEM STATUS", bgcolor=color.rgb(15, 15, 15), text_color=color.gray, text_size=size.small, text_halign=text.align_left)
table.cell(tbl, 1, 0, isArmed ? "ARMED" : "LOCKED (AWAITING INPUT)", bgcolor=isArmed ? color.rgb(10, 60, 30) : color.rgb(80, 15, 15), text_color=color.white, text_size=size.small, text_halign=text.align_right)
// Invalidation Node
table.cell(tbl, 0, 1, "M15 Invalidation Node", bgcolor=color.rgb(22, 22, 22), text_color=color.silver, text_size=size.normal, text_halign=text.align_left)
table.cell(tbl, 1, 1, isArmed ? str.tostring(invalPrice) : "---", bgcolor=color.rgb(22, 22, 22), text_color=color.white, text_size=size.normal, text_halign=text.align_right)
// Adjusted Risk
table.cell(tbl, 0, 2, "Stop (Pips + Spread)", bgcolor=color.rgb(26, 26, 26), text_color=color.silver, text_size=size.normal, text_halign=text.align_left)
table.cell(tbl, 1, 2, isArmed ? str.tostring(math.round(totalRiskPips, 1)) : "---", bgcolor=color.rgb(26, 26, 26), text_color=color.white, text_size=size.normal, text_halign=text.align_right)
// Target Lot Size
isOversized = lotSize < 0.01
table.cell(tbl, 0, 3, "Execution Lot Size", bgcolor=color.rgb(22, 22, 22), text_color=color.silver, text_size=size.normal, text_halign=text.align_left)
table.cell(tbl, 1, 3, isArmed ? (isOversized ? "VIOLATION: < 0.01" : str.tostring(math.round(lotSize, 2))) : "---", bgcolor=isOversized and isArmed ? color.rgb(80, 15, 15) : color.rgb(22, 22, 22), text_color=isOversized ? color.white : color.rgb(100, 200, 255), text_size=size.normal, text_halign=text.align_right)
// Net Expectancy
isValidR = netRMultiple >= 2.0
table.cell(tbl, 0, 4, "Net Expectancy (R)", bgcolor=color.rgb(26, 26, 26), text_color=color.silver, text_size=size.normal, text_halign=text.align_left)
table.cell(tbl, 1, 4, targetPrice != 0 ? str.tostring(math.round(netRMultiple, 2)) + " R" : "---", bgcolor=color.rgb(26, 26, 26), text_color=targetPrice != 0 ? (isValidR ? color.rgb(10, 200, 100) : color.rgb(200, 100, 50)) : color.silver, text_size=size.normal, text_halign=text.align_right)
// Vocalization Override
table.cell(tbl, 0, 5, "VOCALIZE PARAMETERS", bgcolor=color.rgb(15, 15, 15), text_color=color.gray, text_size=size.small, text_halign=text.align_left)
table.cell(tbl, 1, 5, "PENDING", bgcolor=color.rgb(15, 15, 15), text_color=color.gray, text_size=size.small, text_halign=text.align_right)