diff --git a/MQL5/Experts/MultiAgentTest/MultiAgentTest.mq5 b/MQL5/Experts/MultiAgentTest/MultiAgentTest.mq5 index 3212f6c..e86692e 100644 --- a/MQL5/Experts/MultiAgentTest/MultiAgentTest.mq5 +++ b/MQL5/Experts/MultiAgentTest/MultiAgentTest.mq5 @@ -355,14 +355,37 @@ void ManagePositions(const MarketData &data, const FinalSignal &fs) { } int ticket = 0; - if(fs.direction == 1) - ticket = trade.Buy(lot, sym, ask, sl, 0); // TP=0: trailing stop - else - ticket = trade.Sell(lot, sym, bid, sl, 0); + // Calcolo TakeProfit opzionale (usiamo lo stesso fattoreATR per TP) + double tp = 0; + // TakeProfit: se impostato usa Inp_TPRiskATR, altrimenti usa lo stesso fattore di SL (dynamic) + double tpWidth = (Inp_TPRiskATR > 0) ? Inp_TPRiskATR : ((Inp_SLRiskATR > 0) ? Inp_SLRiskATR : orchestrator.AdaptiveSLWidth()); + if(tpWidth > 0) { + tp = (fs.direction == 1) ? price + atr * tpWidth : price - atr * tpWidth; + tp = NormalizeDouble(tp, dig); + } + if(fs.direction == 1) { + // BUY – validate SL and TP + if(sl <= 0 || sl >= ask) { + Print("Invalid BUY SL (", sl, ") – order skipped"); + } else if(tp > 0 && tp <= sl) { + Print("Invalid BUY TP (", tp, ") – must be > SL – order skipped"); + } else { + ticket = trade.Buy(lot, sym, ask, sl, tp); // TP may be 0 (no TP) + } + } else { + // SELL – validate SL and TP + if(sl <= 0 || sl <= bid) { + Print("Invalid SELL SL (", sl, ") – order skipped"); + } else if(tp > 0 && tp >= sl) { + Print("Invalid SELL TP (", tp, ") – must be < SL – order skipped"); + } else { + ticket = trade.Sell(lot, sym, bid, sl, tp); + } + } - if(ticket > 0) { - orchestrator.OnTradeOpen(ticket, price, atr); - } + if(ticket > 0) { + orchestrator.OnTradeOpen(ticket, price, atr); + } } } @@ -396,33 +419,31 @@ void LogSignal(const MarketData &data, const FinalSignal &fs) { void OnTrade() { static int onTradeCloses = 0; static int saveInterval = 0; - if(saveInterval == 0) saveInterval = MathMax(orchestrator.TotalAgents(), orchestrator.TotalAgents() * 5); - + if(saveInterval == 0) { + // Minimum 5 trades, scaled with number of agents + saveInterval = MathMax(5, orchestrator.TotalAgents() * 5); + } if(!orchestrator.HasOpenTrade()) return; - int maxSlots = orchestrator.MaxTradeSlots(); for(int t = 0; t < maxSlots; t++) { - int tkt = orchestrator.GetTrackedTicket(t); - if(tkt < 0) break; // nessun altro trade attivo - - bool found = false; - for(int p = PositionsTotal()-1; p >= 0; p--) { - if(posInfo.SelectByIndex(p)) { - if((int)posInfo.Ticket() == tkt) { found = true; break; } - } - } - + int tkt = orchestrator.GetTrackedTicket(t); + if(tkt < 0) break; // no more active trades + bool found = false; + for(int p = PositionsTotal() - 1; p >= 0; p--) { + if(posInfo.SelectByIndex(p)) { + if((int)posInfo.Ticket() == tkt) { found = true; break; } + } + } if(!found) { - // Trade chiuso da SL/TP (non da noi in ManagePositions) - bool isBuy = orchestrator.IsBuyTrade(tkt); - double closePrice = isBuy ? SymbolInfoDouble(sym, SYMBOL_BID) : SymbolInfoDouble(sym, SYMBOL_ASK); - orchestrator.OnTradeClose(tkt, closePrice); - onTradeCloses++; - Print("SL/TP chiuso trade #", tkt, " (totale SL/TP: ", onTradeCloses, ")"); - - if(onTradeCloses % saveInterval == 0) - orchestrator.SaveState(sym, Inp_TF); - } + // Trade closed by SL/TP (not by ManagePositions) + bool isBuy = orchestrator.IsBuyTrade(tkt); + double closePrice = isBuy ? SymbolInfoDouble(sym, SYMBOL_BID) : SymbolInfoDouble(sym, SYMBOL_ASK); + orchestrator.OnTradeClose(tkt, closePrice); + onTradeCloses++; + Print("SL/TP chiuso trade #", tkt, " (totale SL/TP: ", onTradeCloses, ")"); + if(onTradeCloses % saveInterval == 0) + orchestrator.SaveState(sym, Inp_TF); + } } }