//+------------------------------------------------------------------+ //| SecUnit Strategy 3: Smart Money Structure (Market Range) | //| EURUSD 4H - Original Logic | //+------------------------------------------------------------------+ #property copyright "Copyright © 2025 Jawad Ait Ali Ouichou" #property version "1.00" #property description "Strategy 3 ONLY: Smart Money Structure Breakouts" #include #include //+------------------------------------------------------------------+ //| STRATEGY 3 INPUTS (Original) | //+------------------------------------------------------------------+ input group "═══════Strategy 3: Smart Money Structure════════════" input bool UseStructureStrategy = true; // Enable Structure Strategy? input int Structure_SwingSize = 5; // Market Structure Horizon (Pivot Period) input bool Structure_UseWicks = true; // Use Wicks for Confirmation? (false = Close) input double Structure_SL_Points = 200; // Structure: Stop Loss (Fixed Points) input double Structure_TP_Points = 200; // Structure: Take Profit (Fixed Points) input group "═══════Lot Size════════" input double Lots = 0.01; // Lot Size input group "Magic Number" input int MagicNumber_Structure = 303030; // Magic Number: Structure Strategy //+------------------------------------------------------------------+ //| GLOBAL VARIABLES (Original StructureData) | //+------------------------------------------------------------------+ CTrade *Trade_Structure; CPositionInfo PositionInfo; struct StructureData { double lastHigh; double lastLow; int lastHighIndex; int lastLowIndex; bool highActive; bool lowActive; int prevBreakoutDir; datetime lastTradeTime; }; StructureData Structure; //+------------------------------------------------------------------+ //| Lot Normalization (Original) | //+------------------------------------------------------------------+ double NormalizeLot(double lots) { double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); if(lotStep == 0) return 0; int ratio = (int)MathRound(lots / lotStep); lots = ratio * lotStep; int digits = 2; if(lotStep >= 0.1) digits = 1; else if(lotStep >= 0.01) digits = 2; else digits = 3; return NormalizeDouble(lots, digits); } //+------------------------------------------------------------------+ //| Check Lot Validity (Original) | //+------------------------------------------------------------------+ bool IsLotValid(double lots) { double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); if(lots < minLot) { Print("Lot < min: ", lots, " < ", minLot); return false; } if(lots > maxLot) { Print("Lot > max: ", lots, " > ", maxLot); return false; } return true; } //+------------------------------------------------------------------+ //| Complete SL/TP Validation (Original) | //+------------------------------------------------------------------+ bool CheckStopLoss_Takeprofit(ENUM_ORDER_TYPE type, double SL, double TP) { double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); long stops_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL); long spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD); double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); stops_level = MathMax(stops_level, spread); if(stops_level < 10) stops_level = 10; bool SL_check = false, TP_check = false; switch(type) { case ORDER_TYPE_BUY: SL_check = (SL == 0 || (Bid - SL > stops_level * point)); TP_check = (TP == 0 || (TP - Ask > stops_level * point)); return (SL_check && TP_check); case ORDER_TYPE_SELL: SL_check = (SL == 0 || (SL - Ask > stops_level * point)); TP_check = (TP == 0 || (Bid - TP > stops_level * point)); return (SL_check && TP_check); } return false; } //+------------------------------------------------------------------+ //| Expert initialization (Original Logic) | //+------------------------------------------------------------------+ int OnInit() { Trade_Structure = new CTrade; Trade_Structure.SetExpertMagicNumber(MagicNumber_Structure); // Initialize Structure Data (Original) Structure.lastHigh = 0; Structure.lastLow = 0; Structure.lastHighIndex = 0; Structure.lastLowIndex = 0; Structure.highActive = false; Structure.lowActive = false; Structure.prevBreakoutDir = 0; Structure.lastTradeTime = 0; Print("Structure Strategy 3 EA - Ready (Swing: ", Structure_SwingSize, ")"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { delete Trade_Structure; } //+------------------------------------------------------------------+ //| Expert tick function (Original OnTick Logic for Strategy 3 ONLY) | //+------------------------------------------------------------------+ void OnTick() { // Trading conditions check if ((!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) || (!TerminalInfoInteger(TERMINAL_CONNECTED)) || (SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE) != SYMBOL_TRADE_MODE_FULL)) return; // New Bar Detection (Original) static datetime lastBarTime = 0; datetime currentBarTime = iTime(_Symbol, _Period, 0); bool isNewBar = (currentBarTime != lastBarTime); lastBarTime = currentBarTime; if (!UseStructureStrategy || !isNewBar) return; // CORE STRATEGY 3 LOGIC - EXACTLY ORIGINAL UpdateMarketStructure(); // Find pivots int structureSignal = CheckStructureSignals(); // Check breakouts if (structureSignal == 1) // Bullish Breakout { if (HasOpenPosition()) ClosePositionsByMagic(); // Close opposite if (!HasOpenPosition()) { ProcessBullishStructureBreakout(); } } else if (structureSignal == -1) // Bearish Breakout { if (HasOpenPosition()) ClosePositionsByMagic(); // Close opposite if (!HasOpenPosition()) { ProcessBearishStructureBreakout(); } } } //+------------------------------------------------------------------+ //| STRATEGY 3 FUNCTIONS - 100% ORIGINAL | //+------------------------------------------------------------------+ void UpdateMarketStructure() { double pivotHigh = FindPivotHigh(Structure_SwingSize); if(pivotHigh > 0) { Structure.lastHigh = pivotHigh; Structure.lastHighIndex = Structure_SwingSize; Structure.highActive = true; } double pivotLow = FindPivotLow(Structure_SwingSize); if(pivotLow > 0) { Structure.lastLow = pivotLow; Structure.lastLowIndex = Structure_SwingSize; Structure.lowActive = true; } } double FindPivotHigh(int period) { if(iBars(_Symbol, _Period) < period * 2 + 1) return 0; double centerHigh = iHigh(_Symbol, _Period, period); for(int i = 1; i <= period; i++) { if(iHigh(_Symbol, _Period, period - i) >= centerHigh) return 0; if(iHigh(_Symbol, _Period, period + i) >= centerHigh) return 0; } return centerHigh; } double FindPivotLow(int period) { if(iBars(_Symbol, _Period) < period * 2 + 1) return 0; double centerLow = iLow(_Symbol, _Period, period); for(int i = 1; i <= period; i++) { if(iLow(_Symbol, _Period, period - i) <= centerLow) return 0; if(iLow(_Symbol, _Period, period + i) <= centerLow) return 0; } return centerLow; } int CheckStructureSignals() { if(!Structure.highActive && !Structure.lowActive) return 0; datetime currentBarTime = iTime(_Symbol, _Period, 0); if(currentBarTime == Structure.lastTradeTime) return 0; double currentPrice; if(Structure_UseWicks) { currentPrice = iHigh(_Symbol, _Period, 0); if(Structure.highActive && currentPrice > Structure.lastHigh) { Structure.highActive = false; Structure.prevBreakoutDir = 1; Structure.lastTradeTime = currentBarTime; return 1; } currentPrice = iLow(_Symbol, _Period, 0); if(Structure.lowActive && currentPrice < Structure.lastLow) { Structure.lowActive = false; Structure.prevBreakoutDir = -1; Structure.lastTradeTime = currentBarTime; return -1; } } else { currentPrice = iClose(_Symbol, _Period, 0); if(Structure.highActive && currentPrice > Structure.lastHigh) { Structure.highActive = false; Structure.prevBreakoutDir = 1; Structure.lastTradeTime = currentBarTime; return 1; } if(Structure.lowActive && currentPrice < Structure.lastLow) { Structure.lowActive = false; Structure.prevBreakoutDir = -1; Structure.lastTradeTime = currentBarTime; return -1; } } return 0; } void ProcessBullishStructureBreakout() { double entry = Structure.lastHigh; OpenStructureBuy(entry); } void ProcessBearishStructureBreakout() { double entry = Structure.lastLow; OpenStructureSell(entry); } //+------------------------------------------------------------------+ //| Entry Functions - Original Exact Logic | //+------------------------------------------------------------------+ void OpenStructureBuy(double entry) { double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); double sl = NormalizeDouble(ask - (Structure_SL_Points * point), digits); double tp = NormalizeDouble(ask + (Structure_TP_Points * point), digits); if(!CheckStopLoss_Takeprofit(ORDER_TYPE_BUY, sl, tp)) return; double volume = NormalizeLot(Lots); if(!IsLotValid(volume)) return; Trade_Structure.PositionOpen(_Symbol, ORDER_TYPE_BUY, volume, ask, sl, tp); Print("Structure BUY: Entry=", ask, " SL=", sl, " TP=", tp); } void OpenStructureSell(double entry) { double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); double sl = NormalizeDouble(bid + (Structure_SL_Points * point), digits); double tp = NormalizeDouble(bid - (Structure_TP_Points * point), digits); if(!CheckStopLoss_Takeprofit(ORDER_TYPE_SELL, sl, tp)) return; double volume = NormalizeLot(Lots); if(!IsLotValid(volume)) return; Trade_Structure.PositionOpen(_Symbol, ORDER_TYPE_SELL, volume, bid, sl, tp); Print("Structure SELL: Entry=", bid, " SL=", sl, " TP=", tp); } //+------------------------------------------------------------------+ //| Utility Functions - Original | //+------------------------------------------------------------------+ bool HasOpenPosition() { for (int i = PositionsTotal() - 1; i >= 0; i--) { if (PositionInfo.SelectByIndex(i) && PositionInfo.Symbol() == _Symbol && PositionInfo.Magic() == MagicNumber_Structure) return true; } return false; } void ClosePositionsByMagic() { CTrade closeTrade; for (int i = PositionsTotal() - 1; i >= 0; i--) { if (PositionInfo.SelectByIndex(i) && PositionInfo.Symbol() == _Symbol && PositionInfo.Magic() == MagicNumber_Structure) { closeTrade.PositionClose(PositionInfo.Ticket()); } } }