mql5/Include/Mql5Book/MoneyManagement.mqh
younglubah-gmail 195db6ea13 new files added
2026-03-15 02:48:52 +02:00

136 lines
4.2 KiB
MQL5

#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);
}