// Input Parameters #include #include "../_united/MagicNumberHelpers.mqh" input group "Trade Management" input int MagicNumber = 7; input int rsiPeriod = 19; // RSI period input int overboughtLevel = 93; // Overbought level (RSI > 70 for sell) input int oversoldLevel = 22; // Oversold level (RSI < 30 for buy) input double entryRSIBuySpread = 0; input double entryRSISellSpread = 0; input double lotSize = 0.1; // Trade lot size input int slippage = 3; // Slippage for orders input int cooldownSeconds = 209; // Cooldown period in seconds input ENUM_TIMEFRAMES TimeFrame1 = PERIOD_M1; // RSI Timeframe input ENUM_TIMEFRAMES TimeFrame2 = PERIOD_M1; // EMA Timeframe input ENUM_TIMEFRAMES BarTimeFrame = PERIOD_M12; // EMA Timeframe input int emaPeriod = 140; // EMA period input double emaSlopeThreshold = 105; // EMA slope threshold for trend strength input double exitBuyRSI = 86; input double exitSellRSI = 10; input double TrailingStop = 295; input double emaDistanceThreshold = 165; input int tradingHourOneBegin = 24; input int tradingHourOneEnd = 22; input int tradingHourTwoBegin = 6; input int tradingHourTwoEnd = 19; datetime bartime; // RSI Handle int rsiHandle; input bool Sunday =false; // Sunday input bool Monday =false; // Monday input bool Tuesday =true; // Tuesday input bool Wednesday=true; // Wednesday input bool Thursday =true; // Thursday input bool Friday =false; // Friday input bool Saturday =false; // Saturday bool WeekDays[7]; void WeekDays_Init() { WeekDays[0]=Sunday; WeekDays[1]=Monday; WeekDays[2]=Tuesday; WeekDays[3]=Wednesday; WeekDays[4]=Thursday; WeekDays[5]=Friday; WeekDays[6]=Saturday; } bool WeekDays_Check(datetime aTime) { MqlDateTime stm; TimeToStruct(aTime,stm); return(WeekDays[stm.day_of_week]); } // EMA Handle int emaHandle; double previousRSIDef = 0; // Create CTrade object for executing trades CTrade trade; // Track the last trade time datetime lastTradeTime = 0; void OnInit() { WeekDays_Init(); // Create RSI handle rsiHandle = iRSI(_Symbol, TimeFrame1, rsiPeriod, PRICE_CLOSE); if (rsiHandle == INVALID_HANDLE) { Print("Error creating RSI handle: ", GetLastError()); return; } // Create EMA handle emaHandle = iMA(_Symbol, TimeFrame2, emaPeriod, 0, MODE_EMA, PRICE_CLOSE); if (emaHandle == INVALID_HANDLE) { Print("Error creating EMA handle: ", GetLastError()); return; } // Initialization successful Print("RSI and EMA Reversal Strategy Initialized."); } void OnTick() { if(bartime==iTime(_Symbol,BarTimeFrame,0))return; bartime=iTime(_Symbol,BarTimeFrame,0); // Check if RSI data is available double rsi[]; if (CopyBuffer(rsiHandle, 0, 0, 2, rsi) <= 0) { Print("Error copying RSI data: ", GetLastError()); return; } // Check if EMA data is available double ema[]; if (CopyBuffer(emaHandle, 0, 0, 2, ema) <= 0) { Print("Error copying EMA data: ", GetLastError()); return; } // Get the current time datetime currentTime = TimeCurrent(); int currentHour = TimeHour(TimeCurrent()); if(!WeekDays_Check(TimeTradeServer())) { Close_Position_MN(MagicNumber); return; } if (!(currentHour < tradingHourOneEnd && currentHour > tradingHourOneBegin || currentHour < tradingHourTwoEnd && currentHour > tradingHourTwoBegin)) { Close_Position_MN(MagicNumber); return; // Prevent further trading during this time } // Ensure there is at least one position bool hasPosition = PositionExistsByMagic(_Symbol, MagicNumber); // Get the current and previous RSI values double currentRSI = rsi[0]; double previousRSI = rsi[1]; if(previousRSIDef == 0) { previousRSIDef = currentRSI; return; } // Get the current and previous EMA values double currentEMA = ema[0]; double previousEMA = ema[1]; // Calculate the EMA slope (difference between current and previous EMA values) double emaSlope = (currentEMA - previousEMA) * 100; Print(emaSlope); double closeCurr = iClose(Symbol(), Period(), 0); // Close of current bar // ** NEW CODE: Calculate distance to EMA and adjust score ** double priceToEmaDistance = (closeCurr - currentEMA) * 10; // Distance between the current price and the EMA Print("priceToEmaDistance"); Print(priceToEmaDistance); // Determine if there are existing buy or sell positions bool isBuyPosition = false; bool isSellPosition = false; if (hasPosition) { if (PositionSelectByMagic(_Symbol, MagicNumber)) { int positionType = PositionGetInteger(POSITION_TYPE); if (positionType == POSITION_TYPE_BUY) { isBuyPosition = true; } else if (positionType == POSITION_TYPE_SELL) { isSellPosition = true; } } } ApplyTrailingStop(); // Check if the cooldown period has elapsed since the last trade bool cooldownPassed = (currentTime - lastTradeTime) >= cooldownSeconds; // Check if EMA slope is above the threshold (indicating strong trend) bool isTrendStrong = MathAbs(emaSlope) > emaSlopeThreshold || MathAbs(priceToEmaDistance) > emaDistanceThreshold; // Close trade logic when RSI crosses 50 if (isBuyPosition && currentRSI > exitBuyRSI) { // Close buy position Close_Position_MN(MagicNumber); lastTradeTime = currentTime; // Update last trade time } if (isSellPosition && currentRSI < exitSellRSI) { Close_Position_MN(MagicNumber); lastTradeTime = currentTime; // Update last trade time } // If the EMA slope is strong, do not place new trades if (isTrendStrong) { Close_Position_MN(MagicNumber); lastTradeTime = currentTime; // Update last trade time Print("Strong trend detected (EMA slope), skipping new trade."); return; } // SELL logic (RSI crosses over the overbought level) if (currentRSI < overboughtLevel - entryRSISellSpread && previousRSIDef >= overboughtLevel && !isSellPosition && !hasPosition && cooldownPassed) { trade.SetExpertMagicNumber(MagicNumber); if (trade.Sell(lotSize, _Symbol, 0, 0, "Sell Order")) { Print("Sell order placed."); lastTradeTime = currentTime; // Update last trade time } else { Print("Error placing sell order: ", GetLastError()); } } // BUY logic (RSI crosses below the oversold level) if (currentRSI > oversoldLevel + entryRSIBuySpread && previousRSIDef <= oversoldLevel && !isBuyPosition && !hasPosition && cooldownPassed) { trade.SetExpertMagicNumber(MagicNumber); if (trade.Buy(lotSize, _Symbol, 0, 0, "Buy Order")) { Print("Buy order placed."); lastTradeTime = currentTime; // Update last trade time } else { Print("Error placing buy order: ", GetLastError()); } } previousRSIDef = currentRSI; } void OnDeinit(const int reason) { // Release RSI and EMA handles on deinitialization if (rsiHandle != INVALID_HANDLE) { IndicatorRelease(rsiHandle); Print("RSI handle released."); } if (emaHandle != INVALID_HANDLE) { IndicatorRelease(emaHandle); Print("EMA handle released."); } } void Close_Position_MN(ulong magicNumber) { // Use helper function to close position by magic number ClosePositionByMagic(trade, _Symbol, (int)magicNumber); } void ApplyTrailingStop() { Print("Scanning for trailing stop"); // Check if position exists with our magic number if(!PositionSelectByMagic(_Symbol, MagicNumber)) { return; // No position with our magic number } ulong PositionTicket = PositionGetInteger(POSITION_TICKET); long trade_type = PositionGetInteger(POSITION_TYPE); string symbol = _Symbol; double POINT = SymbolInfoDouble(symbol, SYMBOL_POINT); int DIGIT = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS); if(trade_type == POSITION_TYPE_BUY) { double Bid = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_BID), DIGIT); if(Bid - PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * TrailingStop, DIGIT)) { if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * TrailingStop, DIGIT)) { ModifyPositionByMagic(trade, symbol, MagicNumber, NormalizeDouble(Bid - POINT * TrailingStop, DIGIT), PositionGetDouble(POSITION_TP)); } } } else if(trade_type == POSITION_TYPE_SELL) { double Ask = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), DIGIT); if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble(POINT * TrailingStop, DIGIT)) { if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * TrailingStop, DIGIT)) || (PositionGetDouble(POSITION_SL) == 0)) { ModifyPositionByMagic(trade, symbol, MagicNumber, NormalizeDouble(Ask + POINT * TrailingStop, DIGIT), PositionGetDouble(POSITION_TP)); } } } } int TimeHour(datetime when=0){ if(when == 0) when = TimeCurrent(); return when / 3600 % 24; }