

#include <stdlib.mqh>

extern string Expert_Name = "Quik Trailing ";
extern bool    ManageByMagicNumber=false;
extern int     MagicNumber=1;
extern string s1 = "-- StopLoss & TakeProfit control ------------------------------------";
extern bool Automatic_SL = FALSE;
extern double Automatic_SL_Ratio = 2.0;
extern double Auto_Max_SL = 150.0;
extern double StopLoss = 50.0;
extern string s11 = "-------------------------------";
extern bool Automatic_TP = FALSE;
extern double Automatic_TP_Ratio = 2.0;
extern double TakeProfit = 30.0;
extern string s12 = "-------------------------------";
extern bool Use_First_TakeProfit = TRUE;
extern double First_TakeProfit_At = 15.0;
extern int First_TakeProfit_Percent = 60;
extern bool AlertSound = TRUE;
extern string s0 = "-- Trailing Step & Set Breakeven control ----------------";
extern bool Use_TrailingStep = TRUE;
extern double Start_Trailing_At = 8.0;
extern double TrailingStep = 3.0;
extern string s01 = "-------------------------------";
extern bool Use_Set_BreakEven = TRUE;
extern double LockPips = 0.0;
extern double Set_BreakEvenAt = 6.0;
extern string s2 = "--------------------------------------------------------------------";
extern double MaxSlippage = 5.0;
extern string s3 = "--------------------------------------------------------------------";
extern bool Allow_Drag_PriceLines = TRUE;
extern string s4 = "--------------------------------------------------------------------";
extern bool AccountIsMicro = TRUE;
extern bool ShowInfo = TRUE;
string gs_dummy_280;
int gi_288 = 1;
int Q;
double gd_292;
int g_bars_300 = -1;




int init() {
   Expert_Name = "Quik Trailing  ";
   if (AccountIsMicro) gi_288 = 2;
   else gi_288 = 1;
   gd_292 = Point_Broker();
   MaxSlippage *= SetBrokerX();
   if (Use_First_TakeProfit && First_TakeProfit_Percent < 1 || First_TakeProfit_Percent > 100) Alert("Error: First_TakeProfit_Percent setting value must be set between 1 and 100");
   if (IsExpertEnabled()) Comment("\n\n" + Expert_Name + " initialized\n\nWaiting for price data...");
   else Comment("\n\n" + Expert_Name + " is DISABLED...");
   g_bars_300 = -1;
   return (0);
}

int deinit() {
   ObjectDelete("Copyright");
   Del_Lin();
   return (0);
}

int start() {

  
  int Stellen=Digits;
    if (Stellen ==0)
  {
  Q=1;
  }
  
  
  if (Stellen ==1)
  {
  Q=2;
  }
  
    if (Stellen ==2)
  {
  Q=100;
  }
  
    if (Stellen ==4)
  {
  Q=10000;
  }
  
      if (Stellen ==5)
  {
  Q=100000;
  }
   string verlust;
   string ls_unused_0;
   string ls_ge;
   string ls_8;
   string ls_16;
   string ls_24;
   string ls_32;
   string ls_40;
   string ls_48;
   string l_dbl2str_56;
   if (g_bars_300 != Bars) {
      g_bars_300 = Bars;
      Ares();
   }
   if (ShowInfo) {
      
      ls_unused_0 = "";
      ls_ge = "";
      ls_8 = "";
      ls_16 = "";
      ls_24 = "";
      ls_32 = "";
      ls_40 = "";
      ls_48 = "";
     
      if (OrderLots()==0) ls_ge = "\nAktuellerGewinn: keine Position offen";
      else {
      if (OrderType() == OP_BUY) ls_ge = "\naktueller GEWINN/VERLUST:  " + DoubleToStr((Bid-OrderOpenPrice())*Q*(OrderLots()*(MarketInfo(Symbol(),MODE_TICKVALUE ))),2) +" EURO  ";
      if (OrderType() == OP_SELL)ls_ge = "\naktueller GEWINN/VERLUST:  " + DoubleToStr((OrderOpenPrice()-Ask)*Q*(OrderLots()*(MarketInfo(Symbol(),MODE_TICKVALUE ))),2) +" EURO  ";
           }
           if (OrderType() == OP_BUY)
         {     
      if (OrderStopLoss()<OrderOpenPrice()) verlust= "\nmöglicher VERLUST:  " + DoubleToStr((MathAbs(OrderStopLoss()-OrderOpenPrice())*Q*(OrderLots()*(MarketInfo(Symbol(),MODE_TICKVALUE )))),2) +" EURO" ;  
      if (OrderStopLoss()>OrderOpenPrice()) verlust= "\nminimaler GEWINN:  " + DoubleToStr((MathAbs(OrderStopLoss()-OrderOpenPrice())*Q*(OrderLots()*(MarketInfo(Symbol(),MODE_TICKVALUE )))),2) +" EURO" ; 
      if (OrderStopLoss()==OrderOpenPrice()&& OrderLots()>0) verlust= "\nSL auf BE  " ;  
      if (OrderLots()==0) verlust= "\nmöglicher VERLUST:  " + DoubleToStr((MathAbs(OrderStopLoss()-OrderOpenPrice())*Q*(OrderLots()*(MarketInfo(Symbol(),MODE_TICKVALUE )))),2) +" EURO" ; 
         }  
          
            if (OrderType() == OP_SELL)
         {     
      if (OrderStopLoss()>OrderOpenPrice()) verlust= "\nmöglicher VERLUST:  " + DoubleToStr((MathAbs(OrderStopLoss()-OrderOpenPrice())*Q*(OrderLots()*(MarketInfo(Symbol(),MODE_TICKVALUE )))),2) +" EURO" ;  
      if (OrderStopLoss()<OrderOpenPrice()) verlust= "\nminimaler GEWINN:  " + DoubleToStr((MathAbs(OrderStopLoss()-OrderOpenPrice())*Q*(OrderLots()*(MarketInfo(Symbol(),MODE_TICKVALUE )))),2) +" EURO" ;  
      if (OrderStopLoss()==OrderOpenPrice()&& OrderLots()>0) verlust= "\nSL auf BE  " ;
      if (OrderLots()==0) verlust= "\nmöglicher VERLUST:  " + DoubleToStr((MathAbs(OrderStopLoss()-OrderOpenPrice())*Q*(OrderLots()*(MarketInfo(Symbol(),MODE_TICKVALUE )))),2) +" EURO" ; 
         } 
      
          
      if (Digits == 5 || Digits == 3) l_dbl2str_56 = DoubleToStr(NormalizeDouble(MarketInfo(Symbol(), MODE_SPREAD) / 10.0, 1), 1);
      else l_dbl2str_56 = DoubleToStr(NormalizeDouble(MarketInfo(Symbol(), MODE_SPREAD), 0), 0);
      if (Use_TrailingStep) ls_8 = "\nTrailing Step is ON (Start at +" + DoubleToStr(Start_Trailing_At, 1) + " pips. Step " + DoubleToStr(TrailingStep, 1) + ")";
      else ls_8 = "\nTrailing Step is OFF";
      if (Use_Set_BreakEven) ls_16 = "\nSet Breakeven is ON (at +" + DoubleToStr(Set_BreakEvenAt, 1) + " pips)";
      else ls_16 = "\nSet Breakeven is OFF";
      if (Use_First_TakeProfit) ls_24 = "\nFirst TakeProfit is ON (" + DoubleToStr(First_TakeProfit_Percent, 0) + "% at +" + DoubleToStr(First_TakeProfit_At, 1) + " pips)\n------------------------------------------------------";
      else ls_24 = "\nFirst TakeProfit is OFF\n----------------------------------------------------------------------";
      if (OrderLots()==0) ls_32 = "\nStandartStopLoss: " + DoubleToStr(StopLoss, 1) + " pips ";
      else ls_32 = "\nStopLoss: " + DoubleToStr((MathAbs(OrderStopLoss()-OrderOpenPrice())*Q), 0)+ " pips   "+"("+ DoubleToStr(OrderStopLoss(), Digits) +")";
      if (OrderLots()==0) ls_40 = "\nStandartTakeProfit: " + DoubleToStr(TakeProfit, 1) + " pips ";
      else ls_40 = "\nTakeProfit: " + DoubleToStr((MathAbs(OrderTakeProfit()-OrderOpenPrice())*Q), 0)+ " pips   "+"("+ DoubleToStr(OrderTakeProfit(), Digits) +")";
      ls_40 = ls_40 
      + "\n----------------------------------------------------------";
      if (IsTradeAllowed() == FALSE) ls_48 = "\nTrade NOT Allowed";
      Comment( "\n" + Expert_Name 
         + "\n" 
         + "---------------------------------------------------------" 
         + "\n" 
         + "          INFORMATION"+(MarketInfo(Symbol(), MODE_TICKVALUE)) 
         + "\n" 
         + "---------------------------------------------------------" + ls_8 + ls_16 + ls_24 + ls_32 + ls_40 
         + ls_ge
         + "\n" 
         + "---------------------------------------------------------"
         + "\n"
         + "möglicher GEWINN:  "+ DoubleToStr((MathAbs(OrderTakeProfit()-OrderOpenPrice())*Q*(OrderLots()*(MarketInfo(Symbol(),MODE_TICKVALUE )))),2) +" EURO" 
         + verlust
         + "\n"
         + "---------------------------------------------------------" + ls_48); 
   } else Comment("");
   Check_TrailingStop();
   if (Allow_Drag_PriceLines) Drag_Lines();
   return (0);
}

int Check_TrailingStop() {
   int f;
   double l_lots_0;
   double ld_8;
   double ld_16;
   int l_error_24;
   string l_dbl2str_28;
   double l_point_36;
   double ld_44;
   double ld_52;
   double ld_60;
   double ld_68;
   double ld_76;
   double ld_84;
   double l_price_92;
   if (OrderLots()==0) f=0;
   for (int l_pos_100 = 0; l_pos_100 < OrdersTotal(); l_pos_100++) {
      OrderSelect(l_pos_100, SELECT_BY_POS, MODE_TRADES);
      if (OrderSymbol() == Symbol() ) {
         if (MarketInfo(OrderSymbol(), MODE_POINT) == 0.00001) l_point_36 = 0.0001;
         else {
            if (MarketInfo(OrderSymbol(), MODE_POINT) == 0.001) l_point_36 = 0.01;
            else l_point_36 = MarketInfo(OrderSymbol(), MODE_POINT);
         }
         ld_44 = TrailingStep * l_point_36;
         ld_52 = Start_Trailing_At * l_point_36;
         ld_60 = LockPips * l_point_36;
         ld_68 = Set_BreakEvenAt * l_point_36;
         ld_76 = TakeProfit * l_point_36;
         ld_76 = NormalizeDouble(ld_76, Digits);
         if (OrderType() == OP_BUY) {
            if (Use_TrailingStep && Bid - OrderOpenPrice() >= ld_52) {
               if (Bid - OrderStopLoss() >= ld_52 + ld_44) {
                  Del_Lin();
                  OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss() + ld_44, OrderTakeProfit(), 0);
                  
               }
            }
            if (Use_First_TakeProfit && OrderComment() == "") {
               if (Bid - OrderOpenPrice() >= First_TakeProfit_At * l_point_36) {
                  Del_Lin();
                  ld_8 = First_TakeProfit_Percent;
                  ld_16 = ld_8 / 100.0;
                  l_lots_0 = NormalizeDouble(OrderLots() * ld_16, gi_288);
                  if (OrderClose(OrderTicket(), l_lots_0, Bid, MaxSlippage, Yellow) == 0) {
                     l_error_24 = GetLastError();
                     l_dbl2str_28 = DoubleToStr(Bid, Digits);
                     Print("ERROR closing BUY order (FIRST TakeProfit) : (", l_error_24, ") " + ErrorDescription(l_error_24) + " | Lots: " + DoubleToStr(l_lots_0, gi_288) + " | at " +
                        l_dbl2str_28);
                     continue;
                  }
                  l_dbl2str_28 = DoubleToStr(OrderClosePrice(), Digits);
                  Print("FIRST TakeProfit close Buy order: " + DoubleToStr(l_lots_0, gi_288) + " Lots at " + l_dbl2str_28);
                  if (!(AlertSound)) continue;
                  PlaySound("news.wav");
                  continue;
               }
            }
            if (OrderStopLoss() == 0.0 && StopLoss != 0.0) {
               Del_Lin();
               ld_84 = OrderOpenPrice() - StopLoss * l_point_36;
               l_price_92 = ValidStopLoss(0, Bid, ld_84);
               l_price_92 = NormalizeDouble(l_price_92, Digits);
               if (OrderTakeProfit() == 0.0 && ld_76 != 0.0) OrderModify(OrderTicket(), OrderOpenPrice(), l_price_92, OrderOpenPrice() + ld_76, 0);
               else OrderModify(OrderTicket(), OrderOpenPrice(), l_price_92, OrderTakeProfit(), 0);
            }
            if (Use_Set_BreakEven && Bid - OrderOpenPrice() >= ld_68) {
               if (OrderStopLoss() < OrderOpenPrice()) {
                  Del_Lin();
                  if (!(AlertSound)) continue;
                  PlaySound("news.wav");
                  OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice() + ld_60, OrderTakeProfit(), 0);
               }
            }
         } else {
            if (OrderType() == OP_SELL) {
               if (Use_TrailingStep && OrderOpenPrice() - Ask >= ld_52) {
                  if (OrderStopLoss() - Ask >= ld_52 + ld_44) {
                     Del_Lin();
                     OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss() - ld_44, OrderTakeProfit(), 0);
                  }
               }
               if (Use_First_TakeProfit && OrderComment() == "") {
                  if (OrderOpenPrice() - Ask >= First_TakeProfit_At * l_point_36) {
                     Del_Lin();
                     ld_8 = First_TakeProfit_Percent;
                     ld_16 = ld_8 / 100.0;
                     l_lots_0 = NormalizeDouble(OrderLots() * ld_16, gi_288);
                     if (OrderClose(OrderTicket(), l_lots_0, Ask, MaxSlippage, Yellow) == 0) {
                        l_error_24 = GetLastError();
                        l_dbl2str_28 = DoubleToStr(Ask, Digits);
                        Print("ERROR closing SELL order (FIRST TakeProfit) : (", l_error_24, ") " + ErrorDescription(l_error_24) + " | Lots: " + DoubleToStr(l_lots_0, gi_288) + " | at " +
                           l_dbl2str_28);
                        continue;
                     }
                     l_dbl2str_28 = DoubleToStr(OrderClosePrice(), Digits);
                     Print("FIRST TakeProfit close Sell order: " + DoubleToStr(l_lots_0, gi_288) + " Lots at " + l_dbl2str_28);
                     if (!(AlertSound)) continue;
                     PlaySound("news.wav");
                     continue;
                  }
               }
               if (OrderStopLoss() == 0.0 && StopLoss != 0.0) {
                  Del_Lin();
                  ld_84 = OrderOpenPrice() + StopLoss * l_point_36;
                  l_price_92 = ValidStopLoss(1, Ask, ld_84);
                  l_price_92 = NormalizeDouble(l_price_92, Digits);
                  if (OrderTakeProfit() == 0.0 && ld_76 != 0.0) OrderModify(OrderTicket(), OrderOpenPrice(), l_price_92, OrderOpenPrice() - ld_76, 0);
                  else OrderModify(OrderTicket(), OrderOpenPrice(), l_price_92, OrderTakeProfit(), 0);
               }
               if (Use_Set_BreakEven && OrderOpenPrice() - Ask >= ld_68) {
                  if (OrderStopLoss() > OrderOpenPrice()) {
                     Del_Lin();
                     if (!(AlertSound)) continue;
                     PlaySound("news.wav");
                     OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice() - ld_60, OrderTakeProfit(), 0);
                  }
               }
            }
         }
      }
   }
   return (0);
}

double ValidStopLoss(int ai_unused_0, double ad_unused_4, double ad_12) {
   return (ad_12);
}

int Drag_Lines() {
   string l_name_8;
   int li_16;
   int li_20;
   string ls_0 = Symbol();
   for (int l_pos_24 = 0; l_pos_24 <= OrdersTotal(); l_pos_24++) {
      if (OrderSelect(l_pos_24, SELECT_BY_POS, MODE_TRADES)) {
          if (OrderSymbol() == ls_0) {
               if (OrderStopLoss() > 0.0) {
                  l_name_8 = "_SL" + OrderTicket();
                  li_16 = MathRound(OrderStopLoss() / Point);
                  if (ObjectFind(l_name_8) < 0) ObjectCreate(l_name_8, OBJ_HLINE, 0, TimeCurrent(), OrderStopLoss());
                  ObjectSet(l_name_8, OBJPROP_COLOR, Red);
                  li_20 = MathRound(ObjectGet(l_name_8, OBJPROP_PRICE1) / Point);
                  ObjectSet(l_name_8, OBJPROP_PRICE1, li_20 * Point);
                  if (li_20 != li_16) {
                     if (!OrderModify(OrderTicket(), OrderOpenPrice(), li_20 * Point, OrderTakeProfit(), OrderExpiration())) {
                        Print("ERROR OrderModify(SL): ", ErrorDescription(GetLastError()));
                        ObjectSet(l_name_8, OBJPROP_PRICE1, li_16 * Point);
                     }
                  }
                  ObjectSet(l_name_8, OBJPROP_BACK, TRUE);
               }
               if (OrderTakeProfit() > 0.0) {
                  l_name_8 = "_TP" + OrderTicket();
                  li_16 = MathRound(OrderTakeProfit() / Point);
                  if (ObjectFind(l_name_8) < 0) ObjectCreate(l_name_8, OBJ_HLINE, 0, TimeCurrent(), OrderTakeProfit());
                  ObjectSet(l_name_8, OBJPROP_COLOR, Lime);
                  li_20 = MathRound(ObjectGet(l_name_8, OBJPROP_PRICE1) / Point);
                  ObjectSet(l_name_8, OBJPROP_PRICE1, li_20 * Point);
                  if (li_20 != li_16) {
                     if (!OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), li_20 * Point, OrderExpiration())) {
                        Print("ERROR OrderModify(TP): ", ErrorDescription(GetLastError()));
                        ObjectSet(l_name_8, OBJPROP_PRICE1, li_16 * Point);
                     }
                  }
                  ObjectSet(l_name_8, OBJPROP_BACK, TRUE);
               }
               if (OrderType() > OP_SELL) {
                  l_name_8 = "_OP" + OrderTicket();
                  li_16 = MathRound(OrderOpenPrice() / Point);
                  if (ObjectFind(l_name_8) < 0) ObjectCreate(l_name_8, OBJ_HLINE, 0, TimeCurrent(), OrderOpenPrice());
                  ObjectSet(l_name_8, OBJPROP_COLOR, Gold);
                  li_20 = MathRound(ObjectGet(l_name_8, OBJPROP_PRICE1) / Point);
                  ObjectSet(l_name_8, OBJPROP_PRICE1, li_20 * Point);
                  if (li_20 != li_16) {
                     if (!OrderModify(OrderTicket(), li_20 * Point, OrderStopLoss(), OrderTakeProfit(), OrderExpiration())) {
                        Print("ERROR OrderModify(OP): ", ErrorDescription(GetLastError()));
                        ObjectSet(l_name_8, OBJPROP_PRICE1, li_16 * Point);
                     }
                  }
                  ObjectSet(l_name_8, OBJPROP_BACK, TRUE);
               }
            }
         }
      }
   
   for (l_pos_24 = ObjectsTotal() - 1; l_pos_24 >= 0; l_pos_24--) {
      l_name_8 = ObjectName(l_pos_24);
      if (StringSubstr(l_name_8, 0, 1) == "_") {
         if (OrderSelect(StrToInteger(StringSubstr(l_name_8, 3)), SELECT_BY_TICKET))
            if (OrderCloseTime() > 0) ObjectDelete(l_name_8);
      }
   }
   ObjectsRedraw();
   return (0);
}

int Del_Lin() {
   string l_name_0;
   if (Allow_Drag_PriceLines == FALSE) return (0);
   for (int li_8 = ObjectsTotal() - 1; li_8 >= 0; li_8--) {
      l_name_0 = ObjectName(li_8);
      if (StringSubstr(l_name_0, 0, 1) == "_") ObjectDelete(l_name_0);
   }
   ObjectsRedraw();
   return (0);
}



int SetBrokerX() {
   double ld_ret_0;
   if (Digits == 5 || Digits == 3) ld_ret_0 = 10;
   else ld_ret_0 = 1;
   return (ld_ret_0);
}

double Point_Broker() {
   double l_point_0;
   if (MarketInfo(Symbol(), MODE_POINT) == 0.00001) l_point_0 = 0.0001;
   else {
      if (MarketInfo(Symbol(), MODE_POINT) == 0.001) l_point_0 = 0.01;
      else l_point_0 = MarketInfo(Symbol(), MODE_POINT);
   }
   return (l_point_0);
}

int Ares() {
   double ld_0;
   double ld_8;
   HideTestIndicators(TRUE);
   if (Automatic_SL == TRUE) {
      ld_0 = 0.75 * iATR(NULL, 0, 100, 1) / gd_292;
      StopLoss = ld_0 * Automatic_SL_Ratio;
      if (StopLoss > Auto_Max_SL) StopLoss = Auto_Max_SL;
   }
   if (Automatic_TP == TRUE) {
      ld_8 = 0.75 * iATR(NULL, 0, 100, 1) / gd_292;
      TakeProfit = ld_8 / 2.0 * Automatic_TP_Ratio;
   }
   HideTestIndicators(FALSE);
   return (0);
}