#define MAX_PERCENT 10 // Maximum balance % used in money management // Risk-based money management double MoneyManagement(string pSymbol,double pFixedVol,double pPercent,int pStopPoints) { double tradeSize; if(pPercent > 0 && pStopPoints > 0) { if(pPercent > MAX_PERCENT) pPercent = MAX_PERCENT; double margin = AccountInfoDouble(ACCOUNT_BALANCE) * (pPercent / 100); double tickSize = SymbolInfoDouble(pSymbol,SYMBOL_TRADE_TICK_VALUE); tradeSize = (margin / pStopPoints) / tickSize; tradeSize = VerifyVolume(pSymbol,tradeSize); return(tradeSize); } else { tradeSize = pFixedVol; tradeSize = VerifyVolume(pSymbol,tradeSize); return(tradeSize); } } //+------------------------------------------------------------------+ //| Adaptive Money Management with Risk Distribution | //+------------------------------------------------------------------+ void MoneyManagementAdvanced(string symbol, double fixedVol, double percent, int stopPoints, double &lots, int &positionsCount) { // Safety checks if(percent <= 0 || stopPoints <= 0) { lots = VerifyVolume(symbol, fixedVol); positionsCount = 1; return; } if(percent > MAX_PERCENT) percent = MAX_PERCENT; double balance = AccountInfoDouble(ACCOUNT_BALANCE); double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE); double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); if(tickValue <= 0.0) tickValue = 1.0; // Total risk amount double totalRisk = balance * (percent / 100.0); // Risk split: 45% to lots, 55% to number of positions double lotsRisk = totalRisk * 0.85; double posRisk = totalRisk * 0.55; // Calculate lot size lots = (lotsRisk / (stopPoints * tickValue / tickSize)); lots = VerifyVolume(symbol, lots); // Calculate number of positions dynamically // Each position assumes risk of about 2% of posRisk double perPosRisk = balance * 0.01; positionsCount = (int)MathMax(1, MathRound(posRisk / perPosRisk)); // Apply leverage/margin safety (90% margin protocol) double equity = AccountInfoDouble(ACCOUNT_EQUITY); double usedMargin = AccountInfoDouble(ACCOUNT_MARGIN); double marginPercent = (usedMargin / equity) * 100.0; if(marginPercent > 90.0) { lots /= 2.0; positionsCount = MathMax(1, positionsCount / 2); } } //+------------------------------------------------------------------+ //| Calculate how many positions can be placed under same risk rules | //+------------------------------------------------------------------+ int PositionsAvailable(string pSymbol, double pFixedVol, double pPercent, int pStopPoints) { double tradeSize = MoneyManagement(pSymbol, pFixedVol, pPercent, pStopPoints); if(tradeSize <= 0.0) return 0; // --- Risk money per trade --- double balance = AccountInfoDouble(ACCOUNT_BALANCE); double riskPerTrade = balance * (pPercent / 100.0); // --- Tick info --- double tickValue = SymbolInfoDouble(pSymbol, SYMBOL_TRADE_TICK_VALUE); double stopValue = pStopPoints * tickValue * tradeSize; if(stopValue <= 0.0) return 0; // --- Maximum number of positions --- int count = (int)MathFloor(riskPerTrade / stopValue); if(count < 1) count = 1; // At least one trade is possible return count; } // Verify and adjust trade volume double VerifyVolume(string pSymbol,double pVolume) { double minVolume = SymbolInfoDouble(pSymbol,SYMBOL_VOLUME_MIN); double maxVolume = SymbolInfoDouble(pSymbol,SYMBOL_VOLUME_MAX); double stepVolume = SymbolInfoDouble(pSymbol,SYMBOL_VOLUME_STEP); double tradeSize; if(pVolume < minVolume) tradeSize = minVolume; else if(pVolume > maxVolume) tradeSize = maxVolume; else tradeSize = MathRound(pVolume / stepVolume) * stepVolume; if(stepVolume >= 0.1) tradeSize = NormalizeDouble(tradeSize,1); else tradeSize = NormalizeDouble(tradeSize,2); return(tradeSize); } // Calculate distance between order price and stop loss in points double StopPriceToPoints(string pSymbol,double pStopPrice, double pOrderPrice) { double stopDiff = MathAbs(pStopPrice - pOrderPrice); double getPoint = SymbolInfoDouble(pSymbol,SYMBOL_POINT); double priceToPoint = stopDiff / getPoint; return(priceToPoint); }