Code: Select all
//@version=5
strategy("Institutional Risk Desk", overlay=true, initial_capital=10000, margin_long=100, margin_short=100, calc_on_every_tick=true)
// =========================================================================
// 1. RISK PARAMETERS (The Sunday Prep Inputs)
// =========================================================================
grp_risk = "Sunday Prep: Capital Risk"
maxLoss = input.float(500, "Daily Loss Limit ($)", step=50, group=grp_risk)
rValue = input.float(100, "Value of 1R ($)", step=10, group=grp_risk)
warnPct = input.float(80, "Warning Threshold (%)", step=5, minval=1, maxval=99, group=grp_risk)
grp_behav = "Sunday Prep: Behavioral Circuit Breakers"
maxTrades = input.int(10, "Max Trades Per Day", minval=1, group=grp_behav, tooltip="Forces you to pick A+ setups only.")
maxStreak = input.int(3, "Max Consecutive Losses", minval=1, group=grp_behav, tooltip="Halts trading to prevent tilt.")
grp_ui = "Environment Settings"
uiPos = input.string(position.bottom_right, "Dashboard Position", options=[position.top_right, position.bottom_right, position.bottom_left], group=grp_ui)
bgFlash = input.bool(true, "Flash Chart Background on Halt", group=grp_ui)
// =========================================================================
// 2. NATIVE ENGINE ENFORCEMENT
// =========================================================================
strategy.risk.max_intraday_loss(maxLoss, strategy.cash)
// =========================================================================
// 3. DAILY STATE & INTRADAY METRICS TRACKING
// =========================================================================
var float startOfDayEquity = na
var float peakDailyEquity = na
var int tradesToday = 0
var int consecLosses = 0
var bool warnTriggered = false
var bool haltTriggered = false
var int lastClosedTrades = 0
// Reset state on new daily session
isNewDay = ta.change(time("D"))
if isNewDay
startOfDayEquity := strategy.equity
peakDailyEquity := strategy.equity
tradesToday := 0
consecLosses := 0
warnTriggered := false
haltTriggered := false
lastClosedTrades := strategy.closedtrades
// Track Intraday Peak Equity
peakDailyEquity := math.max(peakDailyEquity, strategy.equity)
// Track Closed Trades & Streaks
if strategy.closedtrades > lastClosedTrades
tradesToday += (strategy.closedtrades - lastClosedTrades)
// Check if the last trade was a loser
lastTradeProfit = strategy.closedtrades.profit(strategy.closedtrades - 1)
if lastTradeProfit < 0
consecLosses += 1
else
consecLosses := 0
lastClosedTrades := strategy.closedtrades
// Calculate real-time metrics
currentDailyPnL = strategy.equity - startOfDayEquity
peakDrawdown = strategy.equity - peakDailyEquity
pnlInR = currentDailyPnL / rValue
limitInR = maxLoss / rValue
// Calculate utilization (0% to 100%+)
lossAmount = math.max(0, -currentDailyPnL)
utilization = (lossAmount / maxLoss) * 100
// =========================================================================
// 4. BEHAVIORAL HALT LOGIC
// =========================================================================
// Trigger conditions
limitHit = utilization >= 100
tiltHit = consecLosses >= maxStreak
overtradeHit = tradesToday >= maxTrades
warnHit = utilization >= warnPct and not (limitHit or tiltHit or overtradeHit)
// Master Halt boolean
isHalted = limitHit or tiltHit or overtradeHit
// Cancel orders and flatten if behaviorally halted (since native risk only handles cash loss)
if (tiltHit or overtradeHit) and not limitHit
strategy.close_all(comment="BEHAVIORAL HALT")
strategy.cancel_all()
// Alerts
if warnHit and not warnTriggered
alert("RISK WARNING: Approaching daily limit.", alert.freq_once_per_bar)
warnTriggered := true
if isHalted and not haltTriggered
haltReason = limitHit ? "HARD LIMIT MET" : (tiltHit ? "TILT BREAKER: CONSECUTIVE LOSSES" : "OVERTRADING CAP MET")
alert("TRADING HALTED: " + haltReason, alert.freq_once_per_bar)
haltTriggered := true
// Physical Override: Red for Cash Limit, Purple for Behavioral Halt
haltColor = limitHit ? color.new(color.red, 85) : ((tiltHit or overtradeHit) ? color.new(color.purple, 85) : na)
bgcolor(bgFlash and isHalted ? haltColor : na, title="Environment Override")
// =========================================================================
// 5. HUD (HEADS UP DISPLAY)
// =========================================================================
var table dash = table.new(uiPos, 2, 7, border_width=1, border_color=color.new(#1e222d, 0), frame_color=color.new(#2a2e39, 0), frame_width=2)
if barstate.islast
statusBg = isHalted ? color.new(color.red, 30) : (warnHit ? color.new(color.orange, 30) : color.new(#00acc1, 50))
valColor = currentDailyPnL >= 0 ? color.lime : (limitHit ? color.red : color.orange)
rowBg = color.new(#131722, 10)
lblColor = color.new(color.silver, 20)
// Header
table.cell(dash, 0, 0, "RISK DESK: ACTIVE", text_color=color.white, bgcolor=statusBg, text_halign=text.align_center, text_font_family=font.family_monospace, text_size=size.small)
table.merge_cells(dash, 0, 0, 1, 0)
// Core Metrics
table.cell(dash, 0, 1, " Daily PnL", text_color=lblColor, bgcolor=rowBg, text_halign=text.align_left, text_size=size.small)
table.cell(dash, 1, 1, (currentDailyPnL >= 0 ? "+$" : "-$") + str.tostring(math.abs(currentDailyPnL), "#.##") + " ", text_color=valColor, bgcolor=rowBg, text_halign=text.align_right, text_font_family=font.family_monospace, text_size=size.small)
table.cell(dash, 0, 2, " Target In R", text_color=lblColor, bgcolor=rowBg, text_halign=text.align_left, text_size=size.small)
table.cell(dash, 1, 2, (pnlInR >= 0 ? "+" : "") + str.tostring(pnlInR, "#.##") + " R ", text_color=valColor, bgcolor=rowBg, text_halign=text.align_right, text_font_family=font.family_monospace, text_size=size.small)
// Drawdown
table.cell(dash, 0, 3, " Peak Drawdown", text_color=lblColor, bgcolor=rowBg, text_halign=text.align_left, text_size=size.small)
table.cell(dash, 1, 3, "$" + str.tostring(math.round(peakDrawdown, 2)) + " ", text_color=color.gray, bgcolor=rowBg, text_halign=text.align_right, text_font_family=font.family_monospace, text_size=size.small)
// Behavioral Stats
table.cell(dash, 0, 4, " Trades Today", text_color=lblColor, bgcolor=rowBg, text_halign=text.align_left, text_size=size.small)
table.cell(dash, 1, 4, str.tostring(tradesToday) + " / " + str.tostring(maxTrades) + " ", text_color=(overtradeHit ? color.red : color.white), bgcolor=rowBg, text_halign=text.align_right, text_font_family=font.family_monospace, text_size=size.small)
table.cell(dash, 0, 5, " Loss Streak", text_color=lblColor, bgcolor=rowBg, text_halign=text.align_left, text_size=size.small)
table.cell(dash, 1, 5, str.tostring(consecLosses) + " / " + str.tostring(maxStreak) + " ", text_color=(tiltHit ? color.red : color.white), bgcolor=rowBg, text_halign=text.align_right, text_font_family=font.family_monospace, text_size=size.small)
// Halt Reason Output
haltText = limitHit ? "MAX LOSS HIT" : (tiltHit ? "TILT HALT" : (overtradeHit ? "OVERTRADING CAP" : (str.tostring(utilization, "#.#") + "% Risk Used")))
table.cell(dash, 0, 6, isHalted ? haltText : haltText, text_color=color.white, bgcolor=statusBg, text_halign=text.align_center, text_font_family=font.family_monospace, text_size=size.small)
table.merge_cells(dash, 0, 6, 1, 6)
// =========================================================================
// 6. PRICE ACTION DUMMY STRATEGY (Engulfing Placeholder)
// =========================================================================
// Replaced MAs with basic PA structure: Bullish/Bearish Engulfing
bullEngulfing = close > open[1] and open < close[1] and close[1] < open[1]
bearEngulfing = close < open[1] and open > close[1] and close[1] > open[1]
// Only allow execution if the Master Halt boolean is false
if not isHalted
if bullEngulfing
strategy.entry("Long", strategy.long)
if bearEngulfing
strategy.entry("Short", strategy.short)