136 lines
4.2 KiB
MQL5
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);
| |||
}
|