diff --git a/Include/Strategy.mqh b/Include/Strategy.mqh index c58934e..42b2b8d 100644 --- a/Include/Strategy.mqh +++ b/Include/Strategy.mqh @@ -68,6 +68,11 @@ public: if(m_ma_slow_handle == INVALID_HANDLE) { + if(m_ma_fast_handle != INVALID_HANDLE) + { + IndicatorRelease(m_ma_fast_handle); + m_ma_fast_handle = INVALID_HANDLE; + } if(mp_logger) mp_logger.Error("Failed to create Slow MA indicator"); return false; diff --git a/Include/TrailingStop.mqh b/Include/TrailingStop.mqh index 4c7ba31..af527dc 100644 --- a/Include/TrailingStop.mqh +++ b/Include/TrailingStop.mqh @@ -98,17 +98,32 @@ private: { double break_even_trigger = CUtilities::PointsToPrice(mp_market_data.GetSymbol(), g_break_even_profit); - double break_even_distance = CUtilities::PointsToPrice(mp_market_data.GetSymbol(), + double break_even_buffer = CUtilities::PointsToPrice(mp_market_data.GetSymbol(), g_break_even_sl); + double current_price = (pos_type == POSITION_TYPE_BUY) ? mp_market_data.GetBid() : mp_market_data.GetAsk(); + double price_move = 0.0; - // Break-even only if profit threshold is reached - if(profit < break_even_trigger) - return false; - - // For BUY: move SL to BE (open price + distance) if(pos_type == POSITION_TYPE_BUY) { - double be_sl = open_price + break_even_distance; + price_move = current_price - open_price; + } + else if(pos_type == POSITION_TYPE_SELL) + { + price_move = open_price - current_price; + } + else + { + return false; + } + + // Break-even only if price has moved enough from entry + if(price_move < break_even_trigger) + return false; + + // For BUY: move SL to entry price plus optional buffer + if(pos_type == POSITION_TYPE_BUY) + { + double be_sl = open_price + break_even_buffer; be_sl = CUtilities::NormalizePrice(mp_market_data.GetSymbol(), be_sl); if(be_sl > current_sl) @@ -119,10 +134,10 @@ private: return true; } } - // For SELL: move SL to BE (open price - distance) + // For SELL: move SL to entry price minus optional buffer else if(pos_type == POSITION_TYPE_SELL) { - double be_sl = open_price - break_even_distance; + double be_sl = open_price - break_even_buffer; be_sl = CUtilities::NormalizePrice(mp_market_data.GetSymbol(), be_sl); if(be_sl < current_sl) diff --git a/Include/Utilities.mqh b/Include/Utilities.mqh index 7ce6f7a..fbc29cf 100644 --- a/Include/Utilities.mqh +++ b/Include/Utilities.mqh @@ -23,6 +23,10 @@ public: double min_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); double max_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); double lot_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); + + // Guard against invalid broker volume data + if(min_lot <= 0.0 || max_lot <= 0.0 || lot_step <= 0.0 || max_lot < min_lot) + return 0.0; // Apply limits if(lot < min_lot) lot = min_lot; @@ -30,6 +34,9 @@ public: // Round to step lot = MathFloor(lot / lot_step) * lot_step; + + if(lot < min_lot) + lot = min_lot; return NormalizeDouble(lot, 2); } diff --git a/MyProEA.ex5 b/MyProEA.ex5 index 4a7bc7c..75692e3 100644 Binary files a/MyProEA.ex5 and b/MyProEA.ex5 differ diff --git a/MyProEA.mq5 b/MyProEA.mq5 index 557ea7c..500a326 100644 --- a/MyProEA.mq5 +++ b/MyProEA.mq5 @@ -48,6 +48,10 @@ int OnInit() if(!g_market_data.IsTradingAllowed()) { g_logger.Error("Trading not allowed for this symbol"); + delete g_market_data; + g_market_data = NULL; + delete g_logger; + g_logger = NULL; return INIT_FAILED; } @@ -56,6 +60,12 @@ int OnInit() if(!g_strategy.Init()) { g_logger.Error("Failed to initialize strategy"); + delete g_strategy; + g_strategy = NULL; + delete g_market_data; + g_market_data = NULL; + delete g_logger; + g_logger = NULL; return INIT_FAILED; }