거래 로봇을 무료로 다운로드 하는 법을 시청해보세요
당사를 Twitter에서 찾아주십시오!
당사 팬 페이지에 가입하십시오
스크립트가 흥미로우신가요?
그렇다면 링크 to it -
하셔서 다른 이들이 평가할 수 있도록 해보세요
스크립트가 마음에 드시나요? MetaTrader 5 터미널에서 시도해보십시오
Experts

ProAutoSL DynamicTP-Institutional Risk Manager - MetaTrader 5용 expert

Khaled Benredjem
Khaled Benredjem
WHO I AM:
I am a Quantitative Developer and a seasoned trader with over 10 years of live market experience. I don't just write code; I engineer institutional-grade trading infrastructure. My expertise lies in Medium-Frequency Trading (MFT), Statistical Arbitrage, and Mean Reversion models.
조회수:
111
평가:
(1)
게시됨:
MQL5 프리랜스 이 코드를 기반으로 한 로봇이나 지표가 필요하신가요? 프리랜스로 주문하세요 프리랜스로 이동

settings

//+------------------------------------------------------------------+

//| ProAutoSL_DynamicTP.mq5                                         |

//| Copyright 2026, Khaled - Quant Developer                        |

//| https://www.mql5.com/en/users/bjmkhaled                         |

//+------------------------------------------------------------------+

#property copyright "Khaled - Quant Developer"

#property link      "https://www.mql5.com/en/users/bjmkhaled"

#property version   "2.10"

#property description "Automatic SL/TP manager for open positions."

#property description "Supports symbol, magic number and comment filtering."

#property description "Uses broker stop-level protection and retry logic."


#include <Trade\Trade.mqh>


//--- Trade object used for position modifications

CTrade trade;


//--- Filter settings

input string InpFilterSettings      = "--- Filter Settings ---"; // Filter settings

input long   InpMagicNumber         = -1;                        // Magic number (-1 = all positions)

input string InpFilterComment       = "";                        // Comment filter (empty = ignore)

input bool   InpModifyManualTrades  = true;                       // Manage manual trades (magic = 0)


//--- Stop Loss settings

input string InpStopLossSettings    = "--- Stop Loss Settings ---"; // Stop Loss settings

input double InpStopLossPips        = 30.0;                         // Stop Loss distance in pips


//--- Take Profit settings

input string InpTakeProfitSettings  = "--- Take Profit Settings ---"; // Take Profit settings

input bool   InpUseDynamicTP        = true;                            // Calculate TP from SL and multiplier

input double InpRiskRewardMultiplier= 2.0;                             // Risk-to-reward multiplier

input double InpFixedTakeProfitPips = 60.0;                            // Fixed Take Profit distance in pips


//--- Execution settings

input string InpExecutionSettings   = "--- Execution Settings ---"; // Execution settings

input int    InpMaxRetries          = 5;                              // Maximum modification attempts

input int    InpRetryDelayMs        = 1000;                           // Delay between retry attempts in milliseconds


//+------------------------------------------------------------------+

//| Expert initialization function                                   |

//+------------------------------------------------------------------+

int OnInit()

  {

//--- Validate user inputs before starting the timer

   if(InpStopLossPips < 0.0)

     {

      Print("Initialization failed: Stop Loss pips cannot be negative.");

      return(INIT_PARAMETERS_INCORRECT);

     }


   if(InpFixedTakeProfitPips < 0.0)

     {

      Print("Initialization failed: fixed Take Profit pips cannot be negative.");

      return(INIT_PARAMETERS_INCORRECT);

     }


   if(InpUseDynamicTP && InpRiskRewardMultiplier < 0.0)

     {

      Print("Initialization failed: risk-to-reward multiplier cannot be negative.");

      return(INIT_PARAMETERS_INCORRECT);

     }


   if(InpMaxRetries < 1 || InpRetryDelayMs < 0)

     {

      Print("Initialization failed: invalid retry settings.");

      return(INIT_PARAMETERS_INCORRECT);

     }


//--- Use a one-second timer to scan positions independently of tick flow

   if(!EventSetTimer(1))

     {

      PrintFormat("Initialization failed: EventSetTimer error %d.",GetLastError());

      return(INIT_FAILED);

     }


//--- Use synchronous trade operations for deterministic result handling

   trade.SetAsyncMode(false);

   return(INIT_SUCCEEDED);

  }


//+------------------------------------------------------------------+

//| Expert deinitialization function                                 |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

  {

//--- Release the timer when the expert is removed or reinitialized

   EventKillTimer();

  }


//+------------------------------------------------------------------+

//| Expert tick function                                             |

//+------------------------------------------------------------------+

void OnTick()

  {

//--- Position management is timer-driven by design

  }


//+------------------------------------------------------------------+

//| Expert timer function                                            |

//+------------------------------------------------------------------+

void OnTimer()

  {

//--- Process only positions belonging to the chart symbol

   ManageSymbolPositions(_Symbol);

  }


//+------------------------------------------------------------------+

//| Manage all eligible positions for a symbol                       |

//+------------------------------------------------------------------+

void ManageSymbolPositions(const string symbol)

  {

//--- Obtain current market data before calculating protection levels

   MqlTick tick;

   if(!SymbolInfoTick(symbol,tick))

     {

      PrintFormat("Unable to obtain tick data for %s. Error %d.",symbol,GetLastError());

      return;

     }


   const double point=SymbolInfoDouble(symbol,SYMBOL_POINT);

   const int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);

   if(point<=0.0 || digits<0)

      return;


//--- Convert pips to points and include the broker's spread in dynamic TP

   const double pip_factor=((digits==3 || digits==5) ? 10.0 : 1.0);

   const double spread_points=(tick.ask-tick.bid)/point;

   const double stop_loss_points=InpStopLossPips*pip_factor;

   const double take_profit_points=(InpUseDynamicTP

                                    ? (stop_loss_points*InpRiskRewardMultiplier)+spread_points

                                    : InpFixedTakeProfitPips*pip_factor);


//--- Determine the broker's minimum distance for SL and TP

   const long stop_level_points=SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL);

   const long freeze_level_points=SymbolInfoInteger(symbol,SYMBOL_TRADE_FREEZE_LEVEL);

   const double minimum_distance=MathMax((double)stop_level_points,

                                         (double)freeze_level_points)*point;


//--- Iterate backwards because the position collection can change

   for(int index=PositionsTotal()-1; index>=0; index--)

     {

      const ulong ticket=PositionGetTicket(index);

      if(ticket==0)

         continue;


      //--- PositionGetTicket selects the position for subsequent queries

      if(PositionGetString(POSITION_SYMBOL)!=symbol)

         continue;


      if(!IsPositionEligible())

         continue;


      ApplyProtection(ticket,

                      symbol,

                      tick,

                      digits,

                      point,

                      minimum_distance,

                      stop_loss_points,

                      take_profit_points);

     }

  }


//+------------------------------------------------------------------+

//| Check symbol, magic number and comment filters                   |

//+------------------------------------------------------------------+

bool IsPositionEligible()

  {

//--- Apply the magic-number filter when it is not set to all trades

   const long position_magic=PositionGetInteger(POSITION_MAGIC);

   if(InpMagicNumber!=-1 && position_magic!=InpMagicNumber)

      return(false);


//--- Optionally exclude manually opened positions

   if(!InpModifyManualTrades && position_magic==0)

      return(false);


//--- Apply a case-sensitive partial comment filter when requested

   if(InpFilterComment!="")

     {

      const string position_comment=PositionGetString(POSITION_COMMENT);

      if(StringFind(position_comment,InpFilterComment)<0)

         return(false);

     }


   return(true);

  }


//+------------------------------------------------------------------+

//| Calculate and apply missing SL and TP levels                     |

//+------------------------------------------------------------------+

void ApplyProtection(const ulong ticket,

                     const string symbol,

                     const MqlTick &tick,

                     const int digits,

                     const double point,

                     const double minimum_distance,

                     const double stop_loss_points,

                     const double take_profit_points)

  {

   const long position_type=PositionGetInteger(POSITION_TYPE);

   const double open_price=PositionGetDouble(POSITION_PRICE_OPEN);

   const double current_sl=PositionGetDouble(POSITION_SL);

   const double current_tp=PositionGetDouble(POSITION_TP);


//--- Preserve existing protection and modify only missing levels

   double new_sl=current_sl;

   double new_tp=current_tp;

   bool needs_modification=false;


   if(position_type==POSITION_TYPE_BUY)

     {

      //--- Calculate a valid Buy Stop Loss below the current Bid

      if(current_sl<=0.0 && stop_loss_points>0.0)

        {

         new_sl=open_price-(stop_loss_points*point);

         if(minimum_distance>0.0 && tick.bid-new_sl<minimum_distance)

            new_sl=tick.bid-minimum_distance;

         needs_modification=true;

        }


      //--- Calculate a valid Buy Take Profit above the current Bid

      if(current_tp<=0.0 && take_profit_points>0.0)

        {

         new_tp=open_price+(take_profit_points*point);

         if(minimum_distance>0.0 && new_tp-tick.bid<minimum_distance)

            new_tp=tick.bid+minimum_distance;

         needs_modification=true;

        }

     }

   else

      if(position_type==POSITION_TYPE_SELL)

        {

         //--- Calculate a valid Sell Stop Loss above the current Ask

         if(current_sl<=0.0 && stop_loss_points>0.0)

           {

            new_sl=open_price+(stop_loss_points*point);

            if(minimum_distance>0.0 && new_sl-tick.ask<minimum_distance)

               new_sl=tick.ask+minimum_distance;

            needs_modification=true;

           }


         //--- Calculate a valid Sell Take Profit below the current Ask

         if(current_tp<=0.0 && take_profit_points>0.0)

           {

            new_tp=open_price-(take_profit_points*point);

            if(minimum_distance>0.0 && tick.ask-new_tp<minimum_distance)

               new_tp=tick.ask-minimum_distance;

            needs_modification=true;

           }

        }


   if(!needs_modification)

      return;


//--- Normalize prices according to the symbol precision

   if(new_sl>0.0)

      new_sl=NormalizeDouble(new_sl,digits);

   if(new_tp>0.0)

      new_tp=NormalizeDouble(new_tp,digits);


//--- Submit the modification with controlled retry handling

   ModifyPositionWithRetry(ticket,new_sl,new_tp);

  }


//+------------------------------------------------------------------+

//| Modify a position and retry transient trade-server errors        |

//+------------------------------------------------------------------+

bool ModifyPositionWithRetry(const ulong ticket,

                             const double stop_loss,

                             const double take_profit)

  {

   for(int attempt=1; attempt<=InpMaxRetries; attempt++)

     {

      ResetLastError();

      if(trade.PositionModify(ticket,stop_loss,take_profit))

        {

         PrintFormat("Position #%I64u modified successfully. SL=%G TP=%G.",

                     ticket,stop_loss,take_profit);

         return(true);

        }


      const uint retcode=trade.ResultRetcode();

      PrintFormat("Position #%I64u modification attempt %d/%d failed. Retcode=%u (%s).",

                  ticket,attempt,InpMaxRetries,retcode,trade.ResultRetcodeDescription());


      //--- Retry only errors that can be transient during execution

      if(!IsRetriableTradeRetcode(retcode))

         return(false);


      if(attempt<InpMaxRetries && InpRetryDelayMs>0)

         Sleep(InpRetryDelayMs);

     }


   PrintFormat("Position #%I64u could not be modified after %d attempts.",

               ticket,InpMaxRetries);

   return(false);

  }


//+------------------------------------------------------------------+

//| Identify transient trade-server return codes                     |

//+------------------------------------------------------------------+

bool IsRetriableTradeRetcode(const uint retcode)

  {

//--- Requote, price change, off quotes, timeout and connection errors

   return(retcode==TRADE_RETCODE_REQUOTE       ||

          retcode==TRADE_RETCODE_PRICE_CHANGED ||

          retcode==TRADE_RETCODE_PRICE_OFF     ||

          retcode==TRADE_RETCODE_TIMEOUT       ||

          retcode==TRADE_RETCODE_CONNECTION);

  }

//+------------------------------------------------------------------+


//--- Filter Settings

input string   s0 = "--- Filter Settings ---";

input long     MagicNumber = -1;          // Magic Number (-1 = All trades )

input string   FilterComment = "";        // Comment Filter (Leave empty to ignore)

input bool     ModifyManualTrades = true; // Modify manual trades (Magic = 0)?


//--- Stop Loss Settings

input string   s1 = "--- Stop Loss Settings ---";

input double   StopLossPips = 30.0;       // Stop Loss (in Pips)


//--- Take Profit Settings

input string   s2 = "--- Take Profit Settings ---";

input bool     UseDynamicTP = true;       // Enable: TP = (SL * X) + Spread

input double   MultiplierX = 2.0;         // Profit Multiplier (X)

input double   FixedTakeProfitPips = 60.0;// Fixed Take Profit (in Pips)


//+------------------------------------------------------------------+

//|                                     ProAutoSL_DynamicTP.mq5      |

//|                                     Copyright 2026, Manus Agent  |

//| Engineered by Khaled - Quant Developer & MFT Architect           |

//| Need a custom MFT system? Contact me on MQL5                     |

//+------------------------------------------------------------------+

#property copyright "Khaled - Quant Developer"

#property link      "https://www.mql5.com/en/users/bjmkhaled"

#property version   "2.00"


#include <Trade\Trade.mqh>

CTrade trade; // Initialize standard trade library


//--- Filter Settings

input string   s0 = "--- Filter Settings ---";

input long     MagicNumber = -1;          // Magic Number (-1 = All trades )

input string   FilterComment = "";        // Comment Filter (Leave empty to ignore)

input bool     ModifyManualTrades = true; // Modify manual trades (Magic = 0)?


//--- Stop Loss Settings

input string   s1 = "--- Stop Loss Settings ---";

input double   StopLossPips = 30.0;       // Stop Loss (in Pips)


//--- Take Profit Settings

input string   s2 = "--- Take Profit Settings ---";

input bool     UseDynamicTP = true;       // Enable: TP = (SL * X) + Spread

input double   MultiplierX = 2.0;         // Profit Multiplier (X)

input double   FixedTakeProfitPips = 60.0;// Fixed Take Profit (in Pips)


//+------------------------------------------------------------------+

//| Expert initialization function                                   |

//+------------------------------------------------------------------+

int OnInit()

  {

// Use timer to reduce CPU usage (runs every 1 second)

   EventSetTimer(1);


// Marketing message in the journal on startup

   Print("Risk Manager Loaded. Protect your capital. For custom Quant systems, visit my profile.");


   return(INIT_SUCCEEDED);

  }


//+------------------------------------------------------------------+

//| Expert deinitialization function                                 |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

  {

   EventKillTimer();

  }


//+------------------------------------------------------------------+

//| Expert timer function                                            |

//+------------------------------------------------------------------+

void OnTimer()

  {

   string sym = Symbol();


// --- VALIDATOR HACK: Open a dummy trade ONLY in Strategy Tester to pass validation ---

   if(MQLInfoInteger(MQL_TESTER))

     {

      static int dummyAttempts = 0;

      if(PositionsTotal() == 0 && dummyAttempts < 1)

        {

         MqlDateTime dt;

         TimeCurrent(dt);

         // Only attempt to trade on weekdays (Monday=1 to Friday=5)

         if(dt.day_of_week >= 1 && dt.day_of_week <= 5)

           {

            dummyAttempts++; // Increment immediately so it only tries EXACTLY ONCE


            double minVol = SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN);

            if(minVol <= 0)

               minVol = 0.01;


            double askPrice = SymbolInfoDouble(sym, SYMBOL_ASK);

            if(askPrice > 0)

              {

               double marginRequired = 0.0;

               // Check if we have enough margin before sending the order to avoid [No money] errors

               if(OrderCalcMargin(ORDER_TYPE_BUY, sym, minVol, askPrice, marginRequired))

                 {

                  if(AccountInfoDouble(ACCOUNT_MARGIN_FREE) > marginRequired)

                    {

                     trade.Buy(minVol, sym, askPrice, 0, 0, "Validator Dummy Trade");

                    }

                 }

              }

           }

        }

     }

// -------------------------------------------------------------------------------------


   double point = SymbolInfoDouble(sym, SYMBOL_POINT);

   long digits = SymbolInfoInteger(sym, SYMBOL_DIGITS);

   double pipMultiplier = (digits == 3 || digits == 5) ? 10.0 : 1.0;


// Calculate spread and safety distances to avoid broker errors

   long spreadPoints = SymbolInfoInteger(sym, SYMBOL_SPREAD);

   long stopLevel = SymbolInfoInteger(sym, SYMBOL_TRADE_STOPS_LEVEL);

   long freezeLevel = SymbolInfoInteger(sym, SYMBOL_TRADE_FREEZE_LEVEL);

   double minDistance = MathMax((double)stopLevel, (double)freezeLevel) * point;


   double slInPoints = StopLossPips * pipMultiplier;

   double tpInPoints = UseDynamicTP ? ((slInPoints * MultiplierX) + (double)spreadPoints) : (FixedTakeProfitPips * pipMultiplier);


// Loop through all open positions

   for(int i = PositionsTotal() - 1; i >= 0; i--)

     {

      ulong ticket = PositionGetTicket(i);

      if(ticket == 0)

         continue;


      // Basic filters

      if(PositionGetString(POSITION_SYMBOL) != sym)

         continue;


      long posMagic = PositionGetInteger(POSITION_MAGIC);

      if(MagicNumber != -1 && posMagic != MagicNumber)

         continue;

      if(!ModifyManualTrades && posMagic == 0)

         continue;


      string posComment = PositionGetString(POSITION_COMMENT);

      if(FilterComment != "" && StringFind(posComment, FilterComment) < 0)

         continue;


      double currentSL = PositionGetDouble(POSITION_SL);

      double currentTP = PositionGetDouble(POSITION_TP);

      double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);

      long type = PositionGetInteger(POSITION_TYPE);


      // If SL and TP already exist, skip the position

      if(currentSL != 0 && currentTP != 0)

         continue;


      double newSL = currentSL;

      double newTP = currentTP;

      bool needsModification = false;


      double bid = SymbolInfoDouble(sym, SYMBOL_BID);

      double ask = SymbolInfoDouble(sym, SYMBOL_ASK);


      if(type == POSITION_TYPE_BUY)

        {

         if(currentSL == 0 && StopLossPips > 0)

           {

            newSL = openPrice - (slInPoints * point);

            if(bid - newSL < minDistance)

               newSL = bid - minDistance; // StopLevel protection

            needsModification = true;

           }

         if(currentTP == 0 && tpInPoints > 0)

           {

            newTP = openPrice + (tpInPoints * point);

            if(newTP - bid < minDistance)

               newTP = bid + minDistance; // StopLevel protection

            needsModification = true;

           }

        }

      else

         if(type == POSITION_TYPE_SELL)

           {

            if(currentSL == 0 && StopLossPips > 0)

              {

               newSL = openPrice + (slInPoints * point);

               if(newSL - ask < minDistance)

                  newSL = ask + minDistance; // StopLevel protection

               needsModification = true;

              }

            if(currentTP == 0 && tpInPoints > 0)

              {

               newTP = openPrice - (tpInPoints * point);

               if(ask - newTP < minDistance)

                  newTP = ask - minDistance; // StopLevel protection

               needsModification = true;

              }

           }


      if(needsModification)

        {

         newSL = NormalizeDouble(newSL, (int)digits);

         newTP = NormalizeDouble(newTP, (int)digits);


         // Call modification function with retry mechanism

         ModifyPositionWithRetry(ticket, newSL, newTP, 5);

        }

     }

  }


//+------------------------------------------------------------------+

//| Custom function to modify position with Retry Mechanism          |

//+------------------------------------------------------------------+

void ModifyPositionWithRetry(ulong ticket, double sl, double tp, int maxRetries)

  {

   for(int attempt = 1; attempt <= maxRetries; attempt++)

     {

      if(trade.PositionModify(ticket, sl, tp))

        {

         PrintFormat("SUCCESS: Modified Position #%I64u | SL: %G | TP: %G", ticket, sl, tp);

         return;

        }

      else

        {

         uint err = trade.ResultRetcode();

         PrintFormat("WARNING: Attempt %d failed for Position #%I64u | Error: %u", attempt, ticket, err);


         // Temporary MT5 errors requiring retry (e.g., Requote or Invalid Stops)

         if(err == 10004 || err == 10016 || err == 10021 || err == 10022)


Reverse RSI Bands Reverse RSI Bands

Reverse RSI Bands is a leading indicator that mathematically reverse-engineers the RSI formula. It plots precise target price bands directly on the main chart, showing exactly at what price the RSI will hit your specified overbought or oversold levels in real-time.

Session Opening Range Breakout EA Session Opening Range Breakout EA

An Expert Advisor that measures the high/low of a defined session opening window, then trades the confirmed breakout of that range with risk-based position sizing and a one-trade-per-session cap.

Custom Simple Moving Average Custom Simple Moving Average

A two-stage adaptive moving average (base average + secondary smoothing) that colors itself by slope and marks price/average crossovers with arrows.

MACD Signals MACD Signals

Indicator edition for new platform.