//+------------------------------------------------------------------+ //| MACD_Scalper_EA_v7.0.mq5 | //| MACD Scalper Expert Advisor v7.0 - OPTIMIZED | //| Improvements: Trend Filter, Risk Management, Better Signals | //+------------------------------------------------------------------+ #property copyright "MACD Scalper Trading - v7.0" #property link "https://www.mql5.com" #property version "7.00" #property strict //+------------------------------------------------------------------+ //| INPUT PARAMETERS | //+------------------------------------------------------------------+ //--- MACD INDICATOR input int macdFastPeriod = 12; // MACD Fast EMA Period input int macdSlowPeriod = 26; // MACD Slow EMA Period input int macdSignalPeriod = 9; // MACD Signal Line Period //--- STOCHASTIC INDICATOR (OPTIMIZED) input int stochKPeriod = 14; // Stochastic K Period input int stochDPeriod = 3; // Stochastic D Period input int stochSlowing = 3; // Stochastic Slowing input int stochOverbought = 85; // Overbought Level (WAS 80, NOW MORE EXTREME) input int stochOversold = 15; // Oversold Level (WAS 20, NOW MORE EXTREME) //--- TREND FILTER (NEW) input int emaTrendPeriod = 50; // EMA Trend Confirmation Period input double macdHistStrength = 0.0001; // Min MACD Histogram strength //--- MONEY MANAGEMENT (OPTIMIZED) input double lotSize = 0.05; // Lot Size (REDUCED from 0.1 for risk management) input int slPips = 70; // Stop Loss (pips) (WAS 120, NOW TIGHTER) input int tpPips = 150; // Take Profit (pips) (WAS 120, NOW LARGER - 1:2.14 R:R) input int maxDailyLoss = 500; // Max Daily Loss in USD (NEW) //--- FILTERS input int maxSpread = 20; // Maximum Spread (pips) input int maxSlippage = 15; // Maximum Slippage (pips) input ulong magicNumber = 12347; // Magic Number (UPDATED for v7.0) //--- INDICATOR INITIALIZATION input int minBarsForMACD = 35; // Minimum bars for MACD input int minBarsForStoch = 20; // Minimum bars for Stochastic input int minBarsForEMA = 55; // Minimum bars for EMA //--- TRADING HOURS FILTER (NEW) input int startHour = 2; // Start trading hour (London open) input int endHour = 22; // End trading hour input bool useTradingHours = true; // Enable trading hours filter //+------------------------------------------------------------------+ //| GLOBAL VARIABLES | //+------------------------------------------------------------------+ int macdHandle = INVALID_HANDLE; // MACD Indicator Handle int stochHandle = INVALID_HANDLE; // Stochastic Indicator Handle int emaHandle = INVALID_HANDLE; // EMA Trend Indicator Handle (NEW) int atrHandle = INVALID_HANDLE; // ATR Volatility Handle (NEW) double macdMain[3]; // MACD Main Line (Buffer 0) double macdSignal[3]; // MACD Signal Line (Buffer 1) double macdHist[3]; // MACD Histogram (Manual: Main - Signal) double stochK[3]; // Stochastic K Buffer (3 bars) double emaTrend[2]; // EMA Trend (2 bars) (NEW) double atrValue[2]; // ATR Value (2 bars) (NEW) bool isInitialized = false; // Initialization Flag bool indicatorsReady = false; // Indicators Ready Flag int tradeCount = 0; // Total trades opened double dailyProfit = 0; // Daily Profit Tracker (NEW) datetime lastDayReset = 0; // Last daily reset time (NEW) //+------------------------------------------------------------------+ //| HELPER FUNCTIONS | //+------------------------------------------------------------------+ /// Get current Bid price double GetBid() { return SymbolInfoDouble(Symbol(), SYMBOL_BID); } /// Get current Ask price double GetAsk() { return SymbolInfoDouble(Symbol(), SYMBOL_ASK); } /// Get current Spread in pips int GetSpread() { return (int)((GetAsk() - GetBid()) / Point()); } /// Check if spread is acceptable bool IsSpreadOK() { return GetSpread() <= maxSpread; } /// Check if trading within allowed hours (NEW) - FIXED bool IsTradingHours() { if(!useTradingHours) return true; datetime currentTime = TimeCurrent(); MqlDateTime timeStruct; TimeToStruct(currentTime, timeStruct); int hour = timeStruct.hour; return (hour >= startHour && hour < endHour); } /// Update daily profit tracker (NEW) - FIXED void UpdateDailyProfit() { datetime currentTime = TimeCurrent(); MqlDateTime timeStruct; TimeToStruct(currentTime, timeStruct); // Get start of day (00:00:00) datetime dayStart = currentTime - (timeStruct.hour * 3600 + timeStruct.min * 60 + timeStruct.sec); if(lastDayReset != dayStart) { lastDayReset = dayStart; dailyProfit = 0; Print("✓ Daily profit reset: ", TimeToString(currentTime)); } // Calculate current day P&L from all positions dailyProfit = 0; for(int i = PositionsTotal() - 1; i >= 0; i--) { if(!PositionGetTicket(i)) continue; if(PositionGetString(POSITION_SYMBOL) == Symbol() && PositionGetInteger(POSITION_MAGIC) == magicNumber) { double profit = PositionGetDouble(POSITION_PROFIT); dailyProfit += profit; } } } /// Check daily loss limit (NEW) bool IsDailyLossOK() { UpdateDailyProfit(); if(dailyProfit < -maxDailyLoss) { Print("⚠️ Daily loss limit reached: ", DoubleToString(dailyProfit, 2), " USD"); return false; } return true; } //+------------------------------------------------------------------+ //| INDICATOR UPDATE FUNCTION | //+------------------------------------------------------------------+ /// Update indicator buffers - v7.0 with all filters bool UpdateIndicators() { // Check handles validity if(macdHandle == INVALID_HANDLE || stochHandle == INVALID_HANDLE || emaHandle == INVALID_HANDLE || atrHandle == INVALID_HANDLE) return false; // Check if indicators are calculated if(BarsCalculated(macdHandle) < minBarsForMACD || BarsCalculated(stochHandle) < minBarsForStoch || BarsCalculated(emaHandle) < minBarsForEMA || BarsCalculated(atrHandle) < minBarsForEMA) return false; // Copy MACD Main Line (Buffer 0) - 3 bars if(CopyBuffer(macdHandle, 0, 0, 3, macdMain) < 3) return false; // Copy MACD Signal Line (Buffer 1) - 3 bars if(CopyBuffer(macdHandle, 1, 0, 3, macdSignal) < 3) return false; // Calculate MACD Histogram MANUALLY (Main - Signal) for(int i = 0; i < 3; i++) { macdHist[i] = macdMain[i] - macdSignal[i]; } // Copy Stochastic K (Buffer 0) - 3 bars if(CopyBuffer(stochHandle, 0, 0, 3, stochK) < 3) return false; // Copy EMA Trend (Buffer 0) - 2 bars (NEW) if(CopyBuffer(emaHandle, 0, 0, 2, emaTrend) < 2) return false; // Copy ATR Value (Buffer 0) - 2 bars (NEW) if(CopyBuffer(atrHandle, 0, 0, 2, atrValue) < 2) return false; return true; } //+------------------------------------------------------------------+ //| SIGNAL CHECKING FUNCTIONS | //+------------------------------------------------------------------+ /// Check for BUY signal (Enhanced with trend filter + volatility) bool CheckBuySignal() { // FILTER 1: Trading hours check (NEW) if(!IsTradingHours()) return false; // FILTER 2: Daily loss limit (NEW) if(!IsDailyLossOK()) return false; // FILTER 3: Spread check if(!IsSpreadOK()) return false; // FILTER 4: Trend confirmation - Price above EMA50 (NEW) double bid = GetBid(); if(bid <= emaTrend[1]) return false; // Not in uptrend // FILTER 5: MACD Momentum strength check (NEW) double macdHistAbs = MathAbs(macdHist[1]); if(macdHistAbs < macdHistStrength) return false; // Momentum too weak // FILTER 6: MACD Momentum: crossed below zero → above zero if(!(macdHist[2] <= 0 && macdHist[1] > 0)) return false; // FILTER 7: Stochastic: in oversold area AND rising (OPTIMIZED) // Now uses stricter levels: oversold < 15 if(!(stochK[2] < stochOversold && stochK[1] > stochK[2])) return false; // Stoch not rising from extreme oversold // FILTER 8: Volatility check - ATR sanity (NEW) // Only trade if volatility is reasonable if(atrValue[1] < 0.0005 * GetAsk()) return false; // Too low volatility return true; } /// Check for SELL signal (Enhanced with trend filter + volatility) bool CheckSellSignal() { // FILTER 1: Trading hours check (NEW) if(!IsTradingHours()) return false; // FILTER 2: Daily loss limit (NEW) if(!IsDailyLossOK()) return false; // FILTER 3: Spread check if(!IsSpreadOK()) return false; // FILTER 4: Trend confirmation - Price below EMA50 (NEW) double ask = GetAsk(); if(ask >= emaTrend[1]) return false; // Not in downtrend // FILTER 5: MACD Momentum strength check (NEW) double macdHistAbs = MathAbs(macdHist[1]); if(macdHistAbs < macdHistStrength) return false; // Momentum too weak // FILTER 6: MACD Momentum: crossed above zero → below zero if(!(macdHist[2] >= 0 && macdHist[1] < 0)) return false; // FILTER 7: Stochastic: in overbought area AND falling (OPTIMIZED) // Now uses stricter levels: overbought > 85 if(!(stochK[2] > stochOverbought && stochK[1] < stochK[2])) return false; // Stoch not falling from extreme overbought // FILTER 8: Volatility check - ATR sanity (NEW) if(atrValue[1] < 0.0005 * GetAsk()) return false; // Too low volatility return true; } //+------------------------------------------------------------------+ //| ORDER FUNCTIONS | //+------------------------------------------------------------------+ /// Check if position TP is reached bool IsTPReached() { for(int i = PositionsTotal() - 1; i >= 0; i--) { if(!PositionGetTicket(i)) continue; if(PositionGetString(POSITION_SYMBOL) != Symbol() || PositionGetInteger(POSITION_MAGIC) != magicNumber) continue; ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); double currentPrice = (posType == POSITION_TYPE_BUY) ? GetBid() : GetAsk(); if(posType == POSITION_TYPE_BUY) { if(currentPrice >= openPrice + (tpPips * Point())) return true; } else { if(currentPrice <= openPrice - (tpPips * Point())) return true; } } return false; } /// Close all positions void CloseAllPositions() { for(int i = PositionsTotal() - 1; i >= 0; i--) { if(!PositionGetTicket(i)) continue; if(PositionGetString(POSITION_SYMBOL) != Symbol() || PositionGetInteger(POSITION_MAGIC) != magicNumber) continue; ulong ticket = PositionGetInteger(POSITION_TICKET); ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); double closingProfit = PositionGetDouble(POSITION_PROFIT); MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_DEAL; request.symbol = Symbol(); request.type = (posType == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY; request.position = ticket; request.deviation = maxSlippage; request.comment = "Close by TP"; request.type_filling = ORDER_FILLING_IOC; if(!OrderSend(request, result)) { Print("❌ Failed to close position: ", GetLastError()); } else { Print("✓ Position closed with profit: ", DoubleToString(closingProfit, 2), " USD"); } } } /// Open BUY order void OpenBuyOrder() { if(!IsSpreadOK()) return; double ask = GetAsk(); double sl = ask - (slPips * Point()); double tp = ask + (tpPips * Point()); MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_BUY; request.symbol = Symbol(); request.volume = lotSize; request.price = ask; request.sl = sl; request.tp = tp; request.deviation = maxSlippage; request.magic = magicNumber; request.comment = "MACD Scalper v7.0 BUY"; request.type_filling = ORDER_FILLING_IOC; if(OrderSend(request, result)) { tradeCount++; Print("✓ BUY #", tradeCount, " @ ", DoubleToString(ask, Digits()), " SL=", DoubleToString(sl, Digits()), " TP=", DoubleToString(tp, Digits()), " R:R=1:", DoubleToString((double)tpPips / (double)slPips, 2)); } else { Print("❌ Failed to open BUY: ", GetLastError()); } } /// Open SELL order void OpenSellOrder() { if(!IsSpreadOK()) return; double bid = GetBid(); double sl = bid + (slPips * Point()); double tp = bid - (tpPips * Point()); MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_DEAL; request.type = ORDER_TYPE_SELL; request.symbol = Symbol(); request.volume = lotSize; request.price = bid; request.sl = sl; request.tp = tp; request.deviation = maxSlippage; request.magic = magicNumber; request.comment = "MACD Scalper v7.0 SELL"; request.type_filling = ORDER_FILLING_IOC; if(OrderSend(request, result)) { tradeCount++; Print("✓ SELL #", tradeCount, " @ ", DoubleToString(bid, Digits()), " SL=", DoubleToString(sl, Digits()), " TP=", DoubleToString(tp, Digits()), " R:R=1:", DoubleToString((double)tpPips / (double)slPips, 2)); } else { Print("❌ Failed to open SELL: ", GetLastError()); } } //+------------------------------------------------------------------+ //| INITIALIZATION FUNCTION | //+------------------------------------------------------------------+ int OnInit() { // Create MACD indicator macdHandle = iMACD(Symbol(), Period(), macdFastPeriod, macdSlowPeriod, macdSignalPeriod, PRICE_CLOSE); if(macdHandle == INVALID_HANDLE) { Print("❌ Error creating MACD"); return INIT_FAILED; } // Create Stochastic indicator stochHandle = iStochastic(Symbol(), Period(), stochKPeriod, stochDPeriod, stochSlowing, MODE_SMA, STO_LOWHIGH); if(stochHandle == INVALID_HANDLE) { Print("❌ Error creating Stochastic"); return INIT_FAILED; } // Create EMA Trend indicator (NEW) emaHandle = iMA(Symbol(), Period(), emaTrendPeriod, 0, MODE_EMA, PRICE_CLOSE); if(emaHandle == INVALID_HANDLE) { Print("❌ Error creating EMA"); return INIT_FAILED; } // Create ATR indicator (NEW) atrHandle = iATR(Symbol(), Period(), 14); if(atrHandle == INVALID_HANDLE) { Print("❌ Error creating ATR"); return INIT_FAILED; } // Set arrays as series ArraySetAsSeries(macdMain, true); ArraySetAsSeries(macdSignal, true); ArraySetAsSeries(macdHist, true); ArraySetAsSeries(stochK, true); ArraySetAsSeries(emaTrend, true); ArraySetAsSeries(atrValue, true); isInitialized = true; Print("✓ EA v7.0 Initialized Successfully!"); Print("✓ Improvements: EMA Trend, ATR Volatility, Daily Loss Limit"); Print("✓ Optimized Stoch Levels: Oversold=", stochOversold, " Overbought=", stochOverbought); Print("✓ Better R:R Ratio: 1:", DoubleToString((double)tpPips / (double)slPips, 2)); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| DEINITIALIZATION FUNCTION | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Release indicator handles if(macdHandle != INVALID_HANDLE) IndicatorRelease(macdHandle); if(stochHandle != INVALID_HANDLE) IndicatorRelease(stochHandle); if(emaHandle != INVALID_HANDLE) IndicatorRelease(emaHandle); if(atrHandle != INVALID_HANDLE) IndicatorRelease(atrHandle); Print("✓ EA v7.0 Deinitialized"); Print("✓ Total trades: ", tradeCount); Print("✓ Final daily profit: ", DoubleToString(dailyProfit, 2), " USD"); } //+------------------------------------------------------------------+ //| MAIN TRADING LOOP | //+------------------------------------------------------------------+ void OnTick() { if(!isInitialized) return; // Update indicators if(!UpdateIndicators()) { if(!indicatorsReady) return; } else if(!indicatorsReady) { indicatorsReady = true; Print("✓ Indicators ready! Starting to trade..."); } if(!indicatorsReady) return; // Check if position exists bool hasPosition = false; for(int i = PositionsTotal() - 1; i >= 0; i--) { if(!PositionGetTicket(i)) continue; if(PositionGetString(POSITION_SYMBOL) == Symbol() && PositionGetInteger(POSITION_MAGIC) == magicNumber) { hasPosition = true; break; } } // Close position if TP reached if(hasPosition && IsTPReached()) CloseAllPositions(); // Check entry signals (only if no position) if(!hasPosition) { if(CheckBuySignal()) OpenBuyOrder(); else if(CheckSellSignal()) OpenSellOrder(); } } //+------------------------------------------------------------------+ //| END OF EXPERT ADVISOR v7.0 - OPTIMIZED & IMPROVED | //+------------------------------------------------------------------+