Ronz SLTP MT5

Author: Copyright 2022
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
Ronz SLTP MT5
//+------------------------------------------------------------------+
//|                                             RoNz Auto SL n TP.mq4|
//|                              Copyright 2014-2018, Rony Nofrianto |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022"
#property description   "Based from Ronz AutoSL-TP"
#property version   "1.3"
#property strict

#include <Trade\Trade.mqh> CTrade trade;
enum ENUM_CHARTSYMBOL
  {
   CurrentChartSymbol=0,//Current Chart Only
   AllOpenOrder=1//All Opened Orders
  };
enum ENUM_SLTP_MODE
  {
   Server=0,//Place SL n TP
   Client=1 //Hidden SL n TP
  };
enum ENUM_LOCKPROFIT_ENABLE
  {
   LP_DISABLE=0,//Disable
   LP_ENABLE=1//Enable
  };
enum ENUM_TRAILINGSTOP_METHOD
  {
   TS_NONE=0,//No Trailing Stop
   TS_CLASSIC=1,//Classic
   TS_STEP_DISTANCE=2,//Step Keep Distance
   TS_STEP_BY_STEP=3 //Step By Step
  };
sinput const string SLTP="";//-=[ SL & TP SETTINGS ]=-
input int   TakeProfit=550;//Take Profit
input int   StopLoss=350;//Stop Loss
input ENUM_SLTP_MODE SLnTPMode=Server;//SL & TP Mode
sinput const string Lock="";//-=[ LOCK PROFIT SETTINGS ]=-
input ENUM_LOCKPROFIT_ENABLE LockProfitEnable=LP_ENABLE;//Enable/Disable Profit Lock
input int   LockProfitAfter=100;//Target point to Lock Profit
input int   ProfitLock=60;//Profit To Lock
sinput const string Trailing="";//-=[ TRAILING STOP SETTINGS ]=-
input ENUM_TRAILINGSTOP_METHOD TrailingStopMethod=TS_CLASSIC;//Trailing Method
input int   TrailingStop=50;//Trailing Stop
input int   TrailingStep=10;//Trailing Stop Step
input int Slippage   = 10; //Slippage
input ENUM_CHARTSYMBOL  ChartSymbolSelection=AllOpenOrder;//
input bool   inpEnableAlert=false;//Enable Alert
input bool   inpEnableTest=false;//Enable Test on Strategy Tester

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class AutoSLTP
  {
private:
   //--
   bool              CheckMoneyForTrade(string sym, double lots,ENUM_ORDER_TYPE type);
   bool              CheckVolumeValue(string sym, double volume);
   bool              RZ_TrailingStop(ulong ticket, int JumlahPoin,int Step=1,ENUM_TRAILINGSTOP_METHOD Method=TS_STEP_DISTANCE);
   bool              LockProfit(ulong ticket, int Targetpoint,int Lockedpoint);
   //--

public:
   //--
   ENUM_SLTP_MODE    autoMode;
   ENUM_LOCKPROFIT_ENABLE LPMode;
   ENUM_CHARTSYMBOL  chartMode;
   ENUM_TRAILINGSTOP_METHOD trailingMode;
   int               slip;
   int               TPa;
   int               SLa;
   int               LPA;
   int               PL;
   int               TS;
   int               TST;
   bool              SetInstantSLTP();
   int               CalculateInstantOrders();
   void              OrderTest();
   //--
  };

AutoSLTP auto;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool AutoSLTP::SetInstantSLTP()
  {
   double SL=0, TP=0;
   double ask = 0, bid = 0, point = 0;
   int digits = 0, minstoplevel = 0;
   for(int i=PositionsTotal()-1; i>=0; i--)
     {
      if(PositionGetTicket(i))
         if(chartMode==CurrentChartSymbol && PositionGetString(POSITION_SYMBOL)!=Symbol())
            continue;
        {
         ask = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_ASK);
         bid = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_BID);
         point = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_POINT);
         digits =(int)SymbolInfoInteger(PositionGetString(POSITION_SYMBOL),SYMBOL_DIGITS);
         minstoplevel =(int)SymbolInfoInteger(PositionGetString(POSITION_SYMBOL),SYMBOL_TRADE_STOPS_LEVEL);

         double ClosePrice=0;
         int Poin=0;
         color CloseColor=clrNONE;

         //Get point
         if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            CloseColor=clrBlue;
            ClosePrice=bid;
            Poin=(int)((ClosePrice-PositionGetDouble(POSITION_PRICE_OPEN))/point);
           }
         else
            if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
              {
               CloseColor=clrRed;
               ClosePrice=ask;
               Poin=(int)((PositionGetDouble(POSITION_PRICE_OPEN)-ClosePrice)/point);
              }

         //Print("Check SL & TP : ",OrderSymbol()," SL = ",OrderStopLoss()," TP = ",OrderTakeProfit());
         //Set Server SL and TP
         if(autoMode == Server)
           {
            if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
              {
               SL=(SLa>0)?NormalizeDouble(PositionGetDouble(POSITION_PRICE_OPEN)-((SLa+minstoplevel)*point),digits):0;
               TP=(TPa>0)?NormalizeDouble(PositionGetDouble(POSITION_PRICE_OPEN)+((TPa+minstoplevel)*point),digits):0;
               if(SLa > 0 && TPa > 0 && PositionGetDouble(POSITION_SL)==0.0 && PositionGetDouble(POSITION_TP)==0.0)
                 {
                  trade.PositionModify(PositionGetInteger(POSITION_TICKET),SL,TP);
                 }
               else
                  if(TPa > 0 && PositionGetDouble(POSITION_TP)==0.0)
                    {
                     trade.PositionModify(PositionGetInteger(POSITION_TICKET),PositionGetDouble(POSITION_SL),TP);
                    }
                  else
                     if(SLa > 0 && PositionGetDouble(POSITION_SL)==0.0)
                       {
                        trade.PositionModify(PositionGetInteger(POSITION_TICKET),SL,PositionGetDouble(POSITION_TP));
                       }
              }
            else
               if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
                 {
                  SL=(SLa>0)?NormalizeDouble(PositionGetDouble(POSITION_PRICE_OPEN)+((SLa+minstoplevel)*point),digits):0;
                  TP=(TPa>0)?NormalizeDouble(PositionGetDouble(POSITION_PRICE_OPEN)-((TPa+minstoplevel)*point),digits):0;
                  if(SLa > 0 && TPa > 0 && PositionGetDouble(POSITION_SL)==0.0 && PositionGetDouble(POSITION_TP)==0.0)
                    {
                     trade.PositionModify(PositionGetInteger(POSITION_TICKET),SL,TP);
                    }
                  else
                     if(TPa > 0 && PositionGetDouble(POSITION_TP)==0.0)
                       {
                        trade.PositionModify(PositionGetInteger(POSITION_TICKET),PositionGetDouble(POSITION_SL),TP);
                       }
                     else
                        if(SLa > 0 && PositionGetDouble(POSITION_SL)==0.0)
                          {
                           trade.PositionModify(PositionGetInteger(POSITION_TICKET),SL,PositionGetDouble(POSITION_TP));
                          }
                 }
           }
         else
            if(autoMode == Client)
              {
               if((TPa>0 && Poin>=TPa) || (SLa>0 && Poin<=(-SLa)))
                 {
                  if(trade.PositionClose(PositionGetInteger(POSITION_TICKET),slip))
                    {
                     if(inpEnableAlert)
                       {
                        if(PositionGetDouble(POSITION_PROFIT)>0)
                           Alert("Closed by Virtual TP #",PositionGetInteger(POSITION_TICKET)," Profit=",PositionGetDouble(POSITION_PROFIT)," Points=",Poin);
                        if(PositionGetDouble(POSITION_PROFIT)<0)
                           Alert("Closed by Virtual SL #",PositionGetInteger(POSITION_TICKET)," Loss=",PositionGetDouble(POSITION_PROFIT)," Points=",Poin);
                       }
                    }
                 }
              }


         if(LPA>0 && PL>0 && Poin>=LPA)
           {
            if(Poin<=LPA+TS)
              {
               LockProfit(PositionGetInteger(POSITION_TICKET),LPA,PL);
              }
            else
               if(Poin>=LPA+TS)
                 {
                  RZ_TrailingStop(PositionGetInteger(POSITION_TICKET),TS,TST,trailingMode);
                 }
           }
         else
            if(LPA==0)
              {
               RZ_TrailingStop(PositionGetInteger(POSITION_TICKET),TS,TST,trailingMode);
              }

        }
     }

   return (false);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void AutoSLTP::OrderTest()
  {
   if(!MQLInfoInteger(MQL_TESTER))
      return;
   if(CalculateInstantOrders()==0)
     {
      if(CheckMoneyForTrade("EURUSD",0.01,ORDER_TYPE_BUY) && CheckVolumeValue("EURUSD",0.01))
         trade.Buy(0.01,"EURUSD",SymbolInfoDouble("EURUSD",SYMBOL_ASK),0,0,NULL);
      if(CheckMoneyForTrade("GBPUSD",0.01,ORDER_TYPE_SELL) && CheckVolumeValue("GBPUSD",0.01))
         trade.Sell(0.01,"GBPUSD",SymbolInfoDouble("GBPUSD",SYMBOL_BID),0,0,NULL);
     }

   return;
  }

//+------------------------------------------------------------------+
bool AutoSLTP::LockProfit(ulong ticket, int Targetpoint,int Lockedpoint)
  {
   if(LPMode==false || Targetpoint==0 || Lockedpoint==0)
      return false;

   if(PositionSelectByTicket(ticket)==false)
      return false;

   double ask = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_ASK);
   double bid = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_BID);
   double point = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_POINT);
   int digits =(int)SymbolInfoInteger(PositionGetString(POSITION_SYMBOL),SYMBOL_DIGITS);
   int minstoplevel =(int)SymbolInfoInteger(PositionGetString(POSITION_SYMBOL),SYMBOL_TRADE_STOPS_LEVEL);

   double PSL=0;
   double CurrentSL=(PositionGetDouble(POSITION_SL)!=0)?PositionGetDouble(POSITION_SL):PositionGetDouble(POSITION_PRICE_OPEN);

   if(Targetpoint < Lockedpoint)
     {
      Print("Target point must be higher than Profit Lock");
      return false;
     }

   if((PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) && (bid-PositionGetDouble(POSITION_PRICE_OPEN)>=Targetpoint*point) && (CurrentSL<=PositionGetDouble(POSITION_PRICE_OPEN)))
     {
      PSL=NormalizeDouble(PositionGetDouble(POSITION_PRICE_OPEN)+(Lockedpoint*point),digits);
     }
   else
      if((PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) && (PositionGetDouble(POSITION_PRICE_OPEN)-ask>=Targetpoint*point) && (CurrentSL>=PositionGetDouble(POSITION_PRICE_OPEN)))
        {
         PSL=NormalizeDouble(PositionGetDouble(POSITION_PRICE_OPEN)-(Lockedpoint*point),digits);
        }
      else
         return false;

   if(trade.PositionModify(ticket,PSL,PositionGetDouble(POSITION_TP)))
      return true;
   else
      return false;


   return false;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool AutoSLTP::RZ_TrailingStop(ulong ticket, int JumlahPoin,int Step=1,ENUM_TRAILINGSTOP_METHOD Method=TS_STEP_DISTANCE)
  {
   if(JumlahPoin==0)
      return false;

   if(PositionSelectByTicket(ticket)==false)
      return false;

   double ask = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_ASK);
   double bid = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_BID);
   double point = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_POINT);
   int digits =(int)SymbolInfoInteger(PositionGetString(POSITION_SYMBOL),SYMBOL_DIGITS);
   int minstoplevel =(int)SymbolInfoInteger(PositionGetString(POSITION_SYMBOL),SYMBOL_TRADE_STOPS_LEVEL);
   int spread =(int)SymbolInfoInteger(PositionGetString(POSITION_SYMBOL),SYMBOL_SPREAD);

   double TSL=0;
   double CurrentSL=(PositionGetDouble(POSITION_SL)!=0)?PositionGetDouble(POSITION_SL):PositionGetDouble(POSITION_PRICE_OPEN);

   if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY && (bid-PositionGetDouble(POSITION_PRICE_OPEN)>JumlahPoin*point))
     {
      //for buy limit == suspected errors come from this
      if(CurrentSL<PositionGetDouble(POSITION_PRICE_OPEN))
         CurrentSL=PositionGetDouble(POSITION_PRICE_OPEN);

      if((bid-CurrentSL)>=(JumlahPoin)*point)
        {
         switch(Method)
           {
            case TS_CLASSIC://Classic, no step
               TSL=NormalizeDouble(bid-(JumlahPoin*point),digits);
               break;
            case TS_STEP_DISTANCE://Step keeping distance
               TSL=NormalizeDouble(bid-((JumlahPoin-Step)*point),digits);
               break;
            case TS_STEP_BY_STEP://Step by step (slow)
               TSL=NormalizeDouble(CurrentSL+(Step*point),digits);
               break;
            case TS_NONE://No Trailing
               TSL=0;
               break;
            default:
               TSL=0;
           }
        }
     }

   else
      if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL && (PositionGetDouble(POSITION_PRICE_OPEN)-ask>JumlahPoin*point))
        {
         //for sell limit == suspected errors come from this
         if(CurrentSL>PositionGetDouble(POSITION_PRICE_OPEN))
            CurrentSL=PositionGetDouble(POSITION_PRICE_OPEN);

         if((CurrentSL-ask)>=(JumlahPoin)*point)
           {
            switch(Method)
              {
               case TS_CLASSIC://Classic
                  TSL=NormalizeDouble(ask+(JumlahPoin*point),digits);
                  break;
               case TS_STEP_DISTANCE://Step keeping distance
                  TSL=NormalizeDouble(ask+((JumlahPoin-Step)*point),digits);
                  break;
               case TS_STEP_BY_STEP://PositionGetDouble(POSITION_SL) by step (slow)
                  TSL=NormalizeDouble(CurrentSL-(Step*point),digits);
                  break;
               case TS_NONE://No Trailing
                  TSL=0;
                  break;
               default:
                  TSL=0;
              }
           }
        }
   if(TSL==0)
      return false;

   if(TSL != CurrentSL)
     {
      if(trade.PositionModify(ticket,TSL,PositionGetDouble(POSITION_TP)))
         return true;
      else
         return false;
     }

   return false;
  }



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int AutoSLTP::CalculateInstantOrders()
  {
   int buys=0, sells=0;
   for(int i=PositionsTotal()-1; i>=0; i--)
     {
      if(PositionGetTicket(i))
         if(chartMode==CurrentChartSymbol && PositionGetString(POSITION_SYMBOL)!=Symbol())
            continue;
        {
         if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
            buys++;
         if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
            sells++;
        }
     }
   if(buys > 0)
      return(buys);
   else
      return(-sells);

  }

//+------------------------------------------------------------------+
bool AutoSLTP::CheckMoneyForTrade(string sym, double lots,ENUM_ORDER_TYPE type)
  {
//--- Getting the opening price
   MqlTick mqltick;
   SymbolInfoTick(sym,mqltick);
   double price=mqltick.ask;
   if(type==ORDER_TYPE_SELL)
      price=mqltick.bid;
//--- values of the required and free margin
   double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
//--- call of the checking function
   if(!OrderCalcMargin(type,sym,lots,price,margin))
     {
      //--- something went wrong, report and return false
      return(false);
     }
//--- if there are insufficient funds to perform the operation
   if(margin>free_margin)
     {
      //--- report the error and return false
      return(false);
     }
//--- checking successful
   return(true);
  }
//************************************************************************************************/
bool AutoSLTP::CheckVolumeValue(string sym, double volume)
  {

   double min_volume = SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN);
   if(volume < min_volume)
      return(false);

   double max_volume = SymbolInfoDouble(sym, SYMBOL_VOLUME_MAX);
   if(volume > max_volume)
      return(false);

   double volume_step = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);

   int ratio = (int)MathRound(volume / volume_step);
   if(MathAbs(ratio * volume_step - volume) > 0.0000001)
      return(false);

   return(true);
  }
//+------------------------------------------------------------------+
int OnInit()
  {
   auto.TPa = TakeProfit;
   auto.SLa = StopLoss;
   auto.TS = TrailingStop;
   auto.TST = TrailingStep;
   auto.LPA = LockProfitAfter;
   auto.PL = ProfitLock;
   auto.slip = Slippage;
   auto.chartMode = ChartSymbolSelection;
   auto.trailingMode = TrailingStopMethod;
   auto.LPMode = LockProfitEnable;
   auto.autoMode = SLnTPMode;

   trade.SetDeviationInPoints(auto.slip);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(inpEnableTest)
      auto.OrderTest();
   if(auto.CalculateInstantOrders()!=0)
      auto.SetInstantSLTP();

   return;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

   return;
  }
//+------------------------------------------------------------------+

Comments