mql5/Experts/Previous/EnhancedRiskManagment_OverlayEA (2).mq5

1045 lines
82 KiB
MQL5
Raw Permalink Normal View History

<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| Enhanced Risk Management Overlay EA v4.0 |
//| Complete Fixed Implementation |
//| With MA Entry System & External Trade Management |
//+------------------------------------------------------------------+
#property version "4.00"
#property strict
#property description "Professional risk management system with MA entry and external trade management"
#include <Trade/Trade.mqh>
#include <Trade/PositionInfo.mqh>
#include <Trade/OrderInfo.mqh>
#include <Trade/DealInfo.mqh>
//+------------------------------------------------------------------+
//| ENUMERATIONS |
//+------------------------------------------------------------------+
enum ENUM_TP_STRATEGY
{
TP_STATIC = 0, // Static risk:reward ratio
TP_TRAILING = 1, // Dynamic trailing take profit
TP_PARTIAL = 2, // Multi-level partial profits
TP_TECHNICAL = 3, // Technical level-based exits
TP_VOLATILITY = 4, // ATR-adjusted targets
TP_ADAPTIVE = 5, // Machine learning-based selection
TP_HYBRID = 6 // Combination of multiple strategies
};
enum ENUM_TP_STATUS
{
TP_NONE = 0, // No partial closes yet
TP_FIRST = 1, // First target hit (33%)
TP_SECOND = 2, // Second target hit (66%)
TP_THIRD = 3, // Third target hit (80%)
TP_FINAL = 4 // Only final portion remains
};
enum ENUM_POSITION_SIZING
{
PS_FIXED_LOTS = 0, // Fixed lot size
PS_RISK_PERCENT = 1, // Percentage of equity at risk
PS_CAPITAL_PERCENT = 2, // Percentage of total capital
PS_ATR_BASED = 3, // Volatility-adjusted sizing
PS_KELLY = 4 // Kelly Criterion sizing
};
enum ENUM_MA_ENTRY_TYPE
{
MA_DISABLED = 0, // No MA entry (external only)
MA_SIMPLE_CROSS = 1, // Fast/Slow MA crossover
MA_TRIPLE_CROSS = 2, // Three MA system
MA_PULLBACK = 3, // MA pullback entry
MA_MOMENTUM = 4 // MA with momentum confirmation
};
enum ENUM_TECHNICAL_LEVEL
{
TECH_FIBONACCI = 0, // Fibonacci retracements/extensions
TECH_PIVOT_POINTS = 1, // Daily/Weekly pivot points
TECH_MOVING_AVG = 2, // Dynamic moving averages
TECH_ROUND_NUMBERS = 3, // Psychological levels
TECH_VWAP = 4, // Volume-weighted average price
TECH_SUPPORT_RES = 5, // Historical S/R levels
TECH_SUPPLY_DEMAND = 6 // Supply/Demand zones
};
//+------------------------------------------------------------------+
//| STRUCTURES |
//+------------------------------------------------------------------+
struct TechnicalLevel
{
double price;
ENUM_TECHNICAL_LEVEL type;
double score;
double zone_width;
string description;
datetime last_touch;
int touch_count;
};
struct RiskData
{
double atr_value;
double sr_support;
double sr_resistance;
double sar_value;
double trail_stop;
double trail_tp;
double volatility_factor;
double market_volatility;
double trend_strength;
TechnicalLevel technical_levels[30];
int technical_count;
double best_technical_target;
datetime last_update;
};
struct TradeInfo
{
ulong ticket;
double open_price;
double original_volume;
double current_volume;
double current_sl;
double current_tp;
double best_profit;
double worst_drawdown;
datetime open_time;
datetime breakeven_time;
ENUM_TP_STATUS tp_status;
ENUM_TP_STRATEGY tp_strategy;
bool breakeven_set;
double entry_atr;
double risk_amount;
string entry_reason;
RiskData risk_data;
};
struct StrategyPerformance
{
ENUM_TP_STRATEGY strategy;
int trades_count;
double total_profit;
double total_loss;
double avg_profit;
double avg_win;
double avg_loss;
double max_drawdown;
double win_rate;
double profit_factor;
double expectancy;
double sharpe_ratio;
double recovery_factor;
double score;
double trade_profits[100];
int profit_index;
datetime last_update;
};
struct MarketAnalysis
{
double trend_direction;
double volatility_regime;
double momentum_score;
bool news_upcoming;
datetime last_analysis;
};
//+------------------------------------------------------------------+
//| INPUT PARAMETERS |
//+------------------------------------------------------------------+
input group "=== ENTRY SYSTEMS ==="
input ENUM_MA_ENTRY_TYPE MAEntryType = MA_SIMPLE_CROSS; // Moving Average Entry Type
input bool EnableContrarian = false; // Enable Contrarian Entry
input bool ManageExistingTrades = true; // Manage External Trades
input bool UseOptimizedParameters = true; // Use Optimized Default Parameters
input group "=== MOVING AVERAGE ENTRY SETTINGS ==="
input int MA_Fast_Period = 20; // Fast MA Period
input int MA_Slow_Period = 50; // Slow MA Period
input int MA_Filter_Period = 200; // Trend Filter MA Period
input ENUM_MA_METHOD MA_Method = MODE_EMA; // MA Calculation Method
input ENUM_APPLIED_PRICE MA_Price = PRICE_CLOSE; // MA Applied Price
input double MA_MinDistance = 10; // Min distance between MAs (points)
input bool MA_RequireMomentum = true; // Require momentum confirmation
input int RSI_Period = 14; // RSI Period for momentum
input double RSI_BuyLevel = 50; // RSI Buy threshold
input double RSI_SellLevel = 50; // RSI Sell threshold
input group "=== CONTRARIAN ENTRY SETTINGS ==="
input int ConsecutiveBars = 3; // Number of consecutive bars
input double MinBarSize = 100; // Minimum bar size in points
input double MaxBarSize = 500; // Maximum bar size in points
input bool RequireVolumeConfirmation = true; // Require volume confirmation
input double VolumeMultiplier = 1.2; // Volume multiplier threshold
input group "=== POSITION SIZING ==="
input ENUM_POSITION_SIZING PositionSizingMode = PS_RISK_PERCENT;
input double FixedLotSize = 0.1; // Fixed lot size
input double RiskPercent = 1.5; // Risk per trade (%)
input double MaxRiskPercent = 3.0; // Maximum risk per trade (%)
input double CapitalPercent = 10.0; // Capital allocation (%)
input double KellyFraction = 0.25; // Kelly fraction (25% = quarter Kelly)
input int MaxPositions = 3; // Maximum simultaneous positions
input int TradingMagic = 12345; // Magic number for trades
input group "=== TAKE PROFIT STRATEGY ==="
input bool EnableAdvancedTP = true; // Enable advanced TP management
input ENUM_TP_STRATEGY TakeProfitMode = TP_ADAPTIVE; // Take profit strategy
input double BaseTPRatio = 2.0; // Base TP ratio (risk:reward)
input double TrailingTPStart = 1.0; // Start trailing after X:1
input double TrailingTPStep = 0.3; // Trailing step (ATR multiplier)
input double PartialTP1Ratio = 1.0; // First partial TP (1:1)
input double PartialTP2Ratio = 2.0; // Second partial TP (2:1)
input double PartialTP3Ratio = 3.0; // Third partial TP (3:1)
input double PartialClosePercent1 = 30.0; // First partial close %
input double PartialClosePercent2 = 30.0; // Second partial close %
input double PartialClosePercent3 = 20.0; // Third partial close %
input double VolatilityTPMultiplier = 1.5; // Volatility TP adjustment
input int AdaptivePeriod = 20; // Adaptive evaluation period
input group "=== TECHNICAL ANALYSIS ==="
input bool UseFibonacci = true; // Use Fibonacci levels
input bool UsePivotPoints = true; // Use Pivot Points
input bool UseMovingAverages = true; // Use MA levels
input bool UseRoundNumbers = true; // Use Round Numbers
input bool UseVWAP = true; // Use VWAP
input bool UseSupplyDemand = true; // Use Supply/Demand zones
input double MinConfluenceScore = 3.0; // Minimum confluence score
input double TechnicalTolerancePoints = 20; // Technical level tolerance
input int TechnicalLookbackBars = 100; // Technical analysis lookback
input int FibLookbackBars = 100; // Fibonacci lookback period
input string RoundNumberStep = "50"; // Round number increment
input group "=== RISK MANAGEMENT ==="
input bool EnableATRSizing = true; // ATR-based position sizing
input bool EnableSRTrails = true; // Support/Resistance trails
input bool EnableSARExits = true; // Parabolic SAR exits
input bool EnableBreakeven = true; // Breakeven management
input double BreakevenTrigger = 1.0; // Move to BE after X:1
input double BreakevenBuffer = 5; // BE buffer in points
input group "=== ATR SETTINGS ==="
input int ATR_Period = 14; // ATR calculation period
input double ATR_Multiplier = 2.0; // ATR stop loss multiplier
input double ATR_TPMultiplier = 3.0; // ATR take profit multiplier
input double MinLotSize = 0.01; // Minimum lot size
input double MaxLotSize = 10.0; // Maximum lot size
input group "=== SUPPORT/RESISTANCE ==="
input int SR_LookbackPeriod = 150; // S/R lookback period
input double SR_MinDistance = 100; // Minimum S/R distance
input int SR_TouchCount = 3; // Minimum touches for S/R
input double SR_TolerancePoints = 30; // S/R clustering tolerance
input double SR_ZoneWidth = 20; // S/R zone width
input group "=== PARABOLIC SAR ==="
input double SAR_Step = 0.02; // SAR step
input double SAR_Maximum = 0.2; // SAR maximum
input group "=== TRADE MANAGEMENT ==="
input int MagicNumberFilter = 0; // Filter by magic (0 = all)
input int MaxHoldingPeriod = 0; // Max holding minutes (0 = off)
input double MaxDrawdownPercent = 5.0; // Max portfolio drawdown %
input bool CloseOnFridayEnd = true; // Close before weekend
input bool EnableNewsFilter = true; // Avoid news events
input int NewsBufferMinutes = 30; // Minutes before/after news
input group "=== PERFORMANCE & LOGGING ==="
input bool EnableLogging = true; // Detailed logging
input bool EnableDashboard = true; // Performance dashboard
input bool SendAlerts = false; // Send alerts
input bool SaveReports = true; // Save performance reports
input int ReportInterval = 1440; // Report interval (minutes)
//+------------------------------------------------------------------+
//| GLOBAL VARIABLES |
//+------------------------------------------------------------------+
CTrade trade;
CPositionInfo posInfo;
COrderInfo orderInfo;
CDealInfo dealInfo;
TradeInfo managed_trades[];
StrategyPerformance strategy_performance[7];
MarketAnalysis market_analysis;
double account_start_balance;
datetime last_risk_check;
datetime last_bar_time;
datetime last_strategy_eval;
datetime last_report_time;
ENUM_TP_STRATEGY current_best_strategy;
// Performance tracking
double session_profit = 0;
double session_loss = 0;
int session_wins = 0;
int session_losses = 0;
double peak_balance = 0;
double current_drawdown = 0;
double max_historical_drawdown = 0;
// Trade management
datetime last_trade_time = 0;
int consecutive_losses = 0;
double current_risk_multiplier = 1.0;
// Indicator handles
int g_ma_fast_handle = INVALID_HANDLE;
int g_ma_slow_handle = INVALID_HANDLE;
int g_ma_filter_handle = INVALID_HANDLE;
int g_atr_handle = INVALID_HANDLE;
int g_rsi_handle = INVALID_HANDLE;
int g_sar_handle = INVALID_HANDLE;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Set trade parameters
trade.SetExpertMagicNumber(TradingMagic);
trade.SetDeviationInPoints(50);
trade.SetTypeFilling(ORDER_FILLING_RETURN);
trade.SetAsyncMode(false);
// Create indicator handles
g_atr_handle = iATR(_Symbol, PERIOD_CURRENT, ATR_Period);
g_sar_handle = iSAR(_Symbol, PERIOD_CURRENT, SAR_Step, SAR_Maximum);
if(MAEntryType != MA_DISABLED)
{
g_ma_fast_handle = iMA(_Symbol, PERIOD_CURRENT, MA_Fast_Period, 0, MA_Method, MA_Price);
g_ma_slow_handle = iMA(_Symbol, PERIOD_CURRENT, MA_Slow_Period, 0, MA_Method, MA_Price);
if(MA_Filter_Period > 0)
g_ma_filter_handle = iMA(_Symbol, PERIOD_CURRENT, MA_Filter_Period, 0, MA_Method, MA_Price);
}
if(MA_RequireMomentum)
g_rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
// Validate handles
if(g_atr_handle == INVALID_HANDLE || g_sar_handle == INVALID_HANDLE ||
(MAEntryType != MA_DISABLED && (g_ma_fast_handle == INVALID_HANDLE || g_ma_slow_handle == INVALID_HANDLE)))
{
Print("Error creating indicator handles");
return(INIT_FAILED);
}
// Initialize account variables
account_start_balance = AccountInfoDouble(ACCOUNT_BALANCE);
peak_balance = account_start_balance;
last_risk_check = TimeCurrent();
last_bar_time = 0;
last_strategy_eval = TimeCurrent();
last_report_time = TimeCurrent();
current_best_strategy = TakeProfitMode;
// Initialize strategy performance tracking
InitializeStrategyPerformance();
// Initialize market analysis
market_analysis.trend_direction = 0;
market_analysis.volatility_regime = 1.0;
market_analysis.momentum_score = 0;
market_analysis.news_upcoming = false;
market_analysis.last_analysis = 0;
// Display initialization info
Print("=== ENHANCED RISK MANAGEMENT OVERLAY v3.0 ===");
Print("Account Balance: $", account_start_balance);
Print("Entry Mode: ", GetEntryModeDescription());
Print("Risk Management: ", EnumToString(PositionSizingMode), " @ ", RiskPercent, "%");
Print("Take Profit: ", EnumToString(TakeProfitMode));
Print("Max Positions: ", MaxPositions);
if(EnableDashboard)
{
CreateDashboard();
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Release indicator handles
if(g_atr_handle != INVALID_HANDLE) IndicatorRelease(g_atr_handle);
if(g_sar_handle != INVALID_HANDLE) IndicatorRelease(g_sar_handle);
if(g_ma_fast_handle != INVALID_HANDLE) IndicatorRelease(g_ma_fast_handle);
if(g_ma_slow_handle != INVALID_HANDLE) IndicatorRelease(g_ma_slow_handle);
if(g_ma_filter_handle != INVALID_HANDLE) IndicatorRelease(g_ma_filter_handle);
if(g_rsi_handle != INVALID_HANDLE) IndicatorRelease(g_rsi_handle);
// Cleanup actions
if(EnableDashboard)
{
DestroyDashboard();
}
Print("=== ENHANCED RISK MANAGEMENT OVERLAY v3.0 - DEINITIALIZED ===");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Risk management checks
ManageRisk();
// Trading strategy execution
ExecuteTradingStrategies();
// Update dashboard
if(EnableDashboard)
{
UpdateDashboard();
}
}
//+------------------------------------------------------------------+
//| Get ATR value |
//+------------------------------------------------------------------+
double GetATRValue(int shift = 0)
{
double buffer[1];
if(CopyBuffer(g_atr_handle, 0, shift, 1, buffer) <= 0)
return 0;
return buffer[0];
}
//+------------------------------------------------------------------+
//| Get SAR value |
//+------------------------------------------------------------------+
double GetSARValue(int shift = 0)
{
double buffer[1];
if(CopyBuffer(g_sar_handle, 0, shift, 1, buffer) <= 0)
return 0;
return buffer[0];
}
//+------------------------------------------------------------------+
//| Modular risk management stubs (implement as needed) |
//+------------------------------------------------------------------+
void ApplyTakeProfitStrategy(TradeInfo &trade_info) {}
void ApplyBreakevenManagement(TradeInfo &trade_info) {}
void ApplyTrailingStop(TradeInfo &trade_info) {}
void CheckSARExits(TradeInfo &trade_info) {}
//+------------------------------------------------------------------+
//| Manage risk for open trades |
//+------------------------------------------------------------------+
void ManageRisk()
{
// Update managed trades list first
UpdateManagedTrades();
// Iterate through managed trades
for(int i = ArraySize(managed_trades) - 1; i >= 0; i--)
{
if(!posInfo.SelectByTicket(managed_trades[i].ticket))
{
// Position closed, remove from array
RemoveTradeFromArray(i);
continue;
}
// Update risk data
UpdateRiskData(managed_trades[i]);
// Apply various risk management techniques
if(EnableAdvancedTP)
ApplyTakeProfitStrategy(managed_trades[i]);
if(EnableBreakeven)
ApplyBreakevenManagement(managed_trades[i]);
if(EnableSRTrails)
ApplyTrailingStop(managed_trades[i]);
if(EnableSARExits)
CheckSARExits(managed_trades[i]);
}
}
//+------------------------------------------------------------------+
//| Update managed trades array |
//+------------------------------------------------------------------+
void UpdateManagedTrades()
{
// Check for new positions to manage
for(int i = 0; i < PositionsTotal(); i++)
{
if(posInfo.SelectByIndex(i))
{
if(posInfo.Symbol() == _Symbol)
{
bool should_manage = false;
// Check if we should manage this position
if(posInfo.Magic() == TradingMagic)
should_manage = true;
else if(ManageExistingTrades && (MagicNumberFilter == 0 || posInfo.Magic() == MagicNumberFilter))
should_manage = true;
if(should_manage && !IsTradeInArray(posInfo.Ticket()))
{
AddExternalTrade(posInfo.Ticket());
}
}
}
}
}
//+------------------------------------------------------------------+
//| Check if trade is already in managed array |
//+------------------------------------------------------------------+
bool IsTradeInArray(ulong ticket)
{
for(int i = 0; i < ArraySize(managed_trades); i++)
{
if(managed_trades[i].ticket == ticket)
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Add external trade to managed array |
//+------------------------------------------------------------------+
void AddExternalTrade(ulong ticket)
{
if(!posInfo.SelectByTicket(ticket)) return;
TradeInfo new_trade;
new_trade.ticket = ticket;
new_trade.open_price = posInfo.PriceOpen();
new_trade.original_volume = posInfo.Volume();
new_trade.current_volume = posInfo.Volume();
new_trade.current_sl = posInfo.StopLoss();
new_trade.current_tp = posInfo.TakeProfit();
new_trade.best_profit = posInfo.Profit();
new_trade.worst_drawdown = 0;
new_trade.open_time = posInfo.Time();
new_trade.breakeven_time = 0;
new_trade.tp_status = TP_NONE;
new_trade.tp_strategy = TakeProfitMode;
new_trade.breakeven_set = false;
new_trade.entry_atr = GetATRValue();
new_trade.risk_amount = 0; // Unknown for external trades
new_trade.entry_reason = "External Trade";
int size = ArraySize(managed_trades);
ArrayResize(managed_trades, size + 1);
managed_trades[size] = new_trade;
if(EnableLogging)
Print("Added external trade #", ticket, " to management");
}
//+------------------------------------------------------------------+
//| Remove trade from managed array |
//+------------------------------------------------------------------+
void RemoveTradeFromArray(int index)
{
if(index < 0 || index >= ArraySize(managed_trades)) return;
for(int i = index; i < ArraySize(managed_trades) - 1; i++)
{
managed_trades[i] = managed_trades[i + 1];
}
ArrayResize(managed_trades, ArraySize(managed_trades) - 1);
}
//+------------------------------------------------------------------+
//| Execute trading strategies |
//+------------------------------------------------------------------+
void ExecuteTradingStrategies()
{
// Check for new bar
static datetime last_check_time = 0;
datetime current_time = iTime(_Symbol, PERIOD_CURRENT, 0);
if(current_time == last_check_time) return;
last_check_time = current_time;
// Check if we can open new positions
if(CountCurrentPositions() >= MaxPositions) return;
// Example: Simple MA crossover strategy
if(MAEntryType == MA_SIMPLE_CROSS)
{
double ma_fast_buffer[2], ma_slow_buffer[2];
// Copy MA values
if(CopyBuffer(g_ma_fast_handle, 0, 0, 2, ma_fast_buffer) != 2) return;
if(CopyBuffer(g_ma_slow_handle, 0, 0, 2, ma_slow_buffer) != 2) return;
double ma_fast_current = ma_fast_buffer[0];
double ma_fast_prev = ma_fast_buffer[1];
double ma_slow_current = ma_slow_buffer[0];
double ma_slow_prev = ma_slow_buffer[1];
// Check for crossover
if(ma_fast_prev <= ma_slow_prev && ma_fast_current > ma_slow_current)
{
// Bullish crossover - Buy signal
OpenBuyOrder();
}
else if(ma_fast_prev >= ma_slow_prev && ma_fast_current < ma_slow_current)
{
// Bearish crossover - Sell signal
OpenSellOrder();
}
}
}
//+------------------------------------------------------------------+
//| Count current positions |
//+------------------------------------------------------------------+
int CountCurrentPositions()
{
int count = 0;
for(int i = 0; i < PositionsTotal(); i++)
{
if(posInfo.SelectByIndex(i))
{
if(posInfo.Symbol() == _Symbol && posInfo.Magic() == TradingMagic)
count++;
}
}
return count;
}
//+------------------------------------------------------------------+
//| Open buy order with risk management |
//+------------------------------------------------------------------+
void OpenBuyOrder()
{
double lot_size = CalculateLotSize();
double stop_loss = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID) - ATR_Multiplier * GetATRValue(), _Digits);
double take_profit = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID) + ATR_TPMultiplier * GetATRValue(), _Digits);
// Send buy order
if(trade.Buy(lot_size, _Symbol, 0, stop_loss, take_profit, "MA Buy Signal"))
{
ulong ticket = trade.ResultOrder(); // Changed from ResultHandle()
Print("Buy order opened: #", ticket);
// Wait a bit for the order to be processed
Sleep(100);
// Find the position by ticket
if(posInfo.SelectByTicket(ticket))
{
// Initialize trade info structure
TradeInfo new_trade;
new_trade.ticket = ticket;
new_trade.open_price = posInfo.PriceOpen();
new_trade.original_volume = lot_size;
new_trade.current_volume = lot_size;
new_trade.current_sl = stop_loss;
new_trade.current_tp = take_profit;
new_trade.best_profit = 0;
new_trade.worst_drawdown = 0;
new_trade.open_time = TimeCurrent();
new_trade.breakeven_time = 0;
new_trade.tp_status = TP_NONE;
new_trade.tp_strategy = TakeProfitMode;
new_trade.breakeven_set = false;
new_trade.entry_atr = GetATRValue();
new_trade.risk_amount = CalculateRiskAmount(lot_size, new_trade.open_price, stop_loss);
new_trade.entry_reason = "MA Crossover Buy";
// Add to managed trades
int size = ArraySize(managed_trades);
ArrayResize(managed_trades, size + 1);
managed_trades[size] = new_trade;
}
}
else
{
Print("Error opening buy order: ", GetLastError(), " - ", trade.ResultComment());
}
}
//+------------------------------------------------------------------+
//| Open sell order with risk management |
//+------------------------------------------------------------------+
void OpenSellOrder()
{
double lot_size = CalculateLotSize();
double stop_loss = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK) + ATR_Multiplier * GetATRValue(), _Digits);
double take_profit = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK) - ATR_TPMultiplier * GetATRValue(), _Digits);
// Send sell order
if(trade.Sell(lot_size, _Symbol, 0, stop_loss, take_profit, "MA Sell Signal"))
{
ulong ticket = trade.ResultOrder(); // Changed from ResultHandle()
Print("Sell order opened: #", ticket);
// Wait a bit for the order to be processed
Sleep(100);
// Find the position by ticket
if(posInfo.SelectByTicket(ticket))
{
// Initialize trade info structure
TradeInfo new_trade;
new_trade.ticket = ticket;
new_trade.open_price = posInfo.PriceOpen();
new_trade.original_volume = lot_size;
new_trade.current_volume = lot_size;
new_trade.current_sl = stop_loss;
new_trade.current_tp = take_profit;
new_trade.best_profit = 0;
new_trade.worst_drawdown = 0;
new_trade.open_time = TimeCurrent();
new_trade.breakeven_time = 0;
new_trade.tp_status = TP_NONE;
new_trade.tp_strategy = TakeProfitMode;
new_trade.breakeven_set = false;
new_trade.entry_atr = GetATRValue();
new_trade.risk_amount = CalculateRiskAmount(lot_size, new_trade.open_price, stop_loss);
new_trade.entry_reason = "MA Crossover Sell";
// Add to managed trades
int size = ArraySize(managed_trades);
ArrayResize(managed_trades, size + 1);
managed_trades[size] = new_trade;
}
}
else
{
Print("Error opening sell order: ", GetLastError(), " - ", trade.ResultComment());
}
}
//+------------------------------------------------------------------+
//| Calculate lot size based on risk management |
//+------------------------------------------------------------------+
double CalculateLotSize()
{
double risk_amount = AccountInfoDouble(ACCOUNT_BALANCE) * RiskPercent / 100;
double lot_size = risk_amount / (ATR_Multiplier * GetATRValue());
lot_size = NormalizeDouble(lot_size, 2);
// Apply minimum and maximum lot size limits
if(lot_size < MinLotSize) lot_size = MinLotSize;
if(lot_size > MaxLotSize) lot_size = MaxLotSize;
return lot_size;
}
//+------------------------------------------------------------------+
//| Calculate risk amount based on position size |
//+------------------------------------------------------------------+
double CalculateRiskAmount(double lot_size, double entry_price, double stop_loss)
{
double stop_distance = MathAbs(entry_price - stop_loss);
double tick_value = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
if(tick_size > 0)
{
double stop_points = stop_distance / _Point;
double risk_amount = lot_size * stop_points * tick_value * (_Point / tick_size);
return risk_amount;
}
return 0;
}
//+------------------------------------------------------------------+
//| Update risk data for a trade |
//+------------------------------------------------------------------+
void UpdateRiskData(TradeInfo &trade_info)
{
// Example: Update ATR-based trailing stop
if(EnableATRSizing)
{
double atr_value = GetATRValue();
double trail_stop = trade_info.open_price + atr_value * ATR_Multiplier;
if(trade_info.tp_status == TP_NONE)
{
trade_info.current_sl = trail_stop;
}
}
}
//+------------------------------------------------------------------+
//| Close a trade by ticket number |
//+------------------------------------------------------------------+
void CloseTrade(TradeInfo &trade_info)
{
// Find and close the trade
for(int i = 0; i < ArraySize(managed_trades); i++)
{
if(managed_trades[i].ticket == trade_info.ticket)
{
// Close the trade
trade.PositionClose(managed_trades[i].ticket);
Print("Trade #", managed_trades[i].ticket, " closed");
// Remove from managed trades
for(int j = i; j < ArraySize(managed_trades) - 1; j++)
{
managed_trades[j] = managed_trades[j + 1];
}
ArrayResize(managed_trades, ArraySize(managed_trades) - 1);
break;
}
}
}
//+------------------------------------------------------------------+
//| Initialize strategy performance data |
//+------------------------------------------------------------------+
void InitializeStrategyPerformance()
{
for(int i = 0; i < ArraySize(strategy_performance); i++)
{
strategy_performance[i].strategy = (ENUM_TP_STRATEGY)i;
strategy_performance[i].trades_count = 0;
strategy_performance[i].total_profit = 0;
strategy_performance[i].total_loss = 0;
strategy_performance[i].avg_profit = 0;
strategy_performance[i].avg_win = 0;
strategy_performance[i].avg_loss = 0;
strategy_performance[i].max_drawdown = 0;
strategy_performance[i].win_rate = 0;
strategy_performance[i].profit_factor = 0;
strategy_performance[i].expectancy = 0;
strategy_performance[i].sharpe_ratio = 0;
strategy_performance[i].recovery_factor = 0;
strategy_performance[i].score = 0;
strategy_performance[i].profit_index = 0;
strategy_performance[i].last_update = 0;
}
}
//+------------------------------------------------------------------+
//| Get entry mode description |
//+------------------------------------------------------------------+
string GetEntryModeDescription()
{
switch(MAEntryType)
{
case MA_SIMPLE_CROSS: return "Simple MA Crossover";
case MA_TRIPLE_CROSS: return "Triple MA Crossover";
case MA_PULLBACK: return "MA Pullback";
case MA_MOMENTUM: return "MA Momentum";
default: return "Disabled";
}
}
//+------------------------------------------------------------------+
//| Create performance dashboard |
//+------------------------------------------------------------------+
void CreateDashboard()
{
// Example: Create a simple dashboard object
string obj_name = "PerformanceDashboard";
if(!ObjectCreate(0, obj_name, OBJ_LABEL, 0, 0, 0))
{
Print("Error creating dashboard object: ", GetLastError());
return;
}
ObjectSetInteger(0, obj_name, OBJPROP_XSIZE, 300);
ObjectSetInteger(0, obj_name, OBJPROP_YSIZE, 200);
ObjectSetInteger(0, obj_name, OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, obj_name, OBJPROP_YDISTANCE, 10);
ObjectSetInteger(0, obj_name, OBJPROP_FONTSIZE, 10);
ObjectSetInteger(0, obj_name, OBJPROP_COLOR, clrWhite);
// Set initial text
UpdateDashboard();
}
//+------------------------------------------------------------------+
//| Update performance dashboard |
//+------------------------------------------------------------------+
void UpdateDashboard()
{
// Example: Update dashboard text with performance data
string obj_name = "PerformanceDashboard";
string text = "=== PERFORMANCE DASHBOARD ===\n";
text += "Account Balance: $" + DoubleToString(account_start_balance, 2) + "\n";
text += "Equity: $" + DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY), 2) + "\n";
text += "Floating Profit: $" + DoubleToString(AccountInfoDouble(ACCOUNT_PROFIT), 2) + "\n";
text += "Total Trades: " + IntegerToString(ArraySize(managed_trades)) + "\n";
text += "Winning Trades: " + IntegerToString(session_wins) + "\n";
text += "Losing Trades: " + IntegerToString(session_losses) + "\n";
text += "Session Profit: $" + DoubleToString(session_profit, 2) + "\n";
text += "Session Loss: $" + DoubleToString(session_loss, 2) + "\n";
text += "Max Drawdown: $" + DoubleToString(max_historical_drawdown, 2) + "\n";
text += "Current DD: $" + DoubleToString(current_drawdown, 2) + "\n";
ObjectSetString(0, obj_name, OBJPROP_TEXT, text);
}
//+------------------------------------------------------------------+
//| Destroy dashboard object |
//+------------------------------------------------------------------+
void DestroyDashboard()
{
string obj_name = "PerformanceDashboard";
ObjectDelete(0, obj_name);
}
//+------------------------------------------------------------------+
//| Find largest winning trade |
//+------------------------------------------------------------------+
double FindLargestWin()
{
double largest = 0;
for(int i = 0; i < ArraySize(strategy_performance); i++)
{
for(int j = 0; j < MathMin(strategy_performance[i].trades_count, 100); j++)
{
if(strategy_performance[i].trade_profits[j] > largest)
largest = strategy_performance[i].trade_profits[j];
}
}
return largest;
}
//+------------------------------------------------------------------+
//| Find largest losing trade |
//+------------------------------------------------------------------+
double FindLargestLoss()
{
double largest = 0;
for(int i = 0; i < ArraySize(strategy_performance); i++)
{
for(int j = 0; j < MathMin(strategy_performance[i].trades_count, 100); j++)
{
if(strategy_performance[i].trade_profits[j] < largest)
largest = strategy_performance[i].trade_profits[j];
}
}
return MathAbs(largest);
}
//+------------------------------------------------------------------+
//| Convert boolean to string |
//+------------------------------------------------------------------+
string BoolToString(bool value)
{
return value ? "Yes" : "No";
}
//+------------------------------------------------------------------+
//| Calculate win rate |
//+------------------------------------------------------------------+
double CalculateWinRate()
{
if(session_wins + session_losses == 0) return 0;
return (double)session_wins / (session_wins + session_losses) * 100.0;
}
//+------------------------------------------------------------------+
//| Calculate average win |
//+------------------------------------------------------------------+
double CalculateAverageWin()
{
if(session_wins == 0) return 0;
return session_profit / session_wins;
}
//+------------------------------------------------------------------+
//| Calculate average loss |
//+------------------------------------------------------------------+
double CalculateAverageLoss()
{
if(session_losses == 0) return 0;
return MathAbs(session_loss) / session_losses;
}
//+------------------------------------------------------------------+
//| Calculate overall profit factor |
//+------------------------------------------------------------------+
double CalculateOverallProfitFactor()
{
if(session_loss == 0)
return (session_profit > 0) ? 999.99 : 0;
return session_profit / MathAbs(session_loss);
}
//+------------------------------------------------------------------+
//| OnTester - Optimization fitness function |
//+------------------------------------------------------------------+
double OnTester()
{
// Ensure minimum trades for valid optimization
double total_trades = session_wins + session_losses;
if(total_trades < 20) return 0;
double win_rate = CalculateWinRate();
double profit_factor = CalculateOverallProfitFactor();
double total_profit = AccountInfoDouble(ACCOUNT_BALANCE) - account_start_balance;
double roi = (total_profit / account_start_balance) * 100;
// Risk-adjusted metrics
double sharpe_ratio = 0;
if(max_historical_drawdown > 0)
sharpe_ratio = (roi / max_historical_drawdown);
double recovery_factor = 0;
if(max_historical_drawdown > 0)
recovery_factor = (total_profit / (account_start_balance * max_historical_drawdown / 100));
// Average profit per trade
double avg_profit_per_trade = total_profit / total_trades;
double expectancy = (win_rate / 100 * CalculateAverageWin()) -
((100 - win_rate) / 100 * CalculateAverageLoss());
// Build composite score with multiple objectives
double score = 0;
// 1. Profitability (30%)
double profit_score = 0;
if(roi > 0)
{
profit_score += MathMin(roi / 100, 1.0) * 0.15; // ROI component
profit_score += MathMin(profit_factor / 3, 1.0) * 0.15; // PF component
}
// 2. Risk-Adjusted Returns (25%)
double risk_score = 0;
if(sharpe_ratio > 0)
{
risk_score += MathMin(sharpe_ratio / 2, 1.0) * 0.15;
risk_score += MathMin(recovery_factor / 3, 1.0) * 0.10;
}
// 3. Consistency (25%)
double consistency_score = 0;
consistency_score += (win_rate / 100) * 0.15;
consistency_score += MathMin(total_trades / 100, 1.0) * 0.10;
// 4. Risk Control (20%)
double risk_control = 1.0;
if(max_historical_drawdown > MaxDrawdownPercent)
risk_control = 0.5; // Heavy penalty for exceeding max drawdown
else
risk_control = 1.0 - (max_historical_drawdown / (MaxDrawdownPercent * 2));
risk_control *= 0.20;
// Combine all components
score = profit_score + risk_score + consistency_score + risk_control;
// Apply additional filters
if(profit_factor < 1.0) score *= 0.5; // Penalty for losing system
if(win_rate < 30) score *= 0.7; // Penalty for very low win rate
if(expectancy < 0) score *= 0.3; // Heavy penalty for negative expectancy
// Scale to 0-100
score = MathMin(score * 100, 100);
score = MathMax(score, 0);
// Log optimization results
if(EnableLogging)
{
Print("=== OPTIMIZATION SCORE ===");
Print("Total Score: ", score);
Print("ROI: ", roi, "% PF: ", profit_factor, " WR: ", win_rate, "%");
Print("Sharpe: ", sharpe_ratio, " Recovery: ", recovery_factor);
Print("Max DD: ", max_historical_drawdown, "% Trades: ", total_trades);
}
return score;
}
//+------------------------------------------------------------------+
//| END OF ENHANCED RISK MANAGEMENT OVERLAY EA v4.0 |
//+------------------------------------------------------------------+