/*
Советник тралит прибыль по отдельной валюте илли по всему счету целиком.
Тралл включается, когда прибыль на счете или по отдельному инструменту (зависитот установки AllSymbol) 
   достигает уровня ProfitClose (измеряется в валюте депозита).

Как только прибыль уменьшиться на TrailingProfit (измеряется в валюте депозита),все ордера будут закрыты.
Если прибыль продолжает расти, то при первом же откате ее значения на TrailingProfit,все ордера будут закрыты.
Если TrailingProfit=0, то советник просто закроет все ордера при достижении прибыли равной ProfitClose.
Если убыток по счету или отдельному инструменту составит LossClose, то все ордерабудут закрыты.
*/

extern double  ProfitClose       = 4.0;     
extern double  LossClose         = 10.0;
extern double  TrailingProfit    = 2.0;
extern bool    AllSymbol         = False;

string Gs_104;
bool Gi_112;
double Gd_116;

int init() {
   Gd_116 = ProfitClose;
   if (ProfitClose == 0.0 && TrailingProfit > 0.0) {
      Alert("Ошибка, ProfitClose не может быть меньше TrailingProfit");
      TrailingProfit = 0;
   }
   if(Digits == 3 || Digits == 5){
      ProfitClose *= 1.0;
      LossClose *= 1.0;
      TrailingProfit *= 1.0;
   }
   ObjectCreate("Balance", OBJ_LABEL, 0, 0, 0);
   ObjectSet("Balance", OBJPROP_CORNER, 1);
   ObjectSet("Balance", OBJPROP_XDISTANCE, 5);
   ObjectSet("Balance", OBJPROP_YDISTANCE, 15);
   ObjectCreate("Equity", OBJ_LABEL, 0, 0, 0);
   ObjectSet("Equity", OBJPROP_CORNER, 1);
   ObjectSet("Equity", OBJPROP_XDISTANCE, 5);
   ObjectSet("Equity", OBJPROP_YDISTANCE, 30);
   ObjectCreate("Profit", OBJ_LABEL, 0, 0, 0);
   ObjectSet("Profit", OBJPROP_CORNER, 1);
   ObjectSet("Profit", OBJPROP_XDISTANCE, 5);
   ObjectSet("Profit", OBJPROP_YDISTANCE, 45);
   ObjectCreate("ProfitClose", OBJ_LABEL, 0, 0, 0);
   ObjectSet("ProfitClose", OBJPROP_CORNER, 1);
   ObjectSet("ProfitClose", OBJPROP_XDISTANCE, 5);
   ObjectSet("ProfitClose", OBJPROP_YDISTANCE, 60);
   ObjectCreate("Copyright", OBJ_LABEL, 0, 0, 0);
   ObjectSet("Copyright", OBJPROP_CORNER, 3);
   ObjectSet("Copyright", OBJPROP_XDISTANCE, 5);
   ObjectSet("Copyright", OBJPROP_YDISTANCE, 5);
   if (ProfitClose != 0.0) {
      if (TrailingProfit == 0.0) Gs_104 = "\nПрофит для закрытия " + DoubleToStr(ProfitClose, 2) + " " + AccountCurrency();
      else Gs_104 = "\nТрайлинг старт = " + DoubleToStr(ProfitClose, 2) + " откат " + DoubleToStr(TrailingProfit, 2) + " " + AccountCurrency();
   }
   if (LossClose != 0.0) {
      Gs_104 = Gs_104 
      + "\nУбыток для закрытия " + DoubleToStr(LossClose, 2) + " " + AccountCurrency();
   }
   if (AllSymbol) {
      Gs_104 = Gs_104 
      + "\nПо всем инструментам счета";
   } else {
      Gs_104 = Gs_104 
      + "\nТолько по " + Symbol();
   }
   return (0);
}

int deinit() {
   ObjectDelete("Balance");
   ObjectDelete("Equity");
   ObjectDelete("Profit");
   ObjectDelete("Copyright");
   ObjectDelete("ProfitClose");
   return (0);
}

void start() {
   double Ld_0;
   int Li_8;
   int Li_12;
   int cmd_16;
   for (int pos_20 = OrdersTotal() - 1; pos_20 >= 0; pos_20--) {
      if (OrderSelect(pos_20, SELECT_BY_POS, MODE_TRADES)) {
         if (OrderSymbol() == Symbol() || AllSymbol) {
            cmd_16 = OrderType();
            if (cmd_16 == OP_BUY) {
               Li_8++;
               Ld_0 += OrderProfit() + OrderSwap() + OrderCommission();
            }
            if (cmd_16 == OP_SELL) {
               Li_12++;
               Ld_0 += OrderProfit() + OrderSwap() + OrderCommission();
            }
         }
      }
   }
   Comment(Gs_104, 
      "\nBuy ", Li_8, 
   "\nSell ", Li_12);
   if (Ld_0 >= ProfitClose && ProfitClose != 0.0 && TrailingProfit == 0.0) {
      Alert("Достигнут уровень профита = " + DoubleToStr(Ld_0, 2));
      CloseAll();
   }
   if (Ld_0 >= Gd_116 && TrailingProfit != 0.0) {
      if (!Gi_112) Alert(AccountCompany(), " Запуск трейлинга, прибыль = " + DoubleToStr(Ld_0, 2));
      Gi_112 = TRUE;
      Gd_116 = Ld_0;
   }
   if (Gi_112 && Ld_0 <= Gd_116 - TrailingProfit) {
      Gd_116 = ProfitClose;
      Alert(AccountCompany(), " Достигнут уровень отката по трейлингу, прибыль = " + DoubleToStr(Ld_0, 2));
      CloseAll();
      Gi_112 = FALSE;
   }
   if (Ld_0 <= (-LossClose) && LossClose != 0.0) {
      Alert(AccountCompany(), " Достигнут уровень максимального убытка " + DoubleToStr(Ld_0, 2));
      CloseAll();
   }
   ObjectSetText("Balance", StringConcatenate("Balance ", DoubleToStr(AccountBalance(), 2)), 10, "Arial", Gold);
   ObjectSetText("Equity", StringConcatenate("Equity ", DoubleToStr(AccountEquity(), 2)), 10, "Arial", Gold);
   if (AllSymbol) ObjectSetText("Profit", StringConcatenate("Profit All Symbol ", DoubleToStr(Ld_0, 2)), 10, "Arial", Color(Ld_0 > 0.0, 32768, 255));
   else ObjectSetText("Profit", StringConcatenate("Profit ", DoubleToStr(Ld_0, 2)), 10, "Arial", Color(Ld_0 > 0.0, 32768, 255));
   if (Gi_112) {
      ObjectSetText("ProfitClose", StringConcatenate("Profit Close ", DoubleToStr(Gd_116 - TrailingProfit, 2)), 10, "Arial", Gold);
      return;
   }
   ObjectSetText("ProfitClose", StringConcatenate("Profit Close ", DoubleToStr(ProfitClose, 2)), 10, "Arial", Color(TrailingProfit != 0.0, 8421504, 32768));
}

int Color(bool Ai_0, int Ai_4, int Ai_8) {
   if (Ai_0) return (Ai_4);
   return (Ai_8);
}

int CloseAll() {
   int error_4;
   int Li_8;
   int cmd_12;
   string symbol_16;
   int count_28;
   bool is_closed_0 = TRUE;
   while (true) {
      for (int pos_24 = OrdersTotal() - 1; pos_24 >= 0; pos_24--) {
         if (OrderSelect(pos_24, SELECT_BY_POS)) {
            symbol_16 = OrderSymbol();
            if (symbol_16 == Symbol() || AllSymbol) {
               cmd_12 = OrderType();
               if (cmd_12 > OP_SELL) OrderDelete(OrderTicket());
               if (cmd_12 == OP_BUY) {
                  is_closed_0 = OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(MarketInfo(symbol_16, MODE_BID), MarketInfo(symbol_16, MODE_DIGITS)), 3, Blue);
                  if (is_closed_0) Alert(symbol_16, "  Закрыт ордер N ", OrderTicket(), "  прибыль ", OrderProfit(), "     ", TimeToStr(TimeCurrent(), TIME_SECONDS));
               }
               if (cmd_12 == OP_SELL) {
                  is_closed_0 = OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(MarketInfo(symbol_16, MODE_ASK), MarketInfo(symbol_16, MODE_DIGITS)), 3, Red);
                  if (is_closed_0) Alert(symbol_16, "  Закрыт ордер N ", OrderTicket(), "  прибыль ", OrderProfit(), "     ", TimeToStr(TimeCurrent(), TIME_SECONDS));
               }
               if (!is_closed_0) {
                  error_4 = GetLastError();
                  if (error_4 >= 2/* COMMON_ERROR */) {
                     if (error_4 == 129/* INVALID_PRICE */) {
                        Comment("Неправильная цена ", TimeToStr(TimeCurrent(), TIME_MINUTES));
                        Sleep(5000);
                        RefreshRates();
                        continue;
                     }
                     if (error_4 == 146/* TRADE_CONTEXT_BUSY */) {
                        if (!(IsTradeContextBusy())) continue;
                        Sleep(2000);
                        continue;
                     }
                     Comment("Ошибка ", error_4, " закрытия ордера N ", OrderTicket(), "     ", TimeToStr(TimeCurrent(), TIME_MINUTES));
                  }
               }
            }
         }
      }
      count_28 = 0;
      for (pos_24 = 0; pos_24 < OrdersTotal(); pos_24++) {
         if (OrderSelect(pos_24, SELECT_BY_POS)) {
            if (OrderSymbol() == Symbol() || AllSymbol) {
               cmd_12 = OrderType();
               if (cmd_12 == OP_BUY || cmd_12 == OP_SELL) count_28++;
            }
         }
      }
      if (count_28 == 0) break;
      Li_8++;
      if (Li_8 > 10) {
         Alert(symbol_16, "  Не удалось закрыть все сделки, осталось еще ", count_28);
         return (0);
      }
      Sleep(1000);
      RefreshRates();
   }
   return (1);
}