ContractSizer.mqh sizes contracts from the account balance with three separate protections: a ladder (one contract per factor of balance, always a cap), a floor (no trading below the minimum capital) and a breaker (stops at a fraction of the balance peak and does not rearm by itself).

Deposits and withdrawals are read from the deal history (DEAL_TYPE_BALANCE) and shift the peak by the same amount, so a deposit made during a drawdown does not hide the drawdown. The peak is persisted under MQL5\Files and survives a terminal restart.

Constructor: CContractSizer(factor = 3000.0, maxContracts = 500, minContracts = 1, minCapital = 1500.0, maxDD = 0.0, peakFile = "contract_sizer_peak.txt") . Use: call ContractsToday(TimeLocal()) on every tick; it recomputes only at the day change. CapByBalance() holds even with manual lots. Rearm() is a manual decision.

Demo inputs: InpBalancePerContract = 3000, InpMinCapital = 1500, InpMaxDrawdown = 0.20, InpDemoDeposit = true.

The demo prints a 12-day simulated path (balance / peak / drop / contracts / event) with a deposit at the bottom of the drawdown, then runs the real class on the open account. Run it with InpDemoDeposit on and off and compare the "drop" column.

Limit: position sizing does not create an edge; it only multiplies whatever edge exists. Nothing is traded.