//+----------------------------------------------------------------------------+
//|                                                                 e-OCO.mq4  |
//|                                                                            |
//|  Идея      : Хуан Занозин                                                  |
//|              http://community.finlist.org/showthread.php?t=2273            |
//|  Реализация: Ким Игорь В. aka KimIV, http://www.kimiv.ru                   |
//|                                                                            |
//|  12.07.2007  One Cancel Others - Один отменяет другие.                     |
//|              Советник следит за появлением позиции.                        |
//|              Как только позиция появляется, удаляет все ордера.            |
//|              Позиция может появиться либо после входа по рынку,            |
//|              либо после срабатывания отложенного ордера.                   |
//+----------------------------------------------------------------------------+
#property copyright "Хуан Занозин & KimIV"
#property link      "http://www.kimiv.ru"

extern string _P_Expert = "---------- Параметры советника";
extern int    NumberAccount   = 0;               // Номер торгового счёта
extern bool   UseSound        = False;           // Использовать звуковой сигнал
extern string NameFileSound   = "expert.wav";    // Наименование звукового файла
extern int    Slippage        = 3;               // Проскальзывание цены
extern int    NumberOfTry     = 5;               // Количество попыток
extern int    PauseAfterError = 75;              // Пауза после ошибки в секундах

//------- Глобальные переменные советника --------------------------------------
color clDelete = Yellow;               // Цвет значка удаления ордера

//------- Подключение внешних модулей ------------------------------------------
#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 (NumberAccount>0 && NumberAccount!=AccountNumber()) {
    Comment("Торговля на счёте: "+AccountNumber()+" ЗАПРЕЩЕНА!");
    return;
  }

  if (ExistPositions()) DeleteOrders();
}


//+----------------------------------------------------------------------------+
//|  Удаление ордеров                                                          |
//|  Параметры:                                                                |
//|    sy - наименование инструмента   ("" - текущий символ)                   |
//|    op - операция                   (-1 - любой ордер)                      |
//|    mn - MagicNumber                (-1 - любой магик)                      |
//+----------------------------------------------------------------------------+
void DeleteOrders(string sy="", int op=-1, int mn=-1) {
  bool fd;
  int  err, i, it, k=OrdersTotal(), ot;

  if (sy=="") sy=Symbol();
  for (i=k-1; i>=0; i--) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      ot=OrderType();
      if (ot==OP_BUYLIMIT || ot==OP_BUYSTOP || ot==OP_SELLLIMIT || ot==OP_SELLSTOP) {
        if (OrderSymbol()==sy && (op<0 || ot==op)) {
          if (mn<0 || OrderMagicNumber()==mn) {
            for (it=1; it<=NumberOfTry; it++) {
              if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) break;
              while (!IsTradeAllowed()) Sleep(5000);
              fd=OrderDelete(OrderTicket(), clDelete);
              if (fd) {
                if (UseSound) PlaySound(NameFileSound); break;
              } else {
                err=GetLastError();
                Print("Error(",err,") delete order ",GetNameOP(ot),": ",ErrorDescription(err),", try ",it);
                Sleep(1000*PauseAfterError);
              }
            }
          }
        }
      }
    }
  }
}

//+----------------------------------------------------------------------------+
//|  Возвращает флаг существования позиций                                     |
//|  Параметры:                                                                |
//|    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");
	}
}
//+----------------------------------------------------------------------------+

