Re: Exponencial money management with profit only
Posted: Tue Sep 22, 2026 9:13 am
MetaTrader 5 (MQL5) Implementation
Code: Select all
//+------------------------------------------------------------------+
//| HouseMoney_Engine_MT5.mq5 |
//+------------------------------------------------------------------+
#property strict
#include <Trade\Trade.mqh>
// --- Risk Management Engine ---
input double InpReferenceBalance = 100000.0; // Reference Baseline (0 = use current balance)
input double InpBaseRiskPct = 0.5; // Base Risk (%)
input double InpScaledRiskPct = 1.5; // Scaled Risk (%)
input double InpProfitBuffer = 5.0; // Activation Threshold (%)
input double InpHardStopEq = 10.0; // Max Drawdown Killswitch (%)
// --- Execution Parameters ---
input int InpSLPoints = 150; // Stop Loss (Points)
input int InpTPPoints = 350; // Take Profit (Points)
input ulong InpMagicNumber = 77777; // Magic Number
double initBalance;
datetime lastBarTime;
CTrade trade;
//+------------------------------------------------------------------+
int OnInit() {
initBalance = (InpReferenceBalance > 0) ? InpReferenceBalance : AccountInfoDouble(ACCOUNT_BALANCE);
trade.SetExpertMagicNumber(InpMagicNumber);
lastBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnTick() {
datetime currentTime = iTime(_Symbol, PERIOD_CURRENT, 0);
if(currentTime == lastBarTime) return;
lastBarTime = currentTime;
double currentEq = AccountInfoDouble(ACCOUNT_EQUITY);
double killswitchEq = initBalance * (1.0 - (InpHardStopEq / 100.0));
double targetEq = initBalance * (1.0 + (InpProfitBuffer / 100.0));
// Hard Stop Killswitch
if(currentEq <= killswitchEq) {
CloseAllPositions();
Print("HARD STOP: Drawdown limit breached. Trading halted.");
ExpertRemove();
return;
}
// Only allow one open position
if(PositionsTotal() > 0) return;
// Buffer arrays for price data
double high[], low[], close[];
ArraySetAsSeries(high, true); ArraySetAsSeries(low, true); ArraySetAsSeries(close, true);
if(CopyHigh(_Symbol, PERIOD_CURRENT, 0, 8, high) <= 0) return;
if(CopyLow(_Symbol, PERIOD_CURRENT, 0, 8, low) <= 0) return;
if(CopyClose(_Symbol, PERIOD_CURRENT, 0, 3, close) <= 0) return;
// Structure detection: 5-bar lookback pivot (indexes 2 through 6)
double lastPivotHigh = 0;
double lastPivotLow = 999999;
for(int i = 2; i <= 6; i++) {
if(high[i] > lastPivotHigh) lastPivotHigh = high[i];
if(low[i] < lastPivotLow) lastPivotLow = low[i];
}
// Sweep conditions (Bar 1 swept the pivot and closed back inside)
bool sweepShort = high[1] > lastPivotHigh && close[1] < lastPivotHigh;
bool sweepLong = low[1] < lastPivotLow && close[1] > lastPivotLow;
if(!sweepShort && !sweepLong) return;
// Dynamic Size Calculation
double activeRisk = (currentEq >= targetEq) ? InpScaledRiskPct : InpBaseRiskPct;
double riskCapital = currentEq * (activeRisk / 100.0);
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
if(tickValue == 0 || tickSize == 0) return;
// Normalization for points/ticks
double pointMultiplier = _Point / tickSize;
double adjustedSL = InpSLPoints * pointMultiplier;
double rawLots = riskCapital / (adjustedSL * tickValue);
double step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotSize = MathFloor(rawLots / step) * step;
if(lotSize < minLot) lotSize = minLot;
if(lotSize > maxLot) lotSize = maxLot;
// Execution
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if(sweepLong) {
double sl = NormalizeDouble(ask - (InpSLPoints * _Point), _Digits);
double tp = NormalizeDouble(ask + (InpTPPoints * _Point), _Digits);
trade.Buy(lotSize, _Symbol, ask, sl, tp, "HouseMoney L");
}
else if(sweepShort) {
double sl = NormalizeDouble(bid + (InpSLPoints * _Point), _Digits);
double tp = NormalizeDouble(bid - (InpTPPoints * _Point), _Digits);
trade.Sell(lotSize, _Symbol, bid, sl, tp, "HouseMoney S");
}
}
//+------------------------------------------------------------------+
void CloseAllPositions() {
for(int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if(PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == InpMagicNumber) {
trade.PositionClose(ticket);
}
}
}