//+----------------------------------------------------------------------------+
//|                                                       e-CloseByProfit.mq4  |
//|                                                    Ким Игорь В. aka KimIV  |
//|                                                       http://www.kimiv.ru  |
//|                                                                            |
//|  22.10.2006  Советник закрывает все позиции при достижении заданного       |
//|              уровня профита пунктах.                                       |
//|  20.06.2008  Исправлена ошибка расчёта профита в пунктах.                  |
//|  18.08.2008  Добавлен параметр StopLoss.                                   |
//+----------------------------------------------------------------------------+
#property copyright "Ким Игорь В. aka KimIV"
#property link      "http://www.kimiv.ru"

//------- Внешние параметры советника ------------------------------------------
extern string _P_Expert = "---------- Параметры советника";
extern bool   CurSymbolOnly   = True;            // Только текущий символ
extern int    StopLoss        = 40;              // Stop
extern int    TakeProfit      = 60;              // Тейк
extern bool   ShowComment     = True;            // Показывать комментарий
extern int    NumberAccount   = 0;               // Номер торгового счёта
extern bool   UseSound        = False;           // Использовать звуковой сигнал
extern string NameFileSound   = "expert.wav";    // Наименование звукового файла
extern int    Slippage        = 3;               // Проскальзывание цены
extern int    NumberOfTry     = 5;               // Количество попыток

//------- Глобальные переменные советника --------------------------------------
color clCloseBuy  = Blue;         // Цвет значка закрытия покупки
color clCloseSell = Red;          // Цвет значка закрытия продажи
int   CurProfit;

//------- Поключение внешних модулей -------------------------------------------
#include <stdlib.mqh>


//+----------------------------------------------------------------------------+
//|  expert initialization function                                            |
//+----------------------------------------------------------------------------+
void init() { if (!IsTesting()) Comment(""); }

//+----------------------------------------------------------------------------+
//|  expert deinitialization function                                          |
//+----------------------------------------------------------------------------+
void deinit() { if (!IsTesting()) Comment(""); }

//+----------------------------------------------------------------------------+
//|  expert start function                                                     |
//+----------------------------------------------------------------------------+
void start() {
  if (!IsTesting()) {
    if (NumberAccount>0 && NumberAccount!=AccountNumber()) {
      Message("ЗАПРЕЩЕНА торговля на счёте "+AccountNumber());
      return;
    } else Comment("");
  }

  CloseByProfit();
  if (ShowComment) {
    Comment(IIFs(CurSymbolOnly, "CurSymbolOnly  ","")
           ,"Текущий профит=",CurProfit," п."
           ,"  Убыток закрытия=",StopLoss," п."
           ,"  Прибыль закрытия=",TakeProfit," п."
           );
  }
}


//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия  : 19.02.2008                                                      |
//|  Описание: Закрытие одной предварительно выбранной позиции                 |
//+----------------------------------------------------------------------------+
void ClosePosBySelect() {
  bool   fc;
  color  clClose;
  double ll, pa, pb, pp;
  int    err, it;

  if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
    for (it=1; it<=NumberOfTry; it++) {
      if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) break;
      while (!IsTradeAllowed()) Sleep(5000);
      RefreshRates();
      pa=MarketInfo(OrderSymbol(), MODE_ASK);
      pb=MarketInfo(OrderSymbol(), MODE_BID);
      if (OrderType()==OP_BUY) {
        pp=pb; clClose=clCloseBuy;
      } else {
        pp=pa; clClose=clCloseSell;
      }
      ll=OrderLots();
      fc=OrderClose(OrderTicket(), ll, pp, Slippage, clClose);
      if (fc) {
        if (UseSound) PlaySound(NameFileSound); break;
      } else {
        err=GetLastError();
        if (err==146) while (IsTradeContextBusy()) Sleep(1000*11);
        Print("Error(",err,") Close ",GetNameOP(OrderType())," ",
              ErrorDescription(err),", try ",it);
        Print(OrderTicket(),"  Ask=",pa,"  Bid=",pb,"  pp=",pp);
        Print("sy=",OrderSymbol(),"  ll=",ll,"  sl=",OrderStopLoss(),
              "  tp=",OrderTakeProfit(),"  mn=",OrderMagicNumber());
        Sleep(1000*5);
      }
    }
  } else Print("Некорректная торговая операция. Close ",GetNameOP(OrderType()));
}

//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 19.02.2008                                                     |
//|  Описание : Закрытие позиций по рыночной цене сначала прибыльных           |
//+----------------------------------------------------------------------------+
void ClosePosFirstProfit() {
  int i, k=OrdersTotal();

  // Сначала закрываем прибыльные позиции
  for (i=k-1; i>=0; i--) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (!CurSymbolOnly || OrderSymbol()==Symbol()) {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
          if (OrderProfit()+OrderSwap()>0) ClosePosBySelect();
        }
      }
    }
  }
  // Потом все остальные
  k=OrdersTotal();
  for (i=k-1; i>=0; i--) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (!CurSymbolOnly || OrderSymbol()==Symbol()) {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) ClosePosBySelect();
      }
    }
  }
}

//+----------------------------------------------------------------------------+
//|  Закрытие всех позиций по профиту.                                         |
//+----------------------------------------------------------------------------+
void CloseByProfit() {
  double pa, pb, pp;
  int    i, k=OrdersTotal(), pr=0;

  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (!CurSymbolOnly || OrderSymbol()==Symbol()) {
        pa=MarketInfo(OrderSymbol(), MODE_ASK);
        pb=MarketInfo(OrderSymbol(), MODE_BID);
        pp=MarketInfo(OrderSymbol(), MODE_POINT);
        if (pp==0) if (StringFind(OrderSymbol(), "JPY")<0) pp=0.0001; else pp=0.01;
        if (OrderType()==OP_BUY) {
          pr+=NormalizeDouble((pb-OrderOpenPrice())/pp, 0);
        }
        if (OrderType()==OP_SELL) {
          pr+=NormalizeDouble((OrderOpenPrice()-pa)/pp, 0);
        }
      }
    }
  }
  CurProfit=pr;
  if (CurProfit<=-StopLoss || CurProfit>=TakeProfit) ClosePosFirstProfit();
}

//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 01.09.2005                                                     |
//|  Описание : Возвращает наименование торговой операции                      |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    op - идентификатор торговой операции                                    |
//+----------------------------------------------------------------------------+
string GetNameOP(int op) {
  switch (op) {
    case OP_BUY      : return("Buy");
    case OP_SELL     : return("Sell");
    case OP_BUYLIMIT : return("BuyLimit");
    case OP_SELLLIMIT: return("SellLimit");
    case OP_BUYSTOP  : return("BuyStop");
    case OP_SELLSTOP : return("SellStop");
    default          : return("Unknown Operation");
  }
}

//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 01.02.2008                                                     |
//|  Описание : Возвращает одно из двух значений взависимости от условия.      |
//+----------------------------------------------------------------------------+
string IIFs(bool condition, string ifTrue, string ifFalse) {
  if (condition) return(ifTrue); else return(ifFalse);
}

//+----------------------------------------------------------------------------+
//|  Вывод сообщения в коммент и в журнал                                      |
//+----------------------------------------------------------------------------+
void Message(string m) {
  Comment(m);
  if (StringLen(m)>0) Print(m);
}
//+----------------------------------------------------------------------------+

