//+------------------------------------------------------------------+ //| EBAKEM_EA_GLORY.mq5 | //| Copyright 2026, EBAKEM Trading | //| | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, EBAKEM Trading" #property link "" #property version "1.00" //--- Input Parameters input group "=== Trading Settings ===" input double LotSize = 0.01; // Lot Size input int MaxTrades = 1; // Maximum Trades (1 = one at a time) input double TakeProfit = 0; // Take Profit in Points (0 = disabled) input ENUM_TIMEFRAMES Timeframe = PERIOD_M5; // Trading Timeframe (M5 or M15) input group "=== ATR Settings ===" input int ATR_Period = 14; // ATR Period input double ATR_Multiplier = 3.0; // ATR Multiplier for SuperTrend input bool ShowATRLine = true; // Show ATR Line on Chart input group "=== MACD Settings ===" input int MACD_Fast = 12; // MACD Fast EMA input int MACD_Slow = 26; // MACD Slow EMA input int MACD_Signal = 9; // MACD Signal Period input int MACD_Divergence_Bars = 10; // Bars to Check for Divergence input group "=== RSI Settings ===" input int RSI_Period = 14; // RSI Period input double RSI_Overbought = 70.0; // RSI Overbought Level input double RSI_Oversold = 30.0; // RSI Oversold Level input group "=== Trailing Stop Settings ===" input bool UseTrailingStop = true; // Use Trailing Stop input bool TrailWithATR = true; // Trail with ATR Line input group "=== Display Settings ===" input bool ShowCandleTimer = true; // Show Candle Timer input color TimerColor = clrWhite; // Timer Color //--- Global Variables int atr_handle, macd_handle, rsi_handle; double atr_buffer[], macd_main[], macd_signal[], rsi_buffer[]; double supertrend_buffer[], supertrend_trend[]; datetime last_bar_time = 0; int magic_number = 123456; string timer_label = "CandleTimer"; string atr_line_name = "ATR_SuperTrend_Line"; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Validate inputs if(LotSize <= 0) { Print("Error: Lot size must be greater than 0"); return(INIT_PARAMETERS_INCORRECT); } if(MaxTrades < 1) { Print("Error: MaxTrades must be at least 1"); return(INIT_PARAMETERS_INCORRECT); } //--- Create indicator handles atr_handle = iATR(_Symbol, Timeframe, ATR_Period); macd_handle = iMACD(_Symbol, Timeframe, MACD_Fast, MACD_Slow, MACD_Signal, PRICE_CLOSE); rsi_handle = iRSI(_Symbol, Timeframe, RSI_Period, PRICE_CLOSE); //--- Check if handles are valid if(atr_handle == INVALID_HANDLE) { Print("Error creating ATR handle. Error code: ", GetLastError()); return(INIT_FAILED); } if(macd_handle == INVALID_HANDLE) { Print("Error creating MACD handle. Error code: ", GetLastError()); return(INIT_FAILED); } if(rsi_handle == INVALID_HANDLE) { Print("Error creating RSI handle. Error code: ", GetLastError()); return(INIT_FAILED); } //--- Initialize arrays as series ArraySetAsSeries(atr_buffer, true); ArraySetAsSeries(macd_main, true); ArraySetAsSeries(macd_signal, true); ArraySetAsSeries(rsi_buffer, true); ArraySetAsSeries(supertrend_buffer, true); ArraySetAsSeries(supertrend_trend, true); //--- Set up timer for candle countdown if(ShowCandleTimer) EventSetTimer(1); //--- Enable auto trading check if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { Print("Warning: Auto trading is not allowed in the terminal"); } if(!MQLInfoInteger(MQL_TRADE_ALLOWED)) { Print("Warning: Auto trading is not allowed for this EA"); } Print("EBAKEM EA GLORY initialized successfully on ", _Symbol, " ", EnumToString(Timeframe)); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Release indicator handles if(atr_handle != INVALID_HANDLE) IndicatorRelease(atr_handle); if(macd_handle != INVALID_HANDLE) IndicatorRelease(macd_handle); if(rsi_handle != INVALID_HANDLE) IndicatorRelease(rsi_handle); //--- Remove timer EventKillTimer(); //--- Remove objects ObjectDelete(0, timer_label); DeleteATRLine(); Print("EBAKEM EA GLORY deinitialized. Reason: ", reason); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Check for new bar datetime current_bar_time = iTime(_Symbol, Timeframe, 0); if(current_bar_time == 0) { Print("Error getting bar time"); return; } bool new_bar = (current_bar_time != last_bar_time); if(new_bar) { last_bar_time = current_bar_time; //--- Update indicators if(!UpdateIndicators()) { Print("Failed to update indicators, waiting for next tick"); return; } //--- Calculate SuperTrend if(!CalculateSuperTrend()) { Print("Failed to calculate SuperTrend"); return; } //--- Draw ATR line if(ShowATRLine) DrawATRLine(); //--- Check trading conditions CheckTradingSignals(); } //--- Manage open positions ManagePositions(); } //+------------------------------------------------------------------+ //| Timer function for candle countdown | //+------------------------------------------------------------------+ void OnTimer() { if(!ShowCandleTimer) return; //--- Calculate time remaining datetime current_time = TimeCurrent(); int period_seconds = PeriodSeconds(Timeframe); datetime bar_time = iTime(_Symbol, Timeframe, 0); if(bar_time == 0) return; int seconds_remaining = period_seconds - (int)(current_time - bar_time); if(seconds_remaining < 0) seconds_remaining = 0; //--- Format time int minutes = seconds_remaining / 60; int seconds = seconds_remaining % 60; string timer_text = StringFormat("Next Candle: %02d:%02d", minutes, seconds); //--- Display on chart if(ObjectFind(0, timer_label) < 0) { ObjectCreate(0, timer_label, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, timer_label, OBJPROP_CORNER, CORNER_RIGHT_UPPER); ObjectSetInteger(0, timer_label, OBJPROP_XDISTANCE, 10); ObjectSetInteger(0, timer_label, OBJPROP_YDISTANCE, 30); ObjectSetInteger(0, timer_label, OBJPROP_COLOR, TimerColor); ObjectSetInteger(0, timer_label, OBJPROP_FONTSIZE, 10); ObjectSetString(0, timer_label, OBJPROP_FONT, "Arial"); } ObjectSetString(0, timer_label, OBJPROP_TEXT, timer_text); } //+------------------------------------------------------------------+ //| Update indicator buffers | //+------------------------------------------------------------------+ bool UpdateIndicators() { //--- Wait for data to be ready if(BarsCalculated(atr_handle) < 50 || BarsCalculated(macd_handle) < 50 || BarsCalculated(rsi_handle) < 50) { Print("Waiting for indicator data..."); return false; } //--- Copy ATR values if(CopyBuffer(atr_handle, 0, 0, 50, atr_buffer) <= 0) { Print("Error copying ATR buffer. Error: ", GetLastError()); return false; } //--- Copy MACD values if(CopyBuffer(macd_handle, 0, 0, 50, macd_main) <= 0) { Print("Error copying MACD main buffer. Error: ", GetLastError()); return false; } if(CopyBuffer(macd_handle, 1, 0, 50, macd_signal) <= 0) { Print("Error copying MACD signal buffer. Error: ", GetLastError()); return false; } //--- Copy RSI values if(CopyBuffer(rsi_handle, 0, 0, 50, rsi_buffer) <= 0) { Print("Error copying RSI buffer. Error: ", GetLastError()); return false; } return true; } //+------------------------------------------------------------------+ //| Calculate SuperTrend indicator | //+------------------------------------------------------------------+ bool CalculateSuperTrend() { int bars_available = Bars(_Symbol, Timeframe); if(bars_available < 50) { Print("Not enough bars available: ", bars_available); return false; } ArrayResize(supertrend_buffer, 50); ArrayResize(supertrend_trend, 50); ArrayInitialize(supertrend_buffer, 0); ArrayInitialize(supertrend_trend, 0); //--- Calculate from oldest to newest (reversed because of ArraySetAsSeries) for(int i = 49; i >= 0; i--) { double high = iHigh(_Symbol, Timeframe, i); double low = iLow(_Symbol, Timeframe, i); double close = iClose(_Symbol, Timeframe, i); if(high == 0 || low == 0 || close == 0) { Print("Error: Invalid price data at bar ", i); return false; } double hl_avg = (high + low) / 2.0; double basic_ub = hl_avg + ATR_Multiplier * atr_buffer[i]; double basic_lb = hl_avg - ATR_Multiplier * atr_buffer[i]; double final_ub = basic_ub; double final_lb = basic_lb; //--- Calculate final bands if(i < 49 && supertrend_buffer[i+1] != 0) { double prev_close = iClose(_Symbol, Timeframe, i+1); if(basic_ub < supertrend_buffer[i+1] || prev_close > supertrend_buffer[i+1]) final_ub = basic_ub; else final_ub = supertrend_buffer[i+1]; if(basic_lb > supertrend_buffer[i+1] || prev_close < supertrend_buffer[i+1]) final_lb = basic_lb; else final_lb = supertrend_buffer[i+1]; } //--- Determine trend and SuperTrend value if(i == 49) // Initialize first bar { if(close <= final_ub) { supertrend_buffer[i] = final_ub; supertrend_trend[i] = -1; // Downtrend } else { supertrend_buffer[i] = final_lb; supertrend_trend[i] = 1; // Uptrend } } else { if(supertrend_trend[i+1] == -1) { if(close > final_ub) { supertrend_buffer[i] = final_lb; supertrend_trend[i] = 1; } else { supertrend_buffer[i] = final_ub; supertrend_trend[i] = -1; } } else { if(close < final_lb) { supertrend_buffer[i] = final_ub; supertrend_trend[i] = -1; } else { supertrend_buffer[i] = final_lb; supertrend_trend[i] = 1; } } } } return true; } //+------------------------------------------------------------------+ //| Draw ATR SuperTrend line on chart | //+------------------------------------------------------------------+ void DrawATRLine() { DeleteATRLine(); int bars_to_draw = 100; int bars_available = Bars(_Symbol, Timeframe); if(bars_to_draw > bars_available) bars_to_draw = bars_available; if(bars_to_draw < 2) return; for(int i = 1; i < bars_to_draw && i < 50; i++) { if(supertrend_buffer[i] == 0 || supertrend_buffer[i-1] == 0) continue; string line_name = atr_line_name + IntegerToString(i); datetime time1 = iTime(_Symbol, Timeframe, i); datetime time2 = iTime(_Symbol, Timeframe, i-1); if(time1 == 0 || time2 == 0) continue; color line_color = (supertrend_trend[i] == 1) ? clrLime : clrRed; if(!ObjectCreate(0, line_name, OBJ_TREND, 0, time1, supertrend_buffer[i], time2, supertrend_buffer[i-1])) { // Object might already exist, try to modify it ObjectMove(0, line_name, 0, time1, supertrend_buffer[i]); ObjectMove(0, line_name, 1, time2, supertrend_buffer[i-1]); } ObjectSetInteger(0, line_name, OBJPROP_COLOR, line_color); ObjectSetInteger(0, line_name, OBJPROP_WIDTH, 2); ObjectSetInteger(0, line_name, OBJPROP_RAY_RIGHT, false); ObjectSetInteger(0, line_name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, line_name, OBJPROP_BACK, true); } } //+------------------------------------------------------------------+ //| Delete ATR line objects | //+------------------------------------------------------------------+ void DeleteATRLine() { int total = ObjectsTotal(0, 0, OBJ_TREND); for(int i = total - 1; i >= 0; i--) { string obj_name = ObjectName(0, i, 0, OBJ_TREND); if(StringFind(obj_name, atr_line_name) >= 0) ObjectDelete(0, obj_name); } } //+------------------------------------------------------------------+ //| Check for MACD divergence | //+------------------------------------------------------------------+ bool CheckMACDDivergence(bool &bullish_div, bool &bearish_div) { bullish_div = false; bearish_div = false; if(ArraySize(macd_main) < MACD_Divergence_Bars) return false; //--- Initialize values double price_low1 = 1000000; double price_low2 = 1000000; double price_high1 = 0; double price_high2 = 0; int low1_bar = -1, low2_bar = -1; int high1_bar = -1, high2_bar = -1; //--- Find recent lows for(int i = 1; i <= MACD_Divergence_Bars; i++) { double low = iLow(_Symbol, Timeframe, i); if(low == 0) continue; if(low < price_low1) { price_low2 = price_low1; low2_bar = low1_bar; price_low1 = low; low1_bar = i; } else if(low < price_low2) { price_low2 = low; low2_bar = i; } } //--- Find recent highs for(int i = 1; i <= MACD_Divergence_Bars; i++) { double high = iHigh(_Symbol, Timeframe, i); if(high == 0) continue; if(high > price_high1) { price_high2 = price_high1; high2_bar = high1_bar; price_high1 = high; high1_bar = i; } else if(high > price_high2) { price_high2 = high; high2_bar = i; } } //--- Check for bullish divergence if(low1_bar > 0 && low2_bar > 0 && low1_bar < ArraySize(macd_main) && low2_bar < ArraySize(macd_main)) { if(price_low1 < price_low2 && macd_main[low1_bar] > macd_main[low2_bar]) bullish_div = true; } //--- Check for bearish divergence if(high1_bar > 0 && high2_bar > 0 && high1_bar < ArraySize(macd_main) && high2_bar < ArraySize(macd_main)) { if(price_high1 > price_high2 && macd_main[high1_bar] < macd_main[high2_bar]) bearish_div = true; } return (bullish_div || bearish_div); } //+------------------------------------------------------------------+ //| Check trading signals | //+------------------------------------------------------------------+ void CheckTradingSignals() { //--- Check if maximum trades reached if(PositionsTotal() >= MaxTrades) return; //--- Ensure we have valid data if(ArraySize(supertrend_trend) < 2 || ArraySize(rsi_buffer) < 1) return; //--- Check for ATR line break bool atr_break_up = (supertrend_trend[1] == -1 && supertrend_trend[0] == 1); bool atr_break_down = (supertrend_trend[1] == 1 && supertrend_trend[0] == -1); //--- Check for MACD divergence bool bullish_div = false, bearish_div = false; CheckMACDDivergence(bullish_div, bearish_div); //--- Check RSI conditions bool rsi_oversold = rsi_buffer[0] < RSI_Oversold; bool rsi_overbought = rsi_buffer[0] > RSI_Overbought; //--- BUY Signal: ATR break up + Bullish divergence + RSI oversold if(atr_break_up && bullish_div && rsi_oversold) { Print("BUY Signal: ATR Break Up + Bullish Divergence + RSI Oversold (", DoubleToString(rsi_buffer[0], 2), ")"); OpenTrade(ORDER_TYPE_BUY); } //--- SELL Signal: ATR break down + Bearish divergence + RSI overbought if(atr_break_down && bearish_div && rsi_overbought) { Print("SELL Signal: ATR Break Down + Bearish Divergence + RSI Overbought (", DoubleToString(rsi_buffer[0], 2), ")"); OpenTrade(ORDER_TYPE_SELL); } } //+------------------------------------------------------------------+ //| Open a trade | //+------------------------------------------------------------------+ void OpenTrade(ENUM_ORDER_TYPE order_type) { //--- Check if trading is allowed if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { Print("Trading is not allowed in the terminal"); return; } MqlTradeRequest request = {}; MqlTradeResult result = {}; double price = (order_type == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID); double sl = 0; double tp = 0; //--- Calculate TP if enabled if(TakeProfit > 0) { double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); if(order_type == ORDER_TYPE_BUY) tp = NormalizeDouble(price + TakeProfit * point, _Digits); else tp = NormalizeDouble(price - TakeProfit * point, _Digits); } //--- Normalize lot size double min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); double max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double lot_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); double normalized_lot = MathFloor(LotSize / lot_step) * lot_step; normalized_lot = MathMax(normalized_lot, min_lot); normalized_lot = MathMin(normalized_lot, max_lot); //--- Fill request request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = normalized_lot; request.type = order_type; request.price = NormalizeDouble(price, _Digits); request.sl = sl; request.tp = tp; request.deviation = 10; request.magic = magic_number; request.comment = "EBAKEM EA"; request.type_filling = ORDER_FILLING_FOK; //--- Try different filling modes if FOK fails if(!OrderSend(request, result)) { request.type_filling = ORDER_FILLING_IOC; if(!OrderSend(request, result)) { request.type_filling = ORDER_FILLING_RETURN; OrderSend(request, result); } } //--- Check result if(result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED) { Print("Order opened successfully. Ticket: ", result.order, " | Type: ", EnumToString(order_type), " | Volume: ", normalized_lot, " | Price: ", price); } else { Print("OrderSend failed. Error: ", GetLastError(), " | Return code: ", result.retcode, " | Comment: ", result.comment); } } //+------------------------------------------------------------------+ //| Manage open positions | //+------------------------------------------------------------------+ void ManagePositions() { int total_positions = PositionsTotal(); for(int i = total_positions - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if(ticket <= 0) continue; if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue; if(PositionGetInteger(POSITION_MAGIC) != magic_number) continue; ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); //--- Trail with ATR line if(UseTrailingStop && TrailWithATR && ArraySize(supertrend_buffer) > 0) { TrailStopWithATR(ticket, pos_type); } //--- Close on opposite signal if(ArraySize(supertrend_trend) >= 2) { CheckCloseOnOppositeSignal(ticket, pos_type); } } } //+------------------------------------------------------------------+ //| Trail stop loss with ATR line | //+------------------------------------------------------------------+ void TrailStopWithATR(ulong ticket, ENUM_POSITION_TYPE pos_type) { if(!PositionSelectByTicket(ticket)) return; double current_sl = PositionGetDouble(POSITION_SL); double current_price = PositionGetDouble(POSITION_PRICE_CURRENT); double new_sl = supertrend_buffer[0]; if(new_sl == 0) return; double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); double min_distance = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * point; //--- For buy positions if(pos_type == POSITION_TYPE_BUY) { if(supertrend_trend[0] == 1) // Still in uptrend { // Ensure new SL is below current price if(new_sl < current_price - min_distance) { if(new_sl > current_sl + point || current_sl == 0) { ModifyPosition(ticket, new_sl, PositionGetDouble(POSITION_TP)); } } } } //--- For sell positions else if(pos_type == POSITION_TYPE_SELL) { if(supertrend_trend[0] == -1) // Still in downtrend { // Ensure new SL is above current price if(new_sl > current_price + min_distance) { if(new_sl < current_sl - point || current_sl == 0) { ModifyPosition(ticket, new_sl, PositionGetDouble(POSITION_TP)); } } } } } //+------------------------------------------------------------------+ //| Check and close on opposite trading signal | //+------------------------------------------------------------------+ void CheckCloseOnOppositeSignal(ulong ticket, ENUM_POSITION_TYPE pos_type) { //--- Close buy on ATR break down if(pos_type == POSITION_TYPE_BUY && supertrend_trend[1] == 1 && supertrend_trend[0] == -1) { ClosePosition(ticket); Print("Closing BUY position #", ticket, " on opposite ATR signal"); } //--- Close sell on ATR break up if(pos_type == POSITION_TYPE_SELL && supertrend_trend[1] == -1 && supertrend_trend[0] == 1) { ClosePosition(ticket); Print("Closing SELL position #", ticket, " on opposite ATR signal"); } } //+------------------------------------------------------------------+ //| Modify position SL/TP | //+------------------------------------------------------------------+ void ModifyPosition(ulong ticket, double sl, double tp) { if(!PositionSelectByTicket(ticket)) return; MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_SLTP; request.position = ticket; request.symbol = _Symbol; request.sl = NormalizeDouble(sl, _Digits); request.tp = NormalizeDouble(tp, _Digits); if(!OrderSend(request, result)) { Print("ModifyPosition failed for ticket ", ticket, ". Error: ", GetLastError(), " | Return code: ", result.retcode); } else { Print("Position #", ticket, " modified. New SL: ", sl); } } //+------------------------------------------------------------------+ //| Close position | //+------------------------------------------------------------------+ void ClosePosition(ulong ticket) { if(!PositionSelectByTicket(ticket)) return; MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_DEAL; request.position = ticket; request.symbol = _Symbol; request.volume = PositionGetDouble(POSITION_VOLUME); request.type = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY; request.price = (request.type == ORDER_TYPE_SELL) ? SymbolInfoDouble(_Symbol, SYMBOL_BID) : SymbolInfoDouble(_Symbol, SYMBOL_ASK); request.deviation = 10; request.magic = magic_number; request.type_filling = ORDER_FILLING_FOK; //--- Try different filling modes if(!OrderSend(request, result)) { request.type_filling = ORDER_FILLING_IOC; if(!OrderSend(request, result)) { request.type_filling = ORDER_FILLING_RETURN; OrderSend(request, result); } } if(result.retcode == TRADE_RETCODE_DONE) { Print("Position #", ticket, " closed successfully"); } else { Print("ClosePosition failed for ticket ", ticket, ". Error: ", GetLastError(), " | Return code: ", result.retcode); } } //+------------------------------------------------------------------+