//+------------------------------------------------------------------+ //| Valid_Break_Detector | //| Copyright 2023, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property description "Detects Valid Breakouts of Zones with Rejection Confirmation" // Input Parameters input double LotSize = 0.1; // Lot size for trades input int StopLoss = 50; // Stop Loss in points input int TakeProfit = 100; // Take Profit in points input bool RequireVolumeSpike = true; // Enable volume spike filter input double VolumeThreshold = 1.5; // Minimum volume increase factor input bool RequireCloseBeyond = true; // Require candle close beyond the zone input int RejectionConfirmationCandles = 2; // Number of candles to confirm rejection // Global Variables int MagicNumber = 789101; // double _Ask = 0; double _Bid = 0; // Zone Boundaries double ZoneHigh = 0; double ZoneLow = 0; // double maBuffer[]; int maHandler = INVALID_HANDLE; // Breakout Status bool BullishBreakoutDetected = false; bool BearishBreakoutDetected = false; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // ArraySetAsSeries(maBuffer, true); maHandler = iMA( _Symbol, _Period, 14, 0, MODE_SMA, VOLUME_TICK // ); if (maHandler == INVALID_HANDLE) { return (INIT_FAILED); } // Print("Valid Break Detector EA Initialized"); return (INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // IndicatorRelease(maHandler); Print("Valid Break Detector EA Deinitialized"); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // _Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); _Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); CopyBuffer(maHandler, MAIN_LINE, 0, 14, maBuffer); // Define the zone dynamically (e.g., based on recent highs/lows) DefineZone(); // Check for valid break of the zone CheckValidBreak(); // Confirm rejection after breakout if (BullishBreakoutDetected || BearishBreakoutDetected) ConfirmRejection(); } //+------------------------------------------------------------------+ //| Function to define the zone dynamically | //+------------------------------------------------------------------+ void DefineZone() { // Example: Define zone based on recent highs and lows ZoneHigh = iHigh(_Symbol, _Period, 1); // Recent high ZoneLow = iLow(_Symbol, _Period, 2); // Recent low } //+------------------------------------------------------------------+ //| Function to check for a valid break of the zone | //+------------------------------------------------------------------+ void CheckValidBreak() { double currentPrice = _Bid; // Check if price breaks above the zone if (!BullishBreakoutDetected && currentPrice > ZoneHigh) { if (IsValidBreak(ZoneHigh, true)) { Print("Potential Bullish Break Above Zone Detected at ", TimeToString(TimeCurrent(), TIME_DATE)); BullishBreakoutDetected = true; } } // Check if price breaks below the zone if (!BearishBreakoutDetected && currentPrice < ZoneLow) { if (IsValidBreak(ZoneLow, false)) { Print("Potential Bearish Break Below Zone Detected at ", TimeToString(TimeCurrent(), TIME_DATE)); BearishBreakoutDetected = true; } } } //+------------------------------------------------------------------+ //| Function to validate the breakout | //+------------------------------------------------------------------+ bool IsValidBreak(double zoneLevel, bool isAbove) { // Check if the candle closed beyond the zone if (RequireCloseBeyond) { double closePrice = iClose(_Symbol, _Period, 1); if ((isAbove && closePrice <= zoneLevel) || (!isAbove && closePrice >= zoneLevel)) return false; } // Check for a volume spike if (RequireVolumeSpike) { double currentVolume = (double) iVolume(_Symbol, _Period, 1); double averageVolume = maBuffer[1]; if (currentVolume < VolumeThreshold * averageVolume) return false; } // All conditions met, valid breakout return true; } //+------------------------------------------------------------------+ //| Function to confirm rejection | //+------------------------------------------------------------------+ void ConfirmRejection() { double currentPrice = _Bid; if (BullishBreakoutDetected) { // Check if price rejects lower levels and confirms bullish breakout bool confirmed = true; for (int i = 1; i <= RejectionConfirmationCandles; i++) { double closePrice = iClose(_Symbol, _Period, i); if (closePrice < ZoneHigh) { confirmed = false; break; } } if (confirmed) { Print("Bullish Breakout Confirmed at ", TimeToString(TimeCurrent(), TIME_DATE)); PlaceTrade(ORDER_TYPE_BUY, "Confirmed Bullish Breakout Buy"); BullishBreakoutDetected = false; // Reset breakout status } } if (BearishBreakoutDetected) { // Check if price rejects higher levels and confirms bearish breakout bool confirmed = true; for (int i = 1; i <= RejectionConfirmationCandles; i++) { double closePrice = iClose(_Symbol, _Period, i); if (closePrice > ZoneLow) { confirmed = false; break; } } if (confirmed) { Print("Bearish Breakout Confirmed at ", TimeToString(TimeCurrent(), TIME_DATE)); PlaceTrade(ORDER_TYPE_SELL, "Confirmed Bearish Breakout Sell"); BearishBreakoutDetected = false; // Reset breakout status } } } //+------------------------------------------------------------------+ //| Function to place a trade | //+------------------------------------------------------------------+ void PlaceTrade(int orderType, string comment) { double price = (orderType == ORDER_TYPE_BUY) ? _Ask : _Bid; double sl = (orderType == ORDER_TYPE_BUY) ? price - StopLoss * Point() : price + StopLoss * Point(); double tp = (orderType == ORDER_TYPE_BUY) ? price + TakeProfit * Point() : price - TakeProfit * Point(); MqlTradeRequest request; MqlTradeResult result; ZeroMemory(request); ZeroMemory(result); request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = LotSize; request.type = orderType; request.price = price; request.sl = sl; request.tp = tp; request.deviation = 10; request.magic = MagicNumber; request.comment = comment; if (!OrderSend(request, result)) { Print("Error placing order: ", result.retcode); } else { Print(comment, " Order placed successfully."); } }