// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © LiquidityEdgeFutures (https://liquidityedgefutures.com) // ========================================================================================================= // LIQUIDITY EDGE | PROP FIRM COMBINE GUARDIAN & POSITION SIZER [FREE COMMUNITY EDITION] // Institutional Risk Management & Contract Sizer for Apex Trader Funding, Topstep, MyFundedFutures // // Features: // - Built-in presets for $25k, $50k, $100k, $150k Prop Firm Combines // - Automatic contract sizing for CME NQ1! / MNQ1! and ES1! / MES1! // - Stop-loss point/tick risk calculator with dollar risk telemetry // - Consecutive Loss Runway counter (know exactly how many bullets you have before blowout) // - Real-time Circuit Breaker lockout warning when daily loss limit is hit // ========================================================================================================= //@version=5 indicator("Liquidity Edge - Prop Firm Combine Risk Guardian", shorttitle="LE - Combine Guardian", overlay=true) // --------------------------------------------------------------------------------------------------------- // INPUT SETTINGS // --------------------------------------------------------------------------------------------------------- var string G_ACCOUNT = "1. Prop Account Configuration" var string G_TRADE = "2. Trade & Stop Parameters" var string G_HUD = "3. Display Settings" // Prop Account Presets string i_accountTier = input.string("$50,000 Combine (Apex/Topstep)", "Account Tier", options=["$25,000 Combine", "$50,000 Combine (Apex/Topstep)", "$100,000 Combine", "$150,000 Combine", "Custom Account"], group=G_ACCOUNT) float i_customDrawdown = input.float(2500.0, "Custom Total Max Drawdown ($)", group=G_ACCOUNT) float i_customDailyCap = input.float(300.0, "Custom Max Daily Loss Cap ($)", group=G_ACCOUNT) // Resolve Drawdown and Daily Cap based on tier float maxDrawdown = 2500.0 float dailyLossCap = 300.0 if i_accountTier == "$25,000 Combine" maxDrawdown := 1500.0 dailyLossCap := 250.0 else if i_accountTier == "$50,000 Combine (Apex/Topstep)" maxDrawdown := 2500.0 dailyLossCap := 300.0 else if i_accountTier == "$100,000 Combine" maxDrawdown := 3000.0 dailyLossCap := 600.0 else if i_accountTier == "$150,000 Combine" maxDrawdown := 5000.0 dailyLossCap := 1000.0 else maxDrawdown := i_customDrawdown dailyLossCap := i_customDailyCap // Trade Parameters float i_stopPoints = input.float(15.0, "Your Planned Stop Loss (Points)", minval=1.0, tooltip="For NQ, 15 points = 60 ticks.", group=G_TRADE) int i_mnqContracts = input.int(2, "Executed MNQ Contracts", minval=1, maxval=20, tooltip="Number of Micro MNQ contracts you plan to enter.", group=G_TRADE) float i_currentDayPnl= input.float(0.0, "Current Daily Realized P&L ($)", tooltip="Update this after each trade to monitor your live drawdown runway.", group=G_TRADE) // Point value detection // CME NQ = $20/pt, MNQ = $2/pt | CME ES = $50/pt, MES = $5/pt float pointValueMicro = 2.0 // default MNQ float pointValueMini = 20.0 // default NQ if str.contains(syminfo.ticker, "ES") or str.contains(syminfo.ticker, "MES") pointValueMicro := 5.0 pointValueMini := 50.0 else pointValueMicro := 2.0 pointValueMini := 20.0 // Display Options string i_hudPosition = input.string("Top Left", "Guardian HUD Position", options=["Top Left", "Bottom Left", "Top Right", "Bottom Right"], group=G_HUD) // --------------------------------------------------------------------------------------------------------- // RISK ENGINE CALCULATIONS // --------------------------------------------------------------------------------------------------------- // Dollar risk for the planned trade on Micro MNQ float tradeRiskMNQ = i_stopPoints * pointValueMicro * i_mnqContracts // Dollar risk if executed on 1 Full Mini contract float tradeRiskNQ = i_stopPoints * pointValueMini * 1 // Consecutive loss runway on current MNQ sizing float remainingDailyRisk = math.max(0.0, dailyLossCap + i_currentDayPnl) int bulletsRemaining = math.floor(remainingDailyRisk / tradeRiskMNQ) // Safe max MNQ sizing so 1 single loss does NOT exceed 50% of daily loss cap float maxSingleLossCap = dailyLossCap * 0.50 int recommendedMaxMNQ = math.max(1, math.floor(maxSingleLossCap / (i_stopPoints * pointValueMicro))) // Circuit breaker check bool isCircuitBreakerHit = i_currentDayPnl <= -dailyLossCap // --------------------------------------------------------------------------------------------------------- // ON-CHART HUD DASHBOARD // --------------------------------------------------------------------------------------------------------- hud_pos = i_hudPosition == "Top Left" ? position.top_left : i_hudPosition == "Bottom Left" ? position.bottom_left : i_hudPosition == "Top Right" ? position.top_right : position.bottom_right var table guardianHud = table.new(hud_pos, 2, 8, bgcolor=color.new(#030712, 10), border_color=color.new(#1E2D48, 30), border_width=1) if barstate.islast // Header Row color headerBg = isCircuitBreakerHit ? #EF4444 : #0E1626 table.cell(guardianHud, 0, 0, "COMBINE GUARDIAN", text_color=#F8FAFC, text_size=size.small, text_font_family=font.family_monospace, bgcolor=headerBg) table.cell(guardianHud, 1, 0, isCircuitBreakerHit ? "LOCKOUT TRIGGERED" : "RISK ONLINE", text_color=(isCircuitBreakerHit ? #FFFFFF : #38BDF8), text_size=size.small, text_font_family=font.family_monospace, bgcolor=headerBg) // Account & Daily Cap table.cell(guardianHud, 0, 1, "Account Tier", text_color=#94A3B8, text_size=size.tiny, text_font_family=font.family_monospace) table.cell(guardianHud, 1, 1, i_accountTier, text_color=#F8FAFC, text_size=size.tiny, text_font_family=font.family_monospace) table.cell(guardianHud, 0, 2, "Daily Loss Cap", text_color=#94A3B8, text_size=size.tiny, text_font_family=font.family_monospace) table.cell(guardianHud, 1, 2, "$" + str.tostring(dailyLossCap, "#") + " Max Daily", text_color=#EF4444, text_size=size.tiny, text_font_family=font.family_monospace) // Planned Trade Risk table.cell(guardianHud, 0, 3, "Planned Stop Loss", text_color=#94A3B8, text_size=size.tiny, text_font_family=font.family_monospace) table.cell(guardianHud, 1, 3, str.tostring(i_stopPoints, "#.#") + " pts (" + str.tostring(i_stopPoints * 4, "#") + " ticks)", text_color=#F59E0B, text_size=size.tiny, text_font_family=font.family_monospace) table.cell(guardianHud, 0, 4, "Current Trade Risk", text_color=#94A3B8, text_size=size.tiny, text_font_family=font.family_monospace) string riskStr = "$" + str.tostring(tradeRiskMNQ, "#.##") + " (" + str.tostring(i_mnqContracts) + " MNQ)" color riskCol = tradeRiskMNQ <= (dailyLossCap * 0.5) ? #10B981 : #EF4444 table.cell(guardianHud, 1, 4, riskStr, text_color=riskCol, text_size=size.tiny, text_font_family=font.family_monospace) // Rec Size & Full Mini Comparison table.cell(guardianHud, 0, 5, "Recommended Max Sizing", text_color=#94A3B8, text_size=size.tiny, text_font_family=font.family_monospace) table.cell(guardianHud, 1, 5, str.tostring(recommendedMaxMNQ) + " Micro MNQ", text_color=#10B981, text_size=size.tiny, text_font_family=font.family_monospace) // Bullets Remaining table.cell(guardianHud, 0, 6, "Loss Runway Today", text_color=#94A3B8, text_size=size.tiny, text_font_family=font.family_monospace) string bulletStr = str.tostring(bulletsRemaining) + " stopouts allowed" color bulletCol = bulletsRemaining >= 3 ? #10B981 : (bulletsRemaining >= 1 ? #F59E0B : #EF4444) table.cell(guardianHud, 1, 6, bulletStr, text_color=bulletCol, text_size=size.tiny, text_font_family=font.family_monospace) // Daily Realized Status table.cell(guardianHud, 0, 7, "Today's Realized P&L", text_color=#94A3B8, text_size=size.tiny, text_font_family=font.family_monospace) string pnlStr = (i_currentDayPnl >= 0 ? "+$" : "-$") + str.tostring(math.abs(i_currentDayPnl), "#.##") color pnlCol = i_currentDayPnl > 0 ? #10B981 : (i_currentDayPnl < 0 ? #EF4444 : #94A3B8) table.cell(guardianHud, 1, 7, pnlStr, text_color=pnlCol, text_size=size.tiny, text_font_family=font.family_monospace) // --------------------------------------------------------------------------------------------------------- // FULL SCREEN LOCKOUT WARNING IF CIRCUIT BREAKER HIT // --------------------------------------------------------------------------------------------------------- bgcolor(isCircuitBreakerHit ? color.new(#EF4444, 80) : na, title="Daily Loss Circuit Breaker Hit") alertcondition(isCircuitBreakerHit, title="Combine Daily Loss Cap Hit", message="[Liquidity Edge] 🛑 Daily loss cap reached! Close your platform and walk away to protect your funded account.")