//+------------------------------------------------------------------+
//|                                                        e-TFL.mq4 |
//|                                           Ким Игорь В. aka KimIV |
//|                                              http://www.kimiv.ru |
//|                                                                  |
//|  10.07.2006  Trade From Lines (торговля от линий). FreeWare.     |
//+------------------------------------------------------------------+
#property copyright "Ким Игорь В. aka KimIV"
#property link      "http://www.kimiv.ru"

//------- Внешние параметры советника --------------------------------
extern string _P_Expert = "---------- Параметры советника";
extern string esNameUpLine  = "UPLine";// Наименование верхней линии
extern string esNameDnLine  = "DNLine";// Наименование нижней линии
extern bool   ebBuyFromUp   = False;   // Покупать от верхней линии
extern bool   ebBuyFromDn   = False;   // Покупать от нижней линии
extern bool   ebShowComment = True;    // Показывать комментарии

extern string _P_Trade = "---------- Параметры торговли";
extern double Lots         = 0.1;      // Размер торгуемого лота
extern int    StopLoss     = 15;       // Размер фиксированного стопа
extern int    TakeProfit   = 15;       // Размер фиксированного тэйка
extern int    Slippage     = 3;        // Проскальзывание цены

//------- Глобальные переменные советника ----------------------------
string Name_Expert   = "e-TFL";
bool   UseSound      = True;           // Использовать звуковой сигнал
string NameFileSound = "expert.wav";   // Наименование звукового файла
color  clOpenBuy     = LightBlue;      // Цвет значка открытия покупки
color  clOpenSell    = LightCoral;     // Цвет значка открытия продажи
color  clCloseBuy    = Blue;           // Цвет значка закрытия покупки
color  clCloseSell   = Red;            // Цвет значка закрытия продажи
double gdUpPrice, gdDnPrice;           // Текущие ценовые уровни
double gdPrevUpPrice, gdPrevDnPrice;   // Предыдущие ценовые уровни
double gdPrevAsk, gdPrevBid;           // Предыдущие цены


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

//+------------------------------------------------------------------+
//| expert program start function                                    |
//+------------------------------------------------------------------+
void start() {
  gdUpPrice=0;
  gdDnPrice=0;
  if (idPriceLevel() && gdPrevAsk!=0 && gdPrevBid!=0) OpenPositions();

  if (ebShowComment) {
    string st="";
    if (gdUpPrice==0) st="Не определён верхний ценовой уровень\n";
    else {
      if (ebBuyFromUp) st="Покупка от ";
      else st="Продажа от ";
      st=st+DoubleToStr(gdUpPrice, Digits)+"\n";
    }
    if (gdDnPrice==0) st=st+"Не определён нижний ценовой уровень";
    else {
      if (ebBuyFromDn) st=st+"Покупка от ";
      else st=st+"Продажа от ";
      st=st+DoubleToStr(gdDnPrice, Digits);
    }
    Comment(st);
  }

  if (gdUpPrice>0) gdPrevUpPrice=gdUpPrice;
  if (gdDnPrice>0) gdPrevDnPrice=gdDnPrice;
  gdPrevAsk=Ask;
  gdPrevBid=Bid;
}

//+------------------------------------------------------------------+
//| Идентификация верхнего и нижнего ценовых уровней                 |
//+------------------------------------------------------------------+
bool idPriceLevel() {
  // Верхний ценовой уровень
  if (ObjectFind(esNameUpLine)<0) {
    gdUpPrice=0;
    gdPrevUpPrice=0;
    Message("Не найдена линия "+esNameUpLine);
  } else {
    switch (ObjectType(esNameUpLine)) {
      case OBJ_HLINE: gdUpPrice=ObjectGet(esNameUpLine, OBJPROP_PRICE1); break;
      case OBJ_TREND: gdUpPrice=ObjectGetValueByShift(esNameUpLine, 0); break;
      default: Message("Неверный тип линии "+esNameUpLine); break;
    }
  }

  // Нижний ценовой уровень
  if (ObjectFind(esNameDnLine)<0) {
    gdDnPrice=0;
    gdPrevDnPrice=0;
    Message("Не найдена линия "+esNameDnLine);
  } else {
    switch (ObjectType(esNameDnLine)) {
      case OBJ_HLINE: gdDnPrice=ObjectGet(esNameDnLine, OBJPROP_PRICE1); break;
      case OBJ_TREND: gdDnPrice=ObjectGetValueByShift(esNameDnLine, 0); break;
      default: Message("Неверный тип линии "+esNameDnLine); break;
    }
  }

  if (gdUpPrice<gdPrevBid && gdUpPrice>0) {
    gdUpPrice=0;
    Message("Верхняя линия "+esNameUpLine+" расположена ниже рынка");
  }
  if (gdDnPrice>gdPrevAsk && gdPrevAsk>0) {
    gdDnPrice=0;
    Message("Нижняя линия "+esNameDnLine+" расположена выше рынка");
  }

  if (gdUpPrice!=gdPrevUpPrice || gdDnPrice!=gdPrevDnPrice
   || gdPrevUpPrice==0 || gdPrevDnPrice==0
   || gdUpPrice==0 || gdUpPrice==0) return(False);
  else return(True);
}

//+------------------------------------------------------------------+
//| Открытие позиции                                                 |
//+------------------------------------------------------------------+
void OpenPositions() {
  bool   lbBuy=False, lbSell=False;
  double ldStop=0, ldTake=0;

  if ((Ask>gdPrevAsk && Ask>=gdUpPrice && ebBuyFromUp)
   || (Ask<gdPrevAsk && Ask<=gdDnPrice && ebBuyFromDn)) lbBuy=True;
  if ((Bid>gdPrevBid && Bid>=gdUpPrice && !ebBuyFromUp)
   || (Bid<gdPrevBid && Bid<=gdDnPrice && !ebBuyFromDn)) lbSell=True;

  if (lbBuy) {
    if (ExistPositionByOP(OP_SELL)) CloseAllPositions();
    if (!ExistPositionByOP(OP_BUY)) {
      if (StopLoss!=0) ldStop=Ask-StopLoss*Point;
      if (TakeProfit!=0) ldTake=Ask+TakeProfit*Point;
      OpenPosition(OP_BUY, ldStop, ldTake);
    }
  }
  if (lbSell) {
    if (ExistPositionByOP(OP_BUY)) CloseAllPositions();
    if (!ExistPositionByOP(OP_SELL)) {
      if (StopLoss!=0) ldStop=Bid+StopLoss*Point;
      if (TakeProfit!=0) ldTake=Bid-TakeProfit*Point;
      OpenPosition(OP_SELL, ldStop, ldTake);
    }
  }
}

//+------------------------------------------------------------------+
//| Возвращает флаг существования позиции по операции                |
//+------------------------------------------------------------------+
bool ExistPositionByOP(int op) {
  for (int i=0; i<OrdersTotal(); i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==Symbol() && OrderType()==op) return(True);
    }
  }
  return(False);
}

//+------------------------------------------------------------------+
//| Открытие позиции по текущей цене                                 |
//| Параметры:                                                       |
//|   op     - операция                                              |
//|   ldStop - уровень стоп                                          |
//|   ldTake - уровень тейк                                          |
//+------------------------------------------------------------------+
void OpenPosition(int op, double ldStop, double ldTake) {
  color  clOpen;
  double pp;
  string lsComm=GetCommentForOrder();

  if (op==OP_BUY) {
    clOpen=clOpenBuy;
    pp=Ask;
  } else {
    clOpen=clOpenSell;
    pp=Bid;
  }
  OrderSend(Symbol(),op,Lots,pp,Slippage,ldStop,ldTake,lsComm,0,0,clOpen);
  if (UseSound) PlaySound(NameFileSound);
}

//+------------------------------------------------------------------+
//| Генерирует и возвращает строку коментария для ордера или позиции |
//+------------------------------------------------------------------+
string GetCommentForOrder() {
  return(Name_Expert+" "+GetNameTF(Period()));
}

//+------------------------------------------------------------------+
//| Возвращает наименование таймфрейма                               |
//+------------------------------------------------------------------+
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");
	}
}

//+------------------------------------------------------------------+
//| Закрытие всех позиций по рыночной цене                           |
//+------------------------------------------------------------------+
void CloseAllPositions() {
  for (int i=OrdersTotal()-1; i>=0; i--) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==Symbol()) {
        if (OrderType()==OP_BUY) {
          OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clCloseBuy);
        }
        if (OrderType()==OP_SELL) {
          OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clCloseSell);
        }
      }
    }
  }
}

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

