Here is a professional-grade Pine Script (v5) implementation.
To elevate this from a basic template to a robust algorithmic script suitable for high-volume scalping, I have integrated several advanced features. The most important addition is the Asymmetric Profit Compounding model, which perfectly mirrors the philosophy from your forum post: protecting the initial deposit while exponentially scaling only the generated profits.
I also added dynamic volatility (ATR) tracking for stop-losses, trading session filters, and a real-time dashboard to monitor system health.
Code: Select all
//@version=5
strategy("Pro MM Engine: Asymmetric Scalping", overlay=true, initial_capital=10000, default_qty_type=strategy.cash, commission_type=strategy.commission.cash_per_contract, commission_value=3.0, margin_long=100, margin_short=100)
// =========================================================================
// 1. ADVANCED INPUTS & CONFIGURATION
// =========================================================================
grp_time = "Session Filters"
trade_session = input.session("0800-1700", title="Trading Session (e.g., London/NY)", group=grp_time)
use_session = input.bool(true, title="Restrict to Session?", group=grp_time)
grp_mm = "Advanced Money Management"
mm_type = input.string("Profit Compounding (Pro)", title="Position Sizing Model", options=["Linear", "Standard Exponential", "Profit Compounding (Pro)"], group=grp_mm)
// Core Risk Parameters
base_risk_pct = input.float(1.0, title="Base Risk % (Initial Capital)", step=0.1, group=grp_mm) / 100
compound_multi = input.float(2.0, title="Profit Compound Multiplier", step=0.1, group=grp_mm, tooltip="How aggressively to compound profits (e.g., 2.0 = risk 2% of accrued profits).")
max_risk_cap = input.float(5.0, title="Hard Risk Cap % per Trade", step=0.1, group=grp_mm) / 100
grp_vol = "Volatility & Exits (ATR)"
atr_len = input.int(14, title="ATR Length", group=grp_vol)
sl_mult = input.float(1.5, title="Stop Loss (ATR Multiplier)", step=0.1, group=grp_vol)
rr_ratio = input.float(2.0, title="Risk:Reward Ratio", step=0.1, group=grp_vol)
// =========================================================================
// 2. TIME & SESSION LOGIC
// =========================================================================
in_session = not use_session or not na(time(timeframe.period, trade_session))
// =========================================================================
// 3. DYNAMIC VOLATILITY & RISK PER UNIT
// =========================================================================
// Use ATR to adjust SL distance dynamically based on current market noise
atr_val = ta.atr(atr_len)
dynamic_sl_points = atr_val * sl_mult
dynamic_tp_points = dynamic_sl_points * rr_ratio
// Calculate monetary risk per contract/lot (Point Value * SL distance)
sl_risk_per_unit = dynamic_sl_points * syminfo.pointvalue
// =========================================================================
// 4. PRO POSITION SIZING ENGINE
// =========================================================================
var float initial_balance = strategy.initial_capital
float current_equity = strategy.equity
float total_profit = math.max(0, current_equity - initial_balance) // Only count positive PnL
float risk_amount = 0.0
if mm_type == "Linear"
// Strictly bases risk on the initial capital, ignoring all growth or drawdown
risk_amount := initial_balance * base_risk_pct
else if mm_type == "Standard Exponential"
// Standard compounding: Risks a flat % of the real-time equity
risk_amount := current_equity * base_risk_pct
else if mm_type == "Profit Compounding (Pro)"
// Asymmetric Compounding: Protects base capital, aggressive on profits
float base_risk_amount = initial_balance * base_risk_pct
float profit_risk_amount = total_profit * (base_risk_pct * compound_multi)
risk_amount := base_risk_amount + profit_risk_amount
// Apply Hard Risk Cap to prevent over-leveraging during extreme spikes
float max_allowed_risk = current_equity * max_risk_cap
risk_amount := math.min(risk_amount, max_allowed_risk)
// Final Contract Sizing Calculation
float position_size = sl_risk_per_unit > 0 ? (risk_amount / sl_risk_per_unit) : 0.0
// =========================================================================
// 5. ENTRY LOGIC (Momentum / Scalping Placeholder)
// =========================================================================
// Fast momentum crossover for scalping demonstration
fast_ema = ta.ema(close, 5)
slow_ema = ta.ema(close, 13)
trend_sma = ta.sma(close, 50) // Baseline trend filter
long_cond = in_session and close > trend_sma and ta.crossover(fast_ema, slow_ema)
short_cond = in_session and close < trend_sma and ta.crossunder(fast_ema, slow_ema)
// =========================================================================
// 6. TRADE EXECUTION
// =========================================================================
if long_cond and strategy.position_size == 0
strategy.entry("Long", strategy.long, qty=position_size)
strategy.exit("Exit Long", "Long", loss=dynamic_sl_points / syminfo.mintick, profit=dynamic_tp_points / syminfo.mintick)
if short_cond and strategy.position_size == 0
strategy.entry("Short", strategy.short, qty=position_size)
strategy.exit("Exit Short", "Short", loss=dynamic_sl_points / syminfo.mintick, profit=dynamic_tp_points / syminfo.mintick)
// Close all positions at the end of the session to prevent overnight slippage
if use_session and not in_session and in_session[1]
strategy.close_all(comment="Session Close")
// =========================================================================
// 7. REAL-TIME DASHBOARD (UI)
// =========================================================================
var table dash = table.new(position.bottom_right, 2, 4, border_width=1, border_color=color.new(color.gray, 50))
if barstate.islast
table.cell(dash, 0, 0, "MM Mode:", text_color=color.white, bgcolor=color.new(color.black, 20))
table.cell(dash, 1, 0, mm_type, text_color=color.yellow, bgcolor=color.new(color.black, 20))
table.cell(dash, 0, 1, "Account Equity:", text_color=color.white, bgcolor=color.new(color.black, 20))
table.cell(dash, 1, 1, str.tostring(current_equity, "#.##"), text_color=current_equity >= initial_balance ? color.green : color.red, bgcolor=color.new(color.black, 20))
table.cell(dash, 0, 2, "Current Risk ($):", text_color=color.white, bgcolor=color.new(color.black, 20))
table.cell(dash, 1, 2, str.tostring(risk_amount, "#.##"), text_color=color.white, bgcolor=color.new(color.black, 20))
table.cell(dash, 0, 3, "Lot / Qty Size:", text_color=color.white, bgcolor=color.new(color.black, 20))
table.cell(dash, 1, 3, str.tostring(position_size, "#.####"), text_color=color.white, bgcolor=color.new(color.black, 20))