Initialize project in MT5 Experts directory
This commit is contained in:
+29
-9
@@ -1,11 +1,16 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Risk/PositionSizer.mqh |
|
||||
//| ATR-based Position Sizing with Dynamic Risk Multiplier |
|
||||
//| Reduces size after losses, increases after wins |
|
||||
//+------------------------------------------------------------------+
|
||||
#ifndef __POSITION_SIZER_MQH__
|
||||
#define __POSITION_SIZER_MQH__
|
||||
|
||||
#include "../Core/Config.mqh"
|
||||
#include "../Core/State.mqh"
|
||||
#include "../Risk/Protection.mqh"
|
||||
|
||||
extern CProtection g_protection;
|
||||
|
||||
class CPositionSizer
|
||||
{
|
||||
@@ -16,21 +21,32 @@ private:
|
||||
public:
|
||||
bool Init(const AssetProfile &profile, double maxRisk)
|
||||
{
|
||||
m_profile = profile; m_maxRiskPercent = maxRisk;
|
||||
Print("[PositionSizer] Max risk per trade: ", maxRisk, "%");
|
||||
m_profile = profile;
|
||||
m_maxRiskPercent = maxRisk;
|
||||
Print("[PositionSizer] Max risk per trade: ", maxRisk, "% (with dynamic multiplier)");
|
||||
return true;
|
||||
}
|
||||
|
||||
void Calculate(TradeParams ¶ms, const SignalData &signal, const EAState &state)
|
||||
{
|
||||
params.isValid = false; params.rejectReason = "";
|
||||
params.isValid = false;
|
||||
params.rejectReason = "";
|
||||
|
||||
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
|
||||
if(equity <= 0) { params.rejectReason = "Invalid account equity"; return; }
|
||||
double riskAmount = equity * (m_maxRiskPercent / 100.0);
|
||||
|
||||
// Apply dynamic risk multiplier based on recent performance
|
||||
double riskMultiplier = g_protection.GetRiskMultiplier();
|
||||
double adjustedRiskPercent = m_maxRiskPercent * riskMultiplier;
|
||||
|
||||
double riskAmount = equity * (adjustedRiskPercent / 100.0);
|
||||
double slDistance = MathAbs(signal.entryPrice - signal.slPrice);
|
||||
if(slDistance <= 0) { params.rejectReason = "Invalid SL distance"; return; }
|
||||
|
||||
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
|
||||
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
|
||||
if(tickValue <= 0 || tickSize <= 0) { params.rejectReason = "Invalid tick value/size"; return; }
|
||||
|
||||
double slTicks = slDistance / tickSize;
|
||||
double lotSize = riskAmount / (slTicks * tickValue);
|
||||
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
|
||||
@@ -56,13 +72,17 @@ public:
|
||||
double finalSlTicks = slDistance / tickSize;
|
||||
double finalRisk = lotSize * finalSlTicks * tickValue;
|
||||
double finalRiskPercent = (finalRisk / equity) * 100.0;
|
||||
if(finalRiskPercent > m_maxRiskPercent * 1.1)
|
||||
{ params.rejectReason = "Risk exceeds max"; return; }
|
||||
params.lotSize = lotSize; params.riskAmount = finalRisk;
|
||||
params.riskPercent = finalRiskPercent; params.slDistance = slDistance;
|
||||
if(finalRiskPercent > adjustedRiskPercent * 1.1)
|
||||
{ params.rejectReason = "Risk exceeds adjusted max"; return; }
|
||||
|
||||
params.lotSize = lotSize;
|
||||
params.riskAmount = finalRisk;
|
||||
params.riskPercent = finalRiskPercent;
|
||||
params.slDistance = slDistance;
|
||||
params.tp1Distance = MathAbs(signal.tp1Price - signal.entryPrice);
|
||||
params.tp2Distance = MathAbs(signal.tp2Price - signal.entryPrice);
|
||||
params.marginRequired = marginRequired; params.isValid = true;
|
||||
params.marginRequired = marginRequired;
|
||||
params.isValid = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+24
-7
@@ -1,7 +1,7 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Risk/Protection.mqh |
|
||||
//| Circuit Breakers: Daily/Weekly Loss, Consecutive Loss, Spread |
|
||||
//| MODIFIED: Completed UpdateState with live statistics tracking |
|
||||
//| Enhanced Circuit Breakers with Dynamic Risk Adjustment |
|
||||
//| Reduces position size after consecutive losses |
|
||||
//+------------------------------------------------------------------+
|
||||
#ifndef __PROTECTION_MQH__
|
||||
#define __PROTECTION_MQH__
|
||||
@@ -25,6 +25,7 @@ private:
|
||||
double m_lastEquity;
|
||||
int m_consecLossCounter;
|
||||
datetime m_lastTradeTime;
|
||||
double m_currentRiskMultiplier; // Dynamic risk reduction
|
||||
|
||||
public:
|
||||
bool Init(double dailyLoss, double weeklyLoss, int consecLoss, int maxPos, double maxRisk)
|
||||
@@ -39,6 +40,7 @@ public:
|
||||
m_lastEquity = AccountInfoDouble(ACCOUNT_EQUITY);
|
||||
m_consecLossCounter = 0;
|
||||
m_lastTradeTime = 0;
|
||||
m_currentRiskMultiplier = 1.0;
|
||||
Print("[Protection] Circuit breakers active. Daily:", dailyLoss, "% Weekly:", weeklyLoss, "% Consec:", consecLoss);
|
||||
return true;
|
||||
}
|
||||
@@ -96,6 +98,12 @@ public:
|
||||
return (spreadPrice <= profile.maxSpreadPoints);
|
||||
}
|
||||
|
||||
// Get dynamic risk multiplier based on recent performance
|
||||
double GetRiskMultiplier() const
|
||||
{
|
||||
return m_currentRiskMultiplier;
|
||||
}
|
||||
|
||||
void UpdateState(EAState &state)
|
||||
{
|
||||
double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);
|
||||
@@ -111,7 +119,14 @@ public:
|
||||
m_consecLossCounter++;
|
||||
state.consecutiveLosses = m_consecLossCounter;
|
||||
m_lastTradeTime = TimeCurrent();
|
||||
g_logger.LogEvent("PROTECTION", StringFormat("Loss detected. Consecutive: %d/%d", m_consecLossCounter, m_maxConsecLosses));
|
||||
|
||||
// Dynamic risk reduction after consecutive losses
|
||||
if(m_consecLossCounter == 1) m_currentRiskMultiplier = 0.75;
|
||||
else if(m_consecLossCounter == 2) m_currentRiskMultiplier = 0.50;
|
||||
else if(m_consecLossCounter >= 3) m_currentRiskMultiplier = 0.25;
|
||||
|
||||
g_logger.LogEvent("PROTECTION", StringFormat("Loss detected. Consecutive: %d/%d. Risk multiplier: %.2f",
|
||||
m_consecLossCounter, m_maxConsecLosses, m_currentRiskMultiplier));
|
||||
}
|
||||
}
|
||||
else if(equityChange > 0)
|
||||
@@ -120,15 +135,16 @@ public:
|
||||
{
|
||||
m_consecLossCounter = 0;
|
||||
state.consecutiveLosses = 0;
|
||||
g_logger.LogEvent("PROTECTION", "Profit detected. Consecutive loss counter reset.");
|
||||
m_currentRiskMultiplier = 1.0; // Reset to full risk
|
||||
g_logger.LogEvent("PROTECTION", "Profit detected. Risk multiplier reset to 1.0");
|
||||
}
|
||||
}
|
||||
}
|
||||
m_lastEquity = currentEquity;
|
||||
if(InpDebugMode)
|
||||
{
|
||||
g_logger.LogEvent("PROTECTION", StringFormat("State | Daily: %.2f | Weekly: %.2f | Consec: %d | Equity: %.2f",
|
||||
state.dailyPnL, state.weeklyPnL, state.consecutiveLosses, currentEquity));
|
||||
g_logger.LogEvent("PROTECTION", StringFormat("State | Daily: %.2f | Weekly: %.2f | Consec: %d | RiskMult: %.2f | Equity: %.2f",
|
||||
state.dailyPnL, state.weeklyPnL, state.consecutiveLosses, m_currentRiskMultiplier, currentEquity));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,10 +159,11 @@ public:
|
||||
state.totalTradesToday = 0;
|
||||
state.consecutiveLosses = 0;
|
||||
m_consecLossCounter = 0;
|
||||
m_currentRiskMultiplier = 1.0;
|
||||
m_lastDailyReset = todayStart;
|
||||
state.equityAtStart = AccountInfoDouble(ACCOUNT_EQUITY);
|
||||
m_lastEquity = state.equityAtStart;
|
||||
g_logger.LogEvent("PROTECTION", "Daily counters reset");
|
||||
g_logger.LogEvent("PROTECTION", "Daily counters reset. Risk multiplier reset to 1.0");
|
||||
}
|
||||
if(dt.day_of_week == 1 && todayStart > m_lastWeeklyReset)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user