//+----------------------------------------------------------------------------+
//|                                                              HandOpen.mq4  |
//|                                                    Ким Игорь В. aka KimIV  |
//|                                                       http://www.kimiv.ru  |
//|                                                                            |
//|  20.07.2006  Скрипт открывает позицию с рынка.                             |
//|  14.06.2007  Немного модифицировал для увеличения надёжности работы.       |
//+----------------------------------------------------------------------------+
#property copyright "Ким Игорь В. aka KimIV"
#property link      "http://www.kimiv.ru"
#property show_inputs

//------- Внешние параметры скрипта -------------------------------------------+
extern string _P_Trade = "---------- Параметры торговли";
extern int    MagicNumber     = 20070614;
extern bool   Buy             = True;       // True-купить, False-продать
extern double Lots            = 0.1;        // Размер лота
extern int    StopLoss        = 40;         // Размер стопа в пунктах
extern int    TakeProfit      = 60;         // Размер тейка в пунктах
extern int    Slippage        = 3;          // Проскальзывание цены
extern int    NumberOfTry     = 3;          // Количество торговых попыток
extern int    PauseAfterError = 15;         // Пауза в секундах между попытками

//------- Глобальные переменные скрипта ---------------------------------------+
bool   UseSound      = True;         // Использовать звуковой сигнал
string NameFileSound = "expert.wav"; // Наименование звукового файла
color  clOpenBuy     = LightBlue;    // Цвет ордера BuyStop
color  clOpenSell    = LightCoral;   // Цвет ордера SellStop

//------- Подключение внешних модулей ------------------------------------------
#include <stdlib.mqh>        // Стандартная библиотека МТ4


//+----------------------------------------------------------------------------+
//|  script program start function                                             |
//+----------------------------------------------------------------------------+
void start() {
  double sl=0, tp=0;

  if (Buy) {
    if (StopLoss  >0) sl=Ask-StopLoss*Point;   else sl=0;
    if (TakeProfit>0) tp=Ask+TakeProfit*Point; else tp=0;
    OpenPosition(OP_BUY, sl, tp, MagicNumber);
  } else {
    if (StopLoss  >0) sl=Bid+StopLoss*Point;   else sl=0;
    if (TakeProfit>0) tp=Bid-TakeProfit*Point; else tp=0;
    OpenPosition(OP_SELL, sl, tp, MagicNumber);
  }
}


//+----------------------------------------------------------------------------+
//|  Возвращает флаг существования позиций                                     |
//|  Параметры:                                                                |
//|    sym - наименование инструмента  ("" - текущий символ)                   |
//|    op  - операция                  (-1 - любая позиция)                    |
//|    mn  - MagicNumber               (-1 - любой магик)                      |
//+----------------------------------------------------------------------------+
bool ExistPositions(string sym="", int op=-1, int mn=-1) {
  int i, k=OrdersTotal();

  if (sym=="") sym=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==sym) {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
          if (op<0 || OrderType()==op) {
            if (mn<0 || OrderMagicNumber()==mn) return(True);
          }
        }
      }
    }
  }
  return(False);
}

//+----------------------------------------------------------------------------+
//|  Возвращает наименование торговой операции                                 |
//|  Параметры:                                                                |
//|    op - идентификатор торговой операции                                    |
//+----------------------------------------------------------------------------+
string GetNameOP(int op) {
	switch (op) {
		case OP_BUY      : return("Buy");
		case OP_SELL     : return("Sell");
		case OP_BUYLIMIT : return("Buy Limit");
		case OP_SELLLIMIT: return("Sell Limit");
		case OP_BUYSTOP  : return("Buy Stop");
		case OP_SELLSTOP : return("Sell Stop");
		default          : return("Unknown Operation");
	}
}

//+----------------------------------------------------------------------------+
//|  Возвращает наименование таймфрейма                                        |
//+----------------------------------------------------------------------------+
string GetNameTF(int TimeFrame) {
	switch (TimeFrame) {
		case PERIOD_M1:  return("M1");
		case PERIOD_M5:  return("M5");
		case PERIOD_M15: return("M15");
		case PERIOD_M30: return("M30");
		case PERIOD_H1:  return("H1");
		case PERIOD_H4:  return("H4");
		case PERIOD_D1:  return("Daily");
		case PERIOD_W1:  return("Weekly");
		case PERIOD_MN1: return("Monthly");
		default:		     return("UnknownPeriod");
	}
}

//+----------------------------------------------------------------------------+
//|  Возвращает размер лота                                                    |
//+----------------------------------------------------------------------------+
double GetSizeLot() {
  return(Lots);
}

//+----------------------------------------------------------------------------+
//|  Открытие позиции                                                          |
//|  Параметры:                                                                |
//|    op - операция                                                           |
//|    sl - уровень стоп                                                       |
//|    tp - уровень тейк                                                       |
//|    mn - MagicNumber                                                        |
//+----------------------------------------------------------------------------+
void OpenPosition(int op, double sl=0, double tp=0, int mn=0) {
  color  clOpen;
  double ll, pp;
  int    err, it, ticket;
  string lsComm=WindowExpertName()+" "+GetNameTF(Period());

  if (op==OP_BUY) clOpen=clOpenBuy; else clOpen=clOpenSell;
  ll=GetSizeLot();
  for (it=1; it<=NumberOfTry; it++) {
    if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) break;
    while (!IsTradeAllowed()) Sleep(5000);
    RefreshRates();
    if (op==OP_BUY) pp=Ask; else pp=Bid;
    pp=NormalizeDouble(pp, Digits);
    ticket=OrderSend(Symbol(),op,ll,pp,Slippage,sl,tp,lsComm,mn,0,clOpen);
    if (ticket>0) {
      if (UseSound) PlaySound(NameFileSound); break;
    } else {
      err=GetLastError();
      if (err==128 || err==142 || err==143 || err==144) {
        Sleep(1000*PauseAfterError);
        if (ExistPositions(Symbol(), op, mn)) {
          if (UseSound) PlaySound(NameFileSound); break;
        }
        Print("Error(",err,") opening position: ",ErrorDescription(err),", try ",it);
        continue;
      }
      if (err==146) while (IsTradeContextBusy()) Sleep(1000*PauseAfterError);
      Print("Error(",err,") opening position: ",ErrorDescription(err),", try ",it);
      Print("Ask=",Ask,"  Bid=",Bid,"  ll=",ll,"  op=",GetNameOP(op),
            "  pp=",pp,"  sl=",sl,"  tp=",tp,"  mn=",mn);
      if (err==2 || err==64 || err==65 || err==4110 || err==4111) break;
      Sleep(1000*PauseAfterError);
    }
  }
}
//+----------------------------------------------------------------------------+

