//+------------------------------------------------------------------+
//|                          Automatic Stop Loss and Take Profit.mq5 |
//|                       Copyright 2019, foreXService Andrzej Pierz |
//|                                     https://www.forex-service.eu |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, foreXService Andrzej Pierz"
#property link      "https://www.forex-service.eu"
#property version   "1.00"

input bool allPair    = true;
input int  stopLoss   = 100;
input int  takeProfit = 100;

enum ENUM_CORNER {LEFT_DN, LEFT_UP, RIGHT_DN, RIGHT_UP };

input bool        showInfo = true;
input string      fontName = "Arial";
input int         fontSize = 10;
input color       fontColor = clrRed;
input int         offsetLine = 20;
input ENUM_CORNER corner = RIGHT_UP;
input int         shiftY = 15;
input int         shiftX = 0;

int cornerMQL;
int OnInit()
{
   while (EventSetMillisecondTimer(500) == false) Sleep(100);
   
   
   if(showInfo)
   {
      cornerMQL = CORNER_RIGHT_UPPER;
      if(corner == RIGHT_DN) cornerMQL = CORNER_RIGHT_LOWER;
      else if(corner == LEFT_DN) cornerMQL = CORNER_LEFT_LOWER;
      else if(corner == LEFT_UP) cornerMQL = CORNER_LEFT_UPPER;
      
      int x_base = 15;
      int y_base = 5;
      
      ObjectCreate ( 0,"allpair",OBJ_LABEL,0,0,0 );
      ObjectSetInteger (0, "allpair",OBJPROP_CORNER, cornerMQL );
      ObjectSetInteger ( 0,"allpair",OBJPROP_COLOR, fontColor );
      ObjectSetInteger (0, "allpair",OBJPROP_XDISTANCE,x_base + shiftX);
      
      
      ObjectCreate ( 0,"stoploss",OBJ_LABEL,0,0,0 );
      ObjectSetInteger (0, "stoploss",OBJPROP_CORNER, cornerMQL );
      ObjectSetInteger (0, "stoploss",OBJPROP_COLOR, fontColor );
      ObjectSetInteger (0, "stoploss",OBJPROP_XDISTANCE,x_base + shiftX);
      ObjectSetInteger (0, "stoploss",OBJPROP_YDISTANCE,y_base + offsetLine + shiftY );
       
      ObjectCreate (0, "takeprofit",OBJ_LABEL,0,0,0 );
      ObjectSetInteger (0, "takeprofit",OBJPROP_CORNER, cornerMQL );
      ObjectSetInteger ( 0,"takeprofit",OBJPROP_COLOR, fontColor );
      ObjectSetInteger (0, "takeprofit",OBJPROP_XDISTANCE,x_base + shiftX);
      
      if(cornerMQL == CORNER_LEFT_UPPER || cornerMQL == CORNER_RIGHT_UPPER)
      {
         ObjectSetInteger (0, "allpair",OBJPROP_YDISTANCE,y_base + shiftY);
         ObjectSetInteger ( 0,"takeprofit",OBJPROP_YDISTANCE,y_base + 2*offsetLine + shiftY );
      }
      else
      {
         ObjectSetInteger ( 0,"allpair",OBJPROP_YDISTANCE,y_base + 2*offsetLine + shiftY);
         ObjectSetInteger (0, "takeprofit",OBJPROP_YDISTANCE,y_base + shiftY );
      }
   }
   else
   {
      ObjectDelete (0, "allpair" );
      ObjectDelete (0, "stoploss" );
      ObjectDelete (0, "takeprofit" );
   }
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   ObjectDelete (0, "allpair" );
   ObjectDelete (0, "stoploss" );
   ObjectDelete (0, "takeprofit" );
   EventKillTimer();
}

void OnTimer()
{
   OnTick();
}

void OnTick()
{
   if (showInfo)
   {
      ObjectSetText("allpair","All pair : "+(allPair ? "Enabled":"Disabled"),fontSize,fontName,fontColor);
      ObjectSetText("stoploss","Stop Loss : "+IntegerToString(stopLoss),fontSize,fontName,fontColor);
      ObjectSetText("takeprofit","Take Profit : "+IntegerToString(takeProfit),fontSize,fontName,fontColor);
      ChartRedraw();
   }
   SecurityPositions();
   SecurityPendings();
}
  
void SecurityPositions()
{
   for (int i = PositionsTotal() - 1;i >= 0;i--)
   {
      ulong positionTicket = PositionGetTicket(i);
      if (PositionSelectByTicket(positionTicket) == true)
      {
         double sl = 0;
         double tp = 0;
         if (PositionGetDouble(POSITION_SL) == 0 && stopLoss > 0)
         {
            if (allPair == true || PositionGetString(POSITION_SYMBOL) == Symbol())
            {
               if (PositionGetInteger(POSITION_TYPE)%2 == 0)
               {
                  sl = PositionGetDouble(POSITION_PRICE_OPEN) - stopLoss * SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_POINT);
               }
               else
               {
                  sl = PositionGetDouble(POSITION_PRICE_OPEN) + stopLoss * SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_POINT);
               }
            }
         }
         if (PositionGetDouble(POSITION_TP) == 0 && takeProfit > 0)
         {
            if (allPair == true || PositionGetString(POSITION_SYMBOL) == Symbol())
            {
               if (PositionGetInteger(POSITION_TYPE)%2 == 0)
               {
                  tp = PositionGetDouble(POSITION_PRICE_OPEN) + takeProfit * SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_POINT);
               }
               else
               {
                  tp = PositionGetDouble(POSITION_PRICE_OPEN) - takeProfit * SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_POINT);
               }
            }
         }
               
         if (sl != 0 || tp != 0)
         {
            OrderModify(positionTicket,PositionGetDouble(POSITION_PRICE_OPEN),sl > 0 ? sl : PositionGetDouble(POSITION_SL),tp > 0 ? tp : PositionGetDouble(POSITION_TP));
         }
      }
   }
}

void SecurityPendings()
{
   for (int i = OrdersTotal() - 1;i >= 0;i--)
   {
      ulong orderTicket = OrderGetTicket(i);
      if (OrderSelect(orderTicket) == true)
      {
         double sl = 0;
         double tp = 0;
         if (OrderGetDouble(ORDER_SL) == 0 && stopLoss > 0)
         {
            if (allPair == true || OrderGetString(ORDER_SYMBOL) == Symbol())
            {
               if (OrderGetInteger(ORDER_TYPE)%2 == 0)
               {
                  sl = OrderGetDouble(ORDER_PRICE_OPEN) - stopLoss * SymbolInfoDouble(OrderGetString(ORDER_SYMBOL),SYMBOL_POINT);
               }
               else
               {
                  sl = OrderGetDouble(ORDER_PRICE_OPEN) + stopLoss * SymbolInfoDouble(OrderGetString(ORDER_SYMBOL),SYMBOL_POINT);
               }
            }
         }
         if (OrderGetDouble(ORDER_TP) == 0 && takeProfit > 0)
         {
            if (allPair == true || OrderGetString(ORDER_SYMBOL) == Symbol())
            {
               if (OrderGetInteger(ORDER_TYPE)%2 == 0)
               {
                  tp = OrderGetDouble(ORDER_PRICE_OPEN) + takeProfit * SymbolInfoDouble(OrderGetString(ORDER_SYMBOL),SYMBOL_POINT);
               }
               else
               {
                  tp = OrderGetDouble(ORDER_PRICE_OPEN) - takeProfit * SymbolInfoDouble(OrderGetString(ORDER_SYMBOL),SYMBOL_POINT);
               }
            }
         }
               
         if (sl != 0 || tp != 0)
         {
            OrderModify(orderTicket,OrderGetDouble(ORDER_PRICE_OPEN),sl > 0 ? sl : OrderGetDouble(ORDER_SL),tp > 0 ? tp : OrderGetDouble(ORDER_TP),OrderGetInteger(ORDER_TIME_EXPIRATION));
         }
      }
   }
}


MqlTradeRequest   m_request;
MqlTradeResult    m_result; 
bool OrderModify(ulong ticket,double price,double stoploss,double takeprofit,datetime expiration = 0,color arrow_color = clrNONE)
{
   ::ZeroMemory(m_request);
   ::ZeroMemory(m_result);   
   
   if(!::PositionSelectByTicket(ticket) && !::OrderSelect(ticket)) return(false);
   
   int typ = ::PositionSelectByTicket(ticket) ? 0 : 1;
   
   m_request.action       = typ == 0? TRADE_ACTION_SLTP : TRADE_ACTION_MODIFY;
   m_request.symbol       = (typ == 0 ? ::PositionGetString(POSITION_SYMBOL) : ::OrderGetString(ORDER_SYMBOL));
   
   if (typ == 0) m_request.position   = ticket;
   if (typ == 1) m_request.order      = ticket;
   if (typ == 1) m_request.price      = price; 
   m_request.sl                       = stoploss;
   m_request.tp                       = takeprofit;
   if (typ == 1) m_request.expiration = expiration; 
   
   if (FillingCheck((typ == 0 ? ::PositionGetString(POSITION_SYMBOL) : ::OrderGetString(ORDER_SYMBOL))) == false) return false;
   
   bool send = OrderSend(m_request,m_result);
   if (send == false) Print(m_result.comment);
   if (send ==  true) return true;
   
   return false;
}

ENUM_ORDER_TYPE_FILLING m_type_filling;
bool FillingCheck(const string symbol)
{
   ENUM_SYMBOL_TRADE_EXECUTION exec=(ENUM_SYMBOL_TRADE_EXECUTION)SymbolInfoInteger(symbol,SYMBOL_TRADE_EXEMODE);
   if(exec==SYMBOL_TRADE_EXECUTION_REQUEST || exec==SYMBOL_TRADE_EXECUTION_INSTANT) return(true);

   uint filling=(uint)SymbolInfoInteger(symbol,SYMBOL_FILLING_MODE);

   if(exec==SYMBOL_TRADE_EXECUTION_MARKET)
   {
      if(m_request.action != TRADE_ACTION_PENDING)
      {
         if((filling&SYMBOL_FILLING_FOK)==SYMBOL_FILLING_FOK)
         {
            m_type_filling=ORDER_FILLING_FOK;
            m_request.type_filling=m_type_filling;
            return(true);
         }
         if((filling&SYMBOL_FILLING_IOC)==SYMBOL_FILLING_IOC)
         {
            m_type_filling=ORDER_FILLING_IOC;
            m_request.type_filling=m_type_filling;
            return(true);
         }
         m_result.retcode=TRADE_RETCODE_INVALID_FILL;
         return(false);
      }
      return(true);
   }
   
   switch(m_type_filling)
   {
      case ORDER_FILLING_FOK:
         if(m_request.action==TRADE_ACTION_PENDING)
         {
            if(m_request.type==ORDER_TYPE_BUY_STOP || m_request.type==ORDER_TYPE_SELL_STOP || m_request.type==ORDER_TYPE_BUY_LIMIT || m_request.type==ORDER_TYPE_SELL_LIMIT)
            {
               m_request.type_filling=ORDER_FILLING_RETURN;
               return(true);
            }
         }
         if((filling&SYMBOL_FILLING_FOK)==SYMBOL_FILLING_FOK)
         {
            m_request.type_filling=m_type_filling;
            return(true);
         }
         m_result.retcode=TRADE_RETCODE_INVALID_FILL;
         return(false);
      case ORDER_FILLING_IOC:
         if(m_request.action==TRADE_ACTION_PENDING)
         {
            if(m_request.type==ORDER_TYPE_BUY_STOP || m_request.type==ORDER_TYPE_SELL_STOP || m_request.type==ORDER_TYPE_BUY_LIMIT || m_request.type==ORDER_TYPE_SELL_LIMIT)
            {
               m_request.type_filling=ORDER_FILLING_RETURN;
               return(true);
            }
         }
         if((filling&SYMBOL_FILLING_IOC)==SYMBOL_FILLING_IOC)
         {
            m_request.type_filling=m_type_filling;
            return(true);
         }
         m_result.retcode=TRADE_RETCODE_INVALID_FILL;
         return(false);
      case ORDER_FILLING_RETURN:
         m_request.type_filling=m_type_filling;
         return(true);
   }
   m_result.retcode=TRADE_RETCODE_ERROR;
   return(false);
}

bool ObjectSetText(string objecName,string text,int size,string font ,color clr)
{
   ::ObjectSetString(0,objecName,OBJPROP_TEXT,text);
   ::ObjectSetString(0,objecName,OBJPROP_FONT,font);
   ::ObjectSetInteger(0,objecName,OBJPROP_FONTSIZE,size);
   ::ObjectSetInteger(0,objecName,OBJPROP_COLOR,clr);
   if (cornerMQL == CORNER_RIGHT_UPPER) ::ObjectSetInteger(0,objecName,OBJPROP_ANCHOR,ANCHOR_RIGHT_UPPER);
   if (cornerMQL == CORNER_RIGHT_LOWER) ::ObjectSetInteger(0,objecName,OBJPROP_ANCHOR,ANCHOR_RIGHT_LOWER);
   if (cornerMQL == CORNER_LEFT_UPPER) ::ObjectSetInteger(0,objecName,OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER);
   if (cornerMQL == CORNER_LEFT_LOWER) ::ObjectSetInteger(0,objecName,OBJPROP_ANCHOR,ANCHOR_LEFT_LOWER);
   
   return true;
}