//+------------------------------------------------------------------+ //| RSI Trend Pullback EA (M15) | //| Intraday, Trend-Following, Multi-TP, Auto-Pause | //+------------------------------------------------------------------+ #property strict #include CTrade trade; //==================== INPUTS ====================// input ENUM_TIMEFRAMES TF = PERIOD_M15; // Trend input int EMA_Fast_Period = 50; input int EMA_Slow_Period = 200; input double Min_EMA_Slope = 0.0; // RSI input int RSI_Period = 14; input double RSI_Buy_Low = 42; input double RSI_Buy_High = 50; input double RSI_Sell_Low = 50; input double RSI_Sell_High = 58; input double RSI_Trigger = 50; // ATR input int ATR_Period = 14; input double ATR_Min = 0.00055; input double ATR_Pause = 0.00045; // Risk input double Risk_Per_Trade = 0.5; input int Max_Trades_Per_Session = 3; input double Max_Daily_Loss = -2.0; // Scaling input double SL_ATR = 1.2; input double TP1_ATR = 0.8; input double TP2_ATR = 1.6; input double TP3_ATR = 2.6; // Sessions (GMT) input bool Enable_London = true; input bool Enable_NY_Overlap = true; //==================== GLOBALS ====================// int hEMA_Fast, hEMA_Slow, hRSI, hATR; bool TradingPaused = false; int TradesToday = 0; int ConsecutiveLosses = 0; double DailyPnL = 0.0; datetime LastBarTime = 0; //==================== INIT ====================// int OnInit() { hEMA_Fast = iMA(_Symbol, TF, EMA_Fast_Period, 0, MODE_EMA, PRICE_CLOSE); hEMA_Slow = iMA(_Symbol, TF, EMA_Slow_Period, 0, MODE_EMA, PRICE_CLOSE); hRSI = iRSI(_Symbol, TF, RSI_Period, PRICE_CLOSE); hATR = iATR(_Symbol, TF, ATR_Period); if(hEMA_Fast < 0 || hRSI < 0 || hATR < 0) return INIT_FAILED; return INIT_SUCCEEDED; } //==================== ON TICK ====================// void OnTick() { if(!IsNewBar()) return; if(!IsSessionActive()) return; double emaFast = GetValue(hEMA_Fast); double emaSlow = GetValue(hEMA_Slow); double rsiCur = GetValue(hRSI, 0); double rsiPrev = GetValue(hRSI, 1); double atr = GetValue(hATR); if(TradingPaused) { if(CanResumeTrading(atr, emaFast, emaSlow, rsiCur)) TradingPaused = false; else return; } if(MarketDeteriorated(atr, emaFast, emaSlow)) { TradingPaused = true; return; } if(TradesToday >= Max_Trades_Per_Session) return; double price = SymbolInfoDouble(_Symbol, SYMBOL_BID); // BUY SETUP if(emaFast > emaSlow && price > emaFast) { if(rsiPrev >= RSI_Buy_Low && rsiPrev <= RSI_Buy_High && rsiCur > RSI_Trigger) ExecuteTrade(ORDER_TYPE_BUY, atr); } // SELL SETUP if(emaFast < emaSlow && price < emaFast) { if(rsiPrev <= RSI_Sell_High && rsiPrev >= RSI_Sell_Low && rsiCur < RSI_Trigger) ExecuteTrade(ORDER_TYPE_SELL, atr); } } //==================== FUNCTIONS ====================// bool IsNewBar() { datetime t = iTime(_Symbol, TF, 0); if(t != LastBarTime) { LastBarTime = t; return true; } return false; } bool IsSessionActive() { datetime gmt = TimeGMT(); int h = TimeHour(gmt); if(Enable_London && h >= 7 && h <= 10) return true; if(Enable_NY_Overlap && h >= 12 && h <= 16) return true; return false; } bool MarketDeteriorated(double atr, double emaFast, double emaSlow) { int conditions = 0; if(atr < ATR_Pause) conditions++; if(MathAbs(emaFast - emaSlow) < (0.3 * atr)) conditions++; if(ConsecutiveLosses >= 3) conditions++; return (conditions >= 2); } bool CanResumeTrading(double atr, double emaFast, double emaSlow, double rsi) { if(atr >= ATR_Min && MathAbs(emaFast - emaSlow) > (0.4 * atr) && (rsi < 45 || rsi > 55)) return true; return false; } double GetValue(int handle, int shift = 0) { double buffer[]; CopyBuffer(handle, 0, shift, 1, buffer); return buffer[0]; } void ExecuteTrade(ENUM_ORDER_TYPE type, double atr) { double lot = CalculateLotSize(atr); double price = (type == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID); double sl = (type == ORDER_TYPE_BUY) ? price - SL_ATR * atr : price + SL_ATR * atr; double tp1 = (type == ORDER_TYPE_BUY) ? price + TP1_ATR * atr : price - TP1_ATR * atr; trade.PositionOpen(_Symbol, type, lot * 0.4, price, sl, tp1); trade.PositionOpen(_Symbol, type, lot * 0.3, price, sl, 0); trade.PositionOpen(_Symbol, type, lot * 0.3, price, sl, 0); TradesToday++; } double CalculateLotSize(double atr) { double riskMoney = AccountInfoDouble(ACCOUNT_BALANCE) * Risk_Per_Trade / 100.0; double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); double slPoints = atr * SL_ATR / _Point; return NormalizeDouble(riskMoney / (slPoints * tickValue), 2); }