Code: Select all
//@version=5
strategy("Apex Risk Engine & Microstructure Controller", overlay=true, initial_capital=100000, calc_on_every_tick=true, margin_long=100, margin_short=100)
// ==========================================
// ⚙️ INPUTS: PROP FIRM RISK LIMITS
// ==========================================
grp_firm = "Prop Firm Constraints"
dailyHardStopPct = input.float(4.0, "Daily Hard Stop (%)", step=0.5, group=grp_firm, tooltip="Absolute daily ruin limit.")
trailStopPct = input.float(5.0, "Trailing Max DD (%)", step=0.5, group=grp_firm, tooltip="High-Water Mark trailing drawdown.")
maxRiskPerTrade = input.float(0.5, "Max Risk Per Trade (%)", step=0.1, group=grp_firm, tooltip="Locks position sizing to this max equity percentage.")
grp_tilt = "Tilt & Time Mechanics"
baseCooldown = input.int(5, "Base Cooldown (Min)", minval=1, group=grp_tilt)
escalationMult = input.int(3, "Loss Multiplier", minval=1, group=grp_tilt, tooltip="Consecutive loss timeout multiplier.")
maxConsecLosses = input.int(3, "Max Consecutive Losses", group=grp_tilt)
sessionStr = input.session("0930-1600", "Execution Window", group=grp_tilt)
maxBarsInTrade = input.int(10, "Time-In-Trade Abort (Bars)", group=grp_tilt, tooltip="Cuts a trade if it flatlines.")
// ==========================================
// 🧠 STATE TRACKING & HWM LOGIC
// ==========================================
var float startOfDayEquity = strategy.initial_capital
var float highWaterMark = strategy.initial_capital
var int consecLosses = 0
var int lastLossTime = na
var int closedTradeCount = 0
// Update High-Water Mark (HWM)
if strategy.equity > highWaterMark
highWaterMark := strategy.equity
// Reset Daily Metrics
isNewDay = ta.change(time("D"))
if isNewDay
startOfDayEquity := strategy.equity
consecLosses := 0
lastLossTime := na
// Trade Evaluation (Executes on trade close)
if strategy.closedtrades > closedTradeCount
lastProfit = strategy.closedtrades.profit(strategy.closedtrades - 1)
if lastProfit < 0
consecLosses += 1
lastLossTime := time
else
consecLosses := 0
closedTradeCount := strategy.closedtrades
// Calculate Drawdowns
dailyPnL_Pct = ((strategy.equity - startOfDayEquity) / startOfDayEquity) * 100
trailDD_Pct = ((strategy.equity - highWaterMark) / highWaterMark) * 100
// Limit Triggers
hitDailyStop = dailyPnL_Pct <= -dailyHardStopPct
hitTrailStop = trailDD_Pct <= -trailStopPct
hitConsecLossLimit = consecLosses >= maxConsecLosses
inSession = not na(time(timeframe.period, sessionStr))
// Escalating Cooldown Math
msPerMinute = 60 * 1000
currentCooldownMs = baseCooldown * math.pow(escalationMult, math.max(0, consecLosses - 1)) * msPerMinute
timeRemainingMs = not na(lastLossTime) ? (lastLossTime + currentCooldownMs) - time : 0
inCooldown = consecLosses > 0 and timeRemainingMs > 0
// Master Failsafe
isLockedOut = hitDailyStop or hitTrailStop or hitConsecLossLimit
masterClear = not isLockedOut and not inCooldown and inSession
// ==========================================
// 🖥️ TELEMETRY HUD
// ==========================================
bgColor = isLockedOut ? color.new(color.red, 85) : inCooldown ? color.new(color.orange, 85) : not inSession ? color.new(color.navy, 90) : na
bgcolor(bgColor, title="Controller State")
c_dark = color.rgb(15, 15, 15, 10), c_green = color.rgb(38, 166, 154), c_red = color.rgb(239, 83, 80), c_orange = color.rgb(255, 167, 38)
var table hud = table.new(position.bottom_right, 2, 6, bgcolor=c_dark, border_color=color.new(color.gray, 60), border_width=1)
if barstate.islast
table.cell(hud, 0, 0, "APEX RISK ENGINE", text_color=color.gray, text_size=size.small, text_halign=text.align_left)
table.cell(hud, 1, 0, "V2.0", text_color=color.gray, text_size=size.small, text_halign=text.align_right)
statusText = isLockedOut ? "FATAL LOCKOUT" : inCooldown ? "COOLDOWN (" + str.tostring(math.ceil(timeRemainingMs / msPerMinute)) + "m)" : inSession ? "ARMED & CLEAR" : "OUT OF SESSION"
table.cell(hud, 0, 1, "Status", text_color=color.white, text_size=size.normal, text_halign=text.align_left)
table.cell(hud, 1, 1, statusText, text_color=isLockedOut ? c_red : inCooldown ? c_orange : inSession ? c_green : color.gray, text_size=size.normal, text_halign=text.align_right)
table.cell(hud, 0, 2, "Daily PnL / Limit", text_color=color.white, text_size=size.normal, text_halign=text.align_left)
table.cell(hud, 1, 2, str.tostring(dailyPnL_Pct, "#.##") + "% / " + str.tostring(-dailyHardStopPct) + "%", text_color=dailyPnL_Pct < 0 ? c_red : c_green, text_halign=text.align_right)
table.cell(hud, 0, 3, "Trailing DD", text_color=color.white, text_size=size.normal, text_halign=text.align_left)
table.cell(hud, 1, 3, str.tostring(trailDD_Pct, "#.##") + "% / " + str.tostring(-trailStopPct) + "%", text_color=trailDD_Pct < -2.0 ? c_orange : c_green, text_halign=text.align_right)
table.cell(hud, 0, 4, "Consec. Losses", text_color=color.white, text_size=size.normal, text_halign=text.align_left)
table.cell(hud, 1, 4, str.tostring(consecLosses) + " / " + str.tostring(maxConsecLosses), text_color=consecLosses > 0 ? c_orange : c_green, text_halign=text.align_right)
// ==========================================
// 📉 RAW PRICE ACTION LOGIC (LIQUIDITY SWEEPS)
// ==========================================
// Identify market structure (15-bar swing lows/highs)
swingLow = ta.lowest(low, 15)[1]
swingHigh = ta.highest(high, 15)[1]
// Bullish Sweep: Price breaks below recent swing low, but closes above it (rejection)
bullishSweep = low < swingLow and close > swingLow and close > open
// Bearish Sweep: Price breaks above recent swing high, but closes below it (rejection)
bearishSweep = high > swingHigh and close < swingHigh and close < open
// Dynamic Position Sizing (Risk / Stop Distance)
riskAmount = strategy.equity * (maxRiskPerTrade / 100)
longStop = low - ta.atr(14) // Structural stop with ATR buffer
shortStop = high + ta.atr(14)
longQty = riskAmount / (close - longStop)
shortQty = riskAmount / (shortStop - close)
// Execution
if bullishSweep and masterClear and strategy.position_size == 0
strategy.entry("Sweep Long", strategy.long, qty=longQty)
strategy.exit("Exit Long", "Sweep Long", stop=longStop, limit=close + ((close - longStop) * 2)) // 2R Target
if bearishSweep and masterClear and strategy.position_size == 0
strategy.entry("Sweep Short", strategy.short, qty=shortQty)
strategy.exit("Exit Short", "Sweep Short", stop=shortStop, limit=close - ((shortStop - close) * 2)) // 2R Target
// Time-in-Trade Abort (Cut dead trades)
barsInTrade = bar_index - strategy.opentrades.entry_bar_index(0)
if strategy.position_size != 0 and barsInTrade >= maxBarsInTrade
strategy.close_all(comment="Time Abort")