diff --git a/Experts/SimpleFVG.mq5 b/Experts/SimpleFVG.mq5 index ca4ef07..87019c8 100644 --- a/Experts/SimpleFVG.mq5 +++ b/Experts/SimpleFVG.mq5 @@ -42,9 +42,117 @@ int OnInit() InpEMAFastPeriod, InpEMASlowPeriod, InpFVGLookbackBars, InpFVGMaxAgeBars); + //--- Initialize last processed exit time so we don't reset based on old history. + g_LastExitDealTime = GetLatestTP_SL_ExitDealTime(); + return INIT_SUCCEEDED; } +//--- Track last processed TP/SL exit so we can reset strategy state +//--- only when a new SL/TP happens (not from older history). +datetime g_LastExitDealTime = 0; + +datetime GetLatestTP_SL_ExitDealTime() +{ + datetime now = TimeCurrent(); + if(now == 0) + return 0; + if(!HistorySelect(0, now)) + return 0; + + datetime latest = 0; + string symbol = GetTradeSymbol(); + + int deals = HistoryDealsTotal(); + for(int i = 0; i < deals; i++) + { + ulong dealTicket = HistoryDealGetTicket(i); + if(dealTicket == 0) + continue; + + string dealSymbol = (string)HistoryDealGetString(dealTicket, DEAL_SYMBOL); + long dealMagic = (long)HistoryDealGetInteger(dealTicket, DEAL_MAGIC); + if(dealSymbol != symbol || dealMagic != InpEAMagic) + continue; + + ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(dealTicket, DEAL_ENTRY); + if(entry != DEAL_ENTRY_OUT && entry != DEAL_ENTRY_INOUT) + continue; + + ENUM_DEAL_REASON reason = (ENUM_DEAL_REASON)HistoryDealGetInteger(dealTicket, DEAL_REASON); + if(reason != DEAL_REASON_TP && reason != DEAL_REASON_SL) + continue; + + datetime dealTime = (datetime)HistoryDealGetInteger(dealTicket, DEAL_TIME); + if(dealTime > latest) + latest = dealTime; + } + return latest; +} + +//--- If a new TP/SL exit is detected since the last processed time, +//--- reset all FVG statuses by re-initializing the array and rescanning. +bool CheckAndResetOnNewTP_SL_Exit() +{ + datetime now = TimeCurrent(); + if(now == 0) + return false; + if(!HistorySelect(0, now)) + return false; + + datetime latestExit = g_LastExitDealTime; + string symbol = GetTradeSymbol(); + + int deals = HistoryDealsTotal(); + for(int i = 0; i < deals; i++) + { + ulong dealTicket = HistoryDealGetTicket(i); + if(dealTicket == 0) + continue; + + string dealSymbol = (string)HistoryDealGetString(dealTicket, DEAL_SYMBOL); + long dealMagic = (long)HistoryDealGetInteger(dealTicket, DEAL_MAGIC); + if(dealSymbol != symbol || dealMagic != InpEAMagic) + continue; + + ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(dealTicket, DEAL_ENTRY); + if(entry != DEAL_ENTRY_OUT && entry != DEAL_ENTRY_INOUT) + continue; + + ENUM_DEAL_REASON reason = (ENUM_DEAL_REASON)HistoryDealGetInteger(dealTicket, DEAL_REASON); + if(reason != DEAL_REASON_TP && reason != DEAL_REASON_SL) + continue; + + datetime dealTime = (datetime)HistoryDealGetInteger(dealTicket, DEAL_TIME); + if(dealTime > g_LastExitDealTime && dealTime > latestExit) + latestExit = dealTime; + } + + if(latestExit <= g_LastExitDealTime) + return false; + + //--- Only reset strategy state when our position is fully closed. + //--- This avoids resetting on partial TP/SL deals while position still exists. + if(CountOurPositions() > 0) + return false; + + g_LastExitDealTime = latestExit; + + //--- Cancel any pending limit orders left from before the exit. + CancelAllOurLimitOrders(); + + //--- Reset FVG states completely and rescan from scratch. + FVGInit(); + TrendUpdate(); + FVGUpdate(); + + if(InpDebugLog) + PrintFormat("[RESET] New SL/TP exit at %s → reset FVG array", + TimeToString(g_LastExitDealTime)); + + return true; +} + //+------------------------------------------------------------------+ //| OnDeinit | //+------------------------------------------------------------------+ @@ -62,6 +170,14 @@ void OnTick() if(!IsNewBar()) return; + //--- IMPORTANT: reset internal FVG status after TP/SL so we don't reuse + //--- old TOUCHED/MITIGATED states. + if(CheckAndResetOnNewTP_SL_Exit()) + { + DrawAll(); + return; // avoid entering a new trade on the same bar immediately + } + TrendUpdate(); FVGUpdate(); ManageFVGTrades();