//+------------------------------------------------------------------+
//|                                            Woodies the Robot.mq4 |
//|                                                      Янин Михаил |
//|                                                www.yan_in.com.ua |
//+------------------------------------------------------------------+
#property copyright "Янин Михаил"
#property link      "www.yan_in.com.ua"

extern string _____________________________="Общие Настройки";
extern int TrendCCI_Period = 50;
extern int EntryCCI_Period = 14;
extern int TurboCCI_Period = 6;   
extern int TP=150;
extern int SL=50;
extern bool FixedLot=true;
extern double Риск=25;
extern string _______________1_____________="Паттерн ZLR";
extern bool ОткрыватьсяПоZLR=true;
extern bool ZLR_ОткрыватьсяКогдаУжеЕстьПозы=true;
extern bool ZLR_ИспользоватьДляЗакрытия=false;
extern int MagicZLR=3832293;
extern double ZLR_lot=0.1;
extern double ZLR_Доливка=0.1;

extern int ЗонаРазворота=50;
int ЗавалЗаZL=5;
int БаровДляРазворота=5;
int ВеличинаОтскока=3;
extern string _______________2_____________="Паттерн Пересечение ZR";
extern bool ОткрыватьсяПоZR=true;
extern bool ZR_ОткрыватьсяКогдаУжеЕстьПозы=true;
extern bool ZR_ИспользоватьДляЗакрытия=false;
extern int MagicZR=356493;
extern double ZR_lot=0.1;
extern double ZR_Доливка=0.1;
int БаровДляПересечения=5;
extern string _______________3_____________="Паттерн Пересечение LT";
extern bool ОткрыватьсяПоLT=true;
extern bool LT_ОткрыватьсяКогдаУжеЕстьПозы=true;
extern bool LT_ИспользоватьДляЗакрытия=false;
extern int MagicLT=356493;
extern double LT_lot=0.1;
extern double LT_Доливка=0.1;
extern int Баров_ДоСигнала=20;
extern double Уровень1Вершины=100;
extern double ЛинияДо=50;
extern double СигналДо=50;
extern string _______________4_____________="Паттерн Крюк"; 
extern bool ОткрыватьсяПоКрюку=true;
extern bool Кр_ОткрыватьсяКогдаУжеЕстьПозы=true;
extern bool Кр_ИспользоватьДляЗакрытия=false;
extern int MagicКр=3564933;
extern double ЗонаКрюка=150;
extern double Кр_lot=0.1;
extern double Кр_Доливка=0.1;

extern string _______________5_____________="Параметры трэйлинга";
extern bool Тралить=true;
extern bool   TSProfitOnly = True;     // Тралить только профит
extern int    TStop.Buy    = 50;       // Размер трала в пунктах для покупок
extern int    TStop.Sell   = 50;       // Размер трала в пунктах для продаж
extern int    TrailingStep = 3;        // Шаг трала в пунктах
extern bool   UseSound     = True;          // Использовать звуковой сигнал
extern string SoundSuccess = "tick.wav";  // Звук успеха
extern string SoundError   = "timeout.wav"; // Звук ошибки
extern int    NumberOfTry  = 3;             // Количество торговых попыток

color  clModifyBuy  = Aqua;            // Цвет значка модификации покупки
color  clModifySell = Tomato;          // Цвет значка модификации продажи
int SleepOk = 2000;
int SleepErr = 6000;   
#include <stderror.mqh>
#include <stdlib.mqh>
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
double l,t,s;
 if(Тралить) SimpleTrailing(Symbol(),-1, -1) ;
 
 //Обрабатываем Крюк сигнал
/////////////////////////////////////////////////////////////   
  if(Кр_ОткрыватьсяКогдаУжеЕстьПозы||((!Кр_ОткрыватьсяКогдаУжеЕстьПозы)&&ВсегоОрдеров(Symbol())==0)){
  l=Кр_lot;
  if(Кр_ОткрыватьсяКогдаУжеЕстьПозы&&ВсегоОрдеров(Symbol())!=0) l=Кр_Доливка;
    
  if(Кр_sig(1)==1&&ОткрыватьсяПоКрюку&&(GetOrders(Symbol(),OP_BUY,MagicКр)==0)&&(GetOrders(Symbol(),OP_SELL,MagicКр)==0))
   {
   t=0;
   if(TP!=0) t=Ask+TP*Point;
   s=0;
   if(SL!=0) s=Ask-SL*Point;
   if(!FixedLot) l=GetLot(SL);
   
   OpenOrders(OP_BUY,t,s,Ask,l,MagicКр,"Кр покупка");
   }
  if(Кр_sig(1)==-1&&ОткрыватьсяПоКрюку&&(GetOrders(Symbol(),OP_BUY,MagicКр)==0)&&(GetOrders(Symbol(),OP_SELL,MagicКр)==0))
   {
  t=0;
   if(TP!=0) t=Bid-TP*Point;
   s=0;
   if(SL!=0) s=Bid+SL*Point;
   
   if(!FixedLot) l=GetLot(SL);
   OpenOrders(OP_SELL,t,s,Bid,l,MagicКр,"Кр продажа");
   } 
   } 
 
 
///////////////////////////////////////////////////////////// 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  
 //Обрабатываем ZLR сигнал
  
  if(ZLR_ОткрыватьсяКогдаУжеЕстьПозы||((!ZLR_ОткрыватьсяКогдаУжеЕстьПозы)&&ВсегоОрдеров(Symbol())==0)){
  l=ZLR_lot;
  if(ZLR_ОткрыватьсяКогдаУжеЕстьПозы&&ВсегоОрдеров(Symbol())!=0) l=ZLR_Доливка;
    
  if(ZLR_sig(1)==1&&ОткрыватьсяПоZLR&&(GetOrders(Symbol(),OP_BUY,MagicZLR)==0)&&(GetOrders(Symbol(),OP_SELL,MagicZLR)==0))
   {
   t=0;
   if(TP!=0) t=Ask+TP*Point;
   s=0;
   if(SL!=0) s=Ask-SL*Point;
   if(!FixedLot) l=GetLot(SL);
   
   OpenOrders(OP_BUY,t,s,Ask,l,MagicZLR,"ZLR покупка");
   }
  if(ZLR_sig(1)==-1&&ОткрыватьсяПоZLR&&(GetOrders(Symbol(),OP_BUY,MagicZLR)==0)&&(GetOrders(Symbol(),OP_SELL,MagicZLR)==0))
   {
  t=0;
   if(TP!=0) t=Bid-TP*Point;
   s=0;
   if(SL!=0) s=Bid+SL*Point;
   
   if(!FixedLot) l=GetLot(SL);
   OpenOrders(OP_SELL,t,s,Bid,l,MagicZLR,"ZLR продажа");
   } 
   }
 
 
//Обрабатываем ZR сигнал
  if(ZR_ОткрыватьсяКогдаУжеЕстьПозы||((!ZR_ОткрыватьсяКогдаУжеЕстьПозы)&&ВсегоОрдеров(Symbol())==0)){
  l=ZR_lot;
  if(ZR_ОткрыватьсяКогдаУжеЕстьПозы&&ВсегоОрдеров(Symbol())!=0) l=ZR_Доливка;
  
  
  if(ZR_sig(1)==1&&ОткрыватьсяПоZR&&(GetOrders(Symbol(),OP_BUY,MagicZR)==0)&&(GetOrders(Symbol(),OP_SELL,MagicZR)==0))
   {
   t=0;
   if(TP!=0) t=Ask+TP*Point;
   s=0;
   if(SL!=0) s=Ask-SL*Point;
   if(!FixedLot) l=GetLot(SL);
   OpenOrders(OP_BUY,t,s,Ask,l,MagicZR,"ZR покупка");
   }
  if(ZR_sig(1)==-1&&ОткрыватьсяПоZR&&(GetOrders(Symbol(),OP_BUY,MagicZR)==0)&&(GetOrders(Symbol(),OP_SELL,MagicZR)==0))
   {
     t=0;
   if(TP!=0) t=Bid-TP*Point;
   s=0;
   if(SL!=0) s=Bid+SL*Point;
   if(!FixedLot) l=GetLot(SL);
   OpenOrders(OP_SELL,t,s,Bid,l,MagicZR,"ZR продажа");
   } 
   }   

//Обрабатываем LT сигнал
  if(LT_ОткрыватьсяКогдаУжеЕстьПозы||((!LT_ОткрыватьсяКогдаУжеЕстьПозы)&&ВсегоОрдеров(Symbol())==0)){
  l=LT_lot;
  if(LT_ОткрыватьсяКогдаУжеЕстьПозы&&ВсегоОрдеров(Symbol())!=0) l=LT_Доливка;
  
  
  if(LT_sig(1)==1&&ОткрыватьсяПоLT&&(GetOrders(Symbol(),OP_BUY,MagicLT)==0)&&(GetOrders(Symbol(),OP_SELL,MagicLT)==0))
   {
   t=0;
   if(TP!=0) t=Ask+TP*Point;
   s=0;
   if(SL!=0) s=Ask-SL*Point;
   if(!FixedLot) l=GetLot(SL);
   OpenOrders(OP_BUY,t,s,Ask,l,MagicLT,"LT покупка");
   }
  if(LT_sig(1)==-1&&ОткрыватьсяПоLT&&(GetOrders(Symbol(),OP_BUY,MagicLT)==0)&&(GetOrders(Symbol(),OP_SELL,MagicLT)==0))
   {
     t=0;
   if(TP!=0) t=Bid-TP*Point;
   s=0;
   if(SL!=0) s=Bid+SL*Point;
  if(!FixedLot) l=GetLot(SL);
   OpenOrders(OP_SELL,t,s,Bid,l,MagicLT,"LT продажа");
   } 
   } 
//----

//Ищем условия для выхода

 if(ZLR_ИспользоватьДляЗакрытия)
 {
 if(ZLR_sig(1)==1) CloseOrders(OP_SELL);
 if(ZLR_sig(1)==-1) CloseOrders(OP_BUY);
 }

 if(ZR_ИспользоватьДляЗакрытия)
 {
 if(ZR_sig(1)==1) CloseOrders(OP_SELL);
 if(ZR_sig(1)==-1) CloseOrders(OP_BUY);
 }

 if(LT_ИспользоватьДляЗакрытия)
 {
 if(LT_sig(1)==1) CloseOrders(OP_SELL);
 if(LT_sig(1)==-1) CloseOrders(OP_BUY);
 }




   return(0);
  }

int Индюк(int shift,int buff)
   {
   return(iCustom(Symbol(),0,"Woodie_Trend",TrendCCI_Period,EntryCCI_Period,TurboCCI_Period,ЗонаРазворота,ЗавалЗаZL,БаровДляРазворота,ВеличинаОтскока,БаровДляПересечения,Баров_ДоСигнала,Уровень1Вершины,ЛинияДо,СигналДо,ЗонаКрюка,5,buff,buff,shift));
   }
int ZLR_sig(int shift)
   {
   return(Индюк(shift,1));
   }
int ZR_sig(int shift)
   {
   return(Индюк(shift,2));
   }
int LT_sig(int shift)
   {
   return(Индюк(shift,3));
   }
int Кр_sig(int shift)
   {
   return(Индюк(shift,4));
   }
//+------------------------------------------------------------------+
int OpenOrders(int type,double tp,double sl,double pr,double Lot,int Magic,string comm)
{ 
tp=NormalizeDouble(tp,Digits);
sl=NormalizeDouble(sl,Digits);
pr=NormalizeDouble(pr,Digits);
  if (type == OP_BUY) {
   RefreshRates();
   int res =OrderSend(Symbol(),OP_BUY,Lot,Ask,5,sl,tp,comm,Magic,0,Green);
   if (res >= 0) {
   Sleep(SleepOk);
   return (res); } 	
   int code = GetLastError();
   Print("Error setting Buy order: ", ErrorDescription(code), " (", code, ")");
   Sleep(SleepErr);
   return (-1);
   }
 
   if (type == OP_SELL) {
   RefreshRates();

   res =OrderSend(Symbol(),OP_SELL,Lot,Bid,5,sl,tp,comm,Magic,0,Red);
   if (res >= 0) {
    Sleep(SleepOk);
   return (res); } 	
  code = GetLastError();
  Print("Error setting SELL order: ", ErrorDescription(code), " (", code, ")");
  Sleep(SleepErr);
  return (-1);
  }
  
  return(0);
  
}
int GetOrders(string symbol, int type,int Magic) {
  int res = 0;
  int cnt = OrdersTotal();
  for (int i=0; i < cnt; i++) {
    OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
    if (OrderSymbol() != symbol) continue;
    if (OrderMagicNumber() != Magic) continue;
    if(OrderType()==type) res++;
   }
  return(res);
}
int ВсегоОрдеров(string symbol) {
  int res = 0;
  int cnt = OrdersTotal();
  for (int i=0; i < cnt; i++) {
    OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
    if (OrderSymbol() != symbol) continue;
    if ((OrderMagicNumber() != MagicZLR)&&(OrderMagicNumber() != MagicZR)&&(OrderMagicNumber() != MagicLT)) continue;
    res++;
   }
  return(res);
}



void SimpleTrailing(string sy="", int op=-1, int mn=-1) {
  double po, pp;
  int    i, k=OrdersTotal();

  if (sy=="0") sy=Symbol();
  for (i=0; i<k; i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if ((OrderSymbol()==sy || sy=="") && (op<0 || OrderType()==op)) {
        po=MarketInfo(OrderSymbol(), MODE_POINT);
        if ((OrderMagicNumber() != MagicZLR)&&(OrderMagicNumber() != MagicZR)&&(OrderMagicNumber() != MagicLT)&&(OrderMagicNumber() != MagicКр)) continue;
          if (OrderType()==OP_BUY) {
            pp=MarketInfo(OrderSymbol(), MODE_BID);
            if (!TSProfitOnly || pp-OrderOpenPrice()>TStop.Buy*po) {
              if (OrderStopLoss()<pp-(TStop.Buy+TrailingStep-1)*po) {
                ModifyOrder(-1, pp-TStop.Buy*po, -1);
              }
            }
          
          
            }
           if (OrderType()==OP_SELL) {
           pp=MarketInfo(OrderSymbol(), MODE_ASK);
           if (!TSProfitOnly || OrderOpenPrice()-pp>TStop.Sell*po) {
              if (OrderStopLoss()>pp+(TStop.Sell+TrailingStep-1)*po || OrderStopLoss()==0) {
                ModifyOrder(-1, pp+TStop.Sell*po, -1);
            }
          }
        }
      }
    }
  }
}

void ModifyOrder(double pp=-1, double sl=0, double tp=0, datetime ex=0) {
  bool   fm;
  color  cl=IIFc(OrderType()==OP_BUY
              || OrderType()==OP_BUYLIMIT
              || OrderType()==OP_BUYSTOP, clModifyBuy, clModifySell);
  double op, pa, pb, os, ot;
  int    dg=MarketInfo(OrderSymbol(), MODE_DIGITS), er, it;

  if (pp<=0) pp=OrderOpenPrice();
  if (sl<0 ) sl=OrderStopLoss();
  if (tp<0 ) tp=OrderTakeProfit();
  
  pp=NormalizeDouble(pp, dg);
  sl=NormalizeDouble(sl, dg);
  tp=NormalizeDouble(tp, dg);
  op=NormalizeDouble(OrderOpenPrice() , dg);
  os=NormalizeDouble(OrderStopLoss()  , dg);
  ot=NormalizeDouble(OrderTakeProfit(), dg);

  if (pp!=op || sl!=os || tp!=ot) {
    for (it=1; it<=NumberOfTry; it++) {
      if (!IsTesting() && (!IsExpertEnabled() || IsStopped())) break;
      while (!IsTradeAllowed()) Sleep(5000);
      RefreshRates();
      fm=OrderModify(OrderTicket(), pp, sl, tp, ex, cl);
      if (fm) {
        if (UseSound) PlaySound(SoundSuccess); break;
      } else {
        er=GetLastError();
        if (UseSound) PlaySound(SoundError);
        pa=MarketInfo(OrderSymbol(), MODE_ASK);
        pb=MarketInfo(OrderSymbol(), MODE_BID);
        Print("Error(",er,") modifying order: ",ErrorDescription(er),", try ",it);
        Print("Ask=",pa,"  Bid=",pb,"  sy=",OrderSymbol(),
              "  op="+GetNameOP(OrderType()),"  pp=",pp,"  sl=",sl,"  tp=",tp);
        Sleep(1000*10);
      }
    }
  }
}
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");
  }
}


color IIFc(bool condition, color ifTrue, color ifFalse) {
  if (condition) return(ifTrue); else return(ifFalse);
}

int CloseOrders(int type) {

  int cnt = OrdersTotal();
  for (int i=cnt-1; i >= 0; i--) {
    if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;

    if (OrderSymbol() != Symbol()) continue;
    if ((OrderMagicNumber() == MagicZLR)||(OrderMagicNumber() == MagicZR)||(OrderMagicNumber() == MagicLT)||(OrderMagicNumber() == MagicКр)) {
    
   
    int type2 = OrderType();
    if (type != type2) continue;
    
    if (type == OP_BUY) {
      RefreshRates();
      CloseOrder(OrderTicket(), OrderLots(), Bid);
    }
          
    if (type == OP_SELL) {
      RefreshRates();
      CloseOrder(OrderTicket(), OrderLots(), Ask);
    }}
  }
  
  return(0);
}

bool CloseOrder(int ticket, double lot, double price) 
{
  if (!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) return(false);
  
  int dig = MarketInfo(OrderSymbol(), MODE_DIGITS);
  string _lot = DoubleToStr(lot, 2);
  string _price = DoubleToStr(price, dig);

  Print("CloseOrder ", ticket, ", ", _lot, ", ", _price, ", ", 5);
  
  bool res = OrderClose(ticket, lot, price, 5);
  if (res) {
    Sleep(SleepOk);
    return (res);
  } 	
   	
  int code = GetLastError();
  Print("CloseOrder failed: ", ErrorDescription(code), " (", code, ")");
  Sleep(SleepErr);
  return (false);
}

double GetLot(int s)
{

  double Счет=AccountEquity();
  double ЦенаПипа=MarketInfo(Symbol(),MODE_TICKVALUE);
  double d;
  if(MarketInfo(Symbol(),MODE_MINLOT)==0.01) d=2;
  if(MarketInfo(Symbol(),MODE_MINLOT)==0.1) d=1;
  if(MarketInfo(Symbol(),MODE_MINLOT)==1) d=0;
  
  double ДопустимаяПросадка=Счет*Риск/100;
  double ДопустимыйЛот=NormalizeDouble(ДопустимаяПросадка/(s*ЦенаПипа),d);
  return(ДопустимыйЛот);
}




