//+------------------------------------------------------------------+ //| 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 #include #include #include //+------------------------------------------------------------------+ //| 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 | //+------------------------------------------------------------------+