//+------------------------------------------------------------------+
//|                                                    Larry_Wil.mq4 |
//+------------------------------------------------------------------+

extern int Wiliams_Period=14;
extern double Williams_Middle_Line=-50;
extern int Map_1=PERIOD_M15;
extern int Map_2=PERIOD_H1; //for mode 1 put this input to 0


extern bool Enable_Pos1=True;
extern bool EnableMM1=false;
extern double Risk1=20; //in percents %
extern double Overide_Lots1=0.30;
extern int TP1=30;
extern int SL1=30;
extern int TS1=15;
extern int Break_Even_Point1=15;  // when the position has "Break_Even_Point1" (15) pips in profit will move the stop at "Break_Even_Stop1" (1) pips profit.
extern int Break_Even_Stop1=1;


extern bool Enable_Pos2=True;
extern bool EnableMM2=false;
extern double Risk2=10; //in percents %
extern double Overide_Lots2=0.20;
extern int TP2=60;
extern int SL2=60;
extern int TS2=30;
extern int Break_Even_Point2=15;  // when the position has "Break_Even_Point2" (15) pips in profit will move the stop at "Break_Even_Stop2" (1) pips profit.
extern int Break_Even_Stop2=1;

extern bool Enable_Pos3=True;
extern double Lots3=0.10;
extern int Break_Even_Point3=15;  // when the position has "Break_Even_Point3" (15) pips in profit will move the stop at "Break_Even_Stop3" (1) pips profit.
extern int Break_Even_Stop3=1;


extern int Trade_Bar=1;
extern bool DisableTrade=false;
extern bool TradeOnSunday=false;
extern int Magic_Number=123;
extern int Slippage=3;

string com1="Larry Wiliams Percent EA 1";
string com2="Larry Wiliams Percent EA 2";
string com3="Larry Wiliams Percent EA 3";

datetime last_t=0;
int init(){return(0);}
int deinit(){return(0);}
int start()
  {
   double Magic_Number1=Magic_Number+1;
   double Magic_Number2=Magic_Number+2;
   double Magic_Number3=Magic_Number+3;
   double ask=0,bid=0;
   int i=0;
   double wil1=iWPR(Symbol(),Map_1,Wiliams_Period,Trade_Bar);
   double wil1_1=iWPR(Symbol(),Map_1,Wiliams_Period,Trade_Bar+1);
   if (Map_2 >0) {
      double wil2=iWPR(Symbol(),Map_2,Wiliams_Period,Trade_Bar);
      double wil2_1=iWPR(Symbol(),Map_2,Wiliams_Period,Trade_Bar+1);
   }
   
   if (EnableMM1){
      double Lots1=FRisk_MM(0.1,SL1,Risk1/100);
   }else{
      Lots1=Overide_Lots1;
   }
   if (EnableMM2){
      double Lots2=FRisk_MM(0.1,SL2,Risk2/100);
   }else{
      Lots2=Overide_Lots2;
   }   
   if (TotalOrders(Magic_Number1)+TotalOrders(Magic_Number2)+TotalOrders(Magic_Number3)==0 && !DisableTrade && Time[0]>last_t){   
      if (wil1>Williams_Middle_Line && wil1_1<=Williams_Middle_Line && 
         (TradeOnSunday || (!TradeOnSunday && TimeDayOfWeek(TimeCurrent())!=0)) && 
         (Map_2==0 || (Map_2>0 && wil2>Williams_Middle_Line))){
         last_t=Time[0];
         RefreshRates();
         ask=MarketInfo(Symbol(),MODE_ASK);
         if (Enable_Pos1){
         if (TP1==0){
            double TP1_0=0;            
         }else{
            TP1_0=NormalizeDouble(ask+TP1*Point,Digits);
         }
         if (OrderSend(Symbol(),OP_BUY,Lots1,NormalizeDouble(ask,Digits),Slippage,NormalizeDouble(ask-SL1*Point,Digits),TP1_0,com1,Magic_Number1,0,Blue)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("1 Buy Error :"+error(i)+" at "+Symbol()+" "+Period());                                                                                         
         }
         }
         if (Enable_Pos2){
         if (TP2==0){
            double TP2_0=0;            
         }else{
            TP2_0=NormalizeDouble(ask+TP2*Point,Digits);
         }
         if (OrderSend(Symbol(),OP_BUY,Lots2,NormalizeDouble(ask,Digits),Slippage,NormalizeDouble(ask-SL2*Point,Digits),TP2_0,com2,Magic_Number2,0,Blue)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("2 Buy Error :"+error(i)+" at "+Symbol()+" "+Period());                                                
         }
         }
         if (Enable_Pos3)
         if (OrderSend(Symbol(),OP_BUY,Lots3,NormalizeDouble(ask,Digits),Slippage,0,0,com3,Magic_Number3,0,Blue)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("3 Buy Error :"+error(i)+" at "+Symbol()+" "+Period());                                               
         }              
      }    
      if (wil1<Williams_Middle_Line && wil1_1>=Williams_Middle_Line && 
         (TradeOnSunday || (!TradeOnSunday && TimeDayOfWeek(TimeCurrent())!=0)) && 
         (Map_2==0 || (Map_2>0 && wil2<Williams_Middle_Line))){
         last_t=Time[0];
         RefreshRates();
         bid=MarketInfo(Symbol(),MODE_BID);         
         if (Enable_Pos1){
         if (TP1==0){
            TP1_0=0;            
         }else{
            TP1_0=NormalizeDouble(Bid-TP1*Point,Digits);
         }         
         if (OrderSend(Symbol(),OP_SELL,Lots1,NormalizeDouble(bid,Digits),Slippage,NormalizeDouble(bid+SL1*Point,Digits),TP1_0,com1,Magic_Number1,0,Red)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("1 Sell Error :"+error(i)+" at "+Symbol()+" "+Period());                                                                                         
         }
         }
         if (Enable_Pos2){
         if (TP2==0){
            TP2_0=0;            
         }else{
            TP2_0=NormalizeDouble(Bid-TP2*Point,Digits);
         }         
         if (OrderSend(Symbol(),OP_SELL,Lots2,NormalizeDouble(bid,Digits),Slippage,NormalizeDouble(bid+SL2*Point,Digits),TP2_0,com2,Magic_Number2,0,Red)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("2 Sell Error :"+error(i)+" at "+Symbol()+" "+Period());                                                
         }
         }
         if (Enable_Pos3)
         if (OrderSend(Symbol(),OP_SELL,Lots3,NormalizeDouble(bid,Digits),Slippage,0,0,com3,Magic_Number3,0,Red)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("3 Sell Error :"+error(i)+" at "+Symbol()+" "+Period());                                               
         }       
      }            
   }
   
   if (TotalOrders(Magic_Number3)>0){
      for (int j=0;j<OrdersTotal();j++){
         OrderSelect(j,SELECT_BY_POS);
         if (OrderMagicNumber()==Magic_Number3) break;
      }
      if (OrderType()==OP_SELL && 
          ((wil1>Williams_Middle_Line && wil1_1<=Williams_Middle_Line) ||
          (Map_2==0 || (Map_2>0 && wil2>Williams_Middle_Line && wil2_1<=Williams_Middle_Line)))){
         RefreshRates();
         ask=MarketInfo(Symbol(),MODE_ASK);
         if (OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(ask,Digits),Slippage,Pink)){
            if (Enable_Pos3  && !DisableTrade)
            if ((TradeOnSunday || (!TradeOnSunday && TimeDayOfWeek(TimeCurrent())!=0)))
            if (OrderSend(Symbol(),OP_BUY,Lots3,NormalizeDouble(ask,Digits),Slippage,0,0,com3,Magic_Number3,0,Blue)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("3-2 Buy Error :"+error(i)+" at "+Symbol()+" "+Period());                                               
            }       
         }
         return(0);
      }
      if (OrderType()==OP_BUY && ((wil1<Williams_Middle_Line && wil1_1>=Williams_Middle_Line) ||
         (Map_2==0 || (Map_2>0 && wil2<Williams_Middle_Line && wil2_1>=Williams_Middle_Line)))){
         RefreshRates();
         bid=MarketInfo(Symbol(),MODE_BID);
         if (OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(bid,Digits),Slippage,Pink)){
            if (Enable_Pos3  && !DisableTrade)
            if ((TradeOnSunday || (!TradeOnSunday && TimeDayOfWeek(TimeCurrent())!=0)))
            if (OrderSend(Symbol(),OP_SELL,Lots3,NormalizeDouble(bid,Digits),Slippage,0,0,com3,Magic_Number3,0,Red)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("3-2 Sell Error :"+error(i)+" at "+Symbol()+" "+Period());                                               
            }                
         }
         return (0);
      }
   }
   
   if (TotalOrders(Magic_Number2)>0){
      bool g=false;
      for (j=0;j<OrdersTotal();j++){
         OrderSelect(j,SELECT_BY_POS);
         if (OrderMagicNumber()==Magic_Number2 && OrderTakeProfit()==0) {
          g=true;
          break;
         }
      }
      if (g && OrderType()==OP_SELL && ((wil1>Williams_Middle_Line && wil1_1<=Williams_Middle_Line) ||
         (Map_2==0 || (Map_2>0 && wil2>Williams_Middle_Line && wil2_1<=Williams_Middle_Line)))){
         RefreshRates();
         ask=MarketInfo(Symbol(),MODE_ASK);
         if (Enable_Pos2  && !DisableTrade)
         if (OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(ask,Digits),Slippage,Pink)){
            if ((TradeOnSunday || (!TradeOnSunday && TimeDayOfWeek(TimeCurrent())!=0)))
            if (OrderSend(Symbol(),OP_BUY,Lots2,NormalizeDouble(ask,Digits),Slippage,NormalizeDouble(ask-SL2*Point,Digits),0,com2,Magic_Number2,0,Blue)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("2-2 Buy Error :"+error(i)+" at "+Symbol()+" "+Period());                                               
            }       
         }
         return(0);
      }
      if (g && OrderType()==OP_BUY && ((wil1<Williams_Middle_Line && wil1_1>=Williams_Middle_Line) ||
         (Map_2==0 || (Map_2>0 && wil2<Williams_Middle_Line && wil2_1>=Williams_Middle_Line)))){
         RefreshRates();         
         bid=MarketInfo(Symbol(),MODE_BID);
         if (Enable_Pos2  && !DisableTrade)
         if (OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(bid,Digits),Slippage,Pink)){
            if ((TradeOnSunday || (!TradeOnSunday && TimeDayOfWeek(TimeCurrent())!=0)))
            if (OrderSend(Symbol(),OP_SELL,Lots2,NormalizeDouble(bid,Digits),Slippage,NormalizeDouble(bid+SL2*Point,Digits),0,com2,Magic_Number2,0,Red)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("2-2 Sell Error :"+error(i)+" at "+Symbol()+" "+Period());                                               
            }                
         }
         return(0);
      }
   }

   if (TotalOrders(Magic_Number1)>0){
      g=false;
      for (j=0;j<OrdersTotal();j++){
         OrderSelect(j,SELECT_BY_POS);
         if (OrderMagicNumber()==Magic_Number1 && OrderTakeProfit()==0) {
          g=true;
          break;
         }
      }
      if (g && OrderType()==OP_SELL && ((wil1>Williams_Middle_Line && wil1_1<=Williams_Middle_Line) ||
         (Map_2==0 || (Map_2>0 && wil2>Williams_Middle_Line && wil2_1<=Williams_Middle_Line)))){
         RefreshRates();
         ask=MarketInfo(Symbol(),MODE_ASK);
         if (Enable_Pos1  && !DisableTrade)
         if (OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(ask,Digits),Slippage,Pink)){
            if ((TradeOnSunday || (!TradeOnSunday && TimeDayOfWeek(TimeCurrent())!=0)))
            if (OrderSend(Symbol(),OP_BUY,Lots1,NormalizeDouble(ask,Digits),Slippage,NormalizeDouble(ask-SL1*Point,Digits),0,com1,Magic_Number1,0,Blue)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("1-2 Buy Error :"+error(i)+" at "+Symbol()+" "+Period());                                               
            }       
         }
         return(0);
      }
      if (g && OrderType()==OP_BUY && ((wil1<Williams_Middle_Line && wil1_1>=Williams_Middle_Line) ||
         (Map_2==0 || (Map_2>0 && wil2<Williams_Middle_Line && wil2_1>=Williams_Middle_Line)))){
         RefreshRates();         
         bid=MarketInfo(Symbol(),MODE_BID);
         if (Enable_Pos2  && !DisableTrade)
         if (OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(bid,Digits),Slippage,Pink)){
            if ((TradeOnSunday || (!TradeOnSunday && TimeDayOfWeek(TimeCurrent())!=0)))
            if (OrderSend(Symbol(),OP_SELL,Lots1,NormalizeDouble(bid,Digits),Slippage,NormalizeDouble(bid+SL1*Point,Digits),0,com1,Magic_Number1,0,Red)==-1){
               i=GetLastError();
               if (i!=1 && i!=0) Print("1-2 Sell Error :"+error(i)+" at "+Symbol()+" "+Period());                                               
            }                
         }
         return(0);
      }
   }

   if (TotalOrders(Magic_Number1)>0){ 
      for (int kk=0;kk<OrdersTotal();kk++){
         OrderSelect(kk,SELECT_BY_POS);
         if (OrderMagicNumber()==Magic_Number1 && OrderType()==OP_BUY && Bid-OrderOpenPrice()>=Break_Even_Point1*Point && OrderStopLoss()!=NormalizeDouble(OrderOpenPrice()+Break_Even_Stop1*Point,Digits)){
            OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(OrderOpenPrice()+Break_Even_Stop1*Point,Digits),OrderTakeProfit(),0,Violet);           
         }
         if (OrderMagicNumber()==Magic_Number1 && OrderType()==OP_SELL && OrderOpenPrice()-Bid>=Break_Even_Point1*Point && OrderStopLoss()!=NormalizeDouble(OrderOpenPrice()-Break_Even_Stop1*Point,Digits)){
            OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(OrderOpenPrice()-Break_Even_Stop1*Point,Digits),OrderTakeProfit(),0,Violet);           
         }         
      }
      tr(Magic_Number1,TS1);
   }
   if (TotalOrders(Magic_Number2)>0){ 
      for (kk=0;kk<OrdersTotal();kk++){
         OrderSelect(kk,SELECT_BY_POS);
         if (OrderMagicNumber()==Magic_Number2 && OrderType()==OP_BUY && Bid-OrderOpenPrice()>=Break_Even_Point2*Point && OrderStopLoss()!=NormalizeDouble(OrderOpenPrice()+Break_Even_Stop2*Point,Digits)){
            OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(OrderOpenPrice()+Break_Even_Stop2*Point,Digits),OrderTakeProfit(),0,Violet);           
         }
         if (OrderMagicNumber()==Magic_Number2 && OrderType()==OP_SELL && OrderOpenPrice()-Bid>=Break_Even_Point2*Point && OrderStopLoss()!=NormalizeDouble(OrderOpenPrice()-Break_Even_Stop2*Point,Digits)){
            OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(OrderOpenPrice()-Break_Even_Stop2*Point,Digits),OrderTakeProfit(),0,Violet);           
         }         
      }   
      tr(Magic_Number2,TS2);
   }
   if (TotalOrders(Magic_Number3)>0){ 
      for (kk=0;kk<OrdersTotal();kk++){
         OrderSelect(kk,SELECT_BY_POS);
         if (OrderMagicNumber()==Magic_Number3 && OrderType()==OP_BUY && Bid-OrderOpenPrice()>=Break_Even_Point3*Point && OrderStopLoss()!=NormalizeDouble(OrderOpenPrice()+Break_Even_Stop3*Point,Digits)){
            OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(OrderOpenPrice()+Break_Even_Stop3*Point,Digits),OrderTakeProfit(),0,Violet);           
         }
         if (OrderMagicNumber()==Magic_Number3 && OrderType()==OP_SELL && OrderOpenPrice()-Bid>=Break_Even_Point3*Point && OrderStopLoss()!=NormalizeDouble(OrderOpenPrice()-Break_Even_Stop3*Point,Digits)){
            OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(OrderOpenPrice()-Break_Even_Stop3*Point,Digits),OrderTakeProfit(),0,Violet);           
         }         
      }   
    }
   return(0);
  }

int TotalOrders(int magic){
   int rez=0;
   for (int i=0;i<OrdersTotal();i++){
      OrderSelect(i,SELECT_BY_POS);
      if (OrderMagicNumber()==magic){
         rez++;
      }
   }   
   return(rez);
} 
void tr(int magic,int triling_i){  
  for (int k=0;k<OrdersTotal();k++){
    OrderSelect(k,SELECT_BY_POS);
    if (OrderMagicNumber()==magic){        
      if (OrderType()==OP_BUY && NormalizeDouble(Ask-OrderOpenPrice(),Digits)>=triling_i*Point && OrderStopLoss()<NormalizeDouble(Ask-triling_i*Point,Digits)) {
         if (!OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(Ask-triling_i*Point,Digits),OrderTakeProfit(),0,Blue)){
            Print("Trailing stop error Buy :"+error(GetLastError()));
         }    
      }
      if (OrderType()==OP_SELL && NormalizeDouble(Bid+triling_i*Point,Digits)<=OrderOpenPrice() && (OrderStopLoss()>NormalizeDouble(Bid+triling_i*Point,Digits) || OrderStopLoss()==0)) {
         if (!OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(Bid+triling_i*Point,Digits),OrderTakeProfit(),0,Red)){
            Print("Trailing stop error Sell :"+error(GetLastError()));  
         }
      }
    }
  }
}


double FRisk_MM(double SLot,double TR,double f){
   double rez=0;      
   rez=MathFloor((f*(AccountEquity()/TR)));        
   if (rez/10<SLot) return(SLot);
   return(rez/10);
}
string error(int err){
switch (err){
 case 0 :return("No error returned.");
 case 1 :return("No error returned, but the result is unknown. ");
 case 2 :return("Common error. ");
 case 3 :return("Invalid trade parameters. ");
 case 4 :return("Trade server is busy. ");
 case 5 :return("Old version of the client terminal. ");
 case 6 :return("No connection with trade server. ");
 case 7 :return("Not enough rights. ");
 case 8 :return("Too frequent requests."); 
 case 9 :return("Malfunctional trade operation. ");
 case 64 :return("Account disabled. ");
 case 65 :return("Invalid account. ");
 case 128 :return("Trade timeout. ");
 case 129 :return("Invalid price. ");
 case 130 :return("Invalid stops. ");
 case 131 :return("Invalid trade volume. ");
 case 132 :return("Market is closed. ");
 case 133 :return("Trade is disabled. ");
 case 134 :return("Not enough money. ");
 case 135 :return("Price changed. ");
 case 136 :return("Off quotes. ");
 case 137 :return("Broker is busy."); 
 case 138 :return("Requote. ");
 case 139 :return("Order is locked. ");
 case 140 :return("Long positions only allowed. ");
 case 141 :return("Too many requests. ");
 case 145 :return("Modification denied because order too close to market. ");
 case 146 :return("Trade context is busy. ");
 case 147 :return("Expirations are denied by broker. ");
 case 148 :return("The amount of open and pending orders has reached the limit set by the broker. ");
 case 4000 :return("No error. ");
 case 4001 :return("Wrong function pointer. ");
 case 4002 :return("Array index is out of range. ");
 case 4003 :return("No memory for function call stack. ");
 case 4004 :return("Recursive stack overflow. ");
 case 4005 :return("Not enough stack for parameter. ");
 case 4006 :return("No memory for parameter string. ");
 case 4007 :return("No memory for temp string. ");
 case 4008 :return("Not initialized string. ");
 case 4009 :return("Not initialized string in array. ");
 case 4010 :return("No memory for array string. ");
 case 4011 :return("Too long string. ");
 case 4012 :return("Remainder from zero divide. ");
 case 4013 :return("Zero divide. ");
 case 4014 :return("Unknown command. ");
 case 4015 :return("Wrong jump (never generated error). ");
 case 4016 :return("Not initialized array. ");
 case 4017 :return("DLL calls are not allowed. ");
 case 4018 :return("Cannot load library. ");
 case 4019 :return("Cannot call function. ");
 case 4020 :return("Expert function calls are not allowed. ");
 case 4021 :return("Not enough memory for temp string returned from function. ");
 case 4022 :return("System is busy (never generated error). ");
 case 4050 :return("Invalid function parameters count. ");
 case 4051 :return("Invalid function parameter value. ");
 case 4052 :return("String function internal error. ");
 case 4053 :return("Some array error. ");
 case 4054 :return("Incorrect series array using. ");
 case 4055 :return("Custom indicator error. ");
 case 4056 :return("Arrays are incompatible. ");
 case 4057 :return("Global variables processing error. ");
 case 4058 :return("Global variable not found. ");
 case 4059 :return("Function is not allowed in testing mode. ");
 case 4060 :return("Function is not confirmed. ");
 case 4061 :return("Send mail error. ");
 case 4062 :return("String parameter expected. ");
 case 4063 :return("Integer parameter expected. ");
 case 4064 :return("Double parameter expected. ");
 case 4065 :return("Array as parameter expected. ");
 case 4066 :return("Requested history data in updating state. ");
 case 4067 :return("Some error in trading function. ");
 case 4099 :return("End of file. ");
 case 4100 :return("Some file error."); 
 case 4101 :return("Wrong file name. ");
 case 4102 :return("Too many opened files. ");
 case 4103 :return("Cannot open file. ");
 case 4104 :return("Incompatible access to a file. ");
 case 4105 :return("No order selected. ");
 case 4106 :return("Unknown symbol. ");
 case 4107 :return("Invalid price. ");
 case 4108 :return("Invalid ticket. ");
 case 4109 :return("Trade is not allowed. ");
 case 4110 :return("Longs are not allowed. ");
 case 4111 :return("Shorts are not allowed. ");
 case 4200 :return("Object exists already. ");
 case 4201 :return("Unknown object property. ");
 case 4202 :return("Object does not exist. ");
 case 4203 :return("Unknown object type. ");
 case 4204 :return("No object name. ");
 case 4205 :return("Object coordinates error. ");
 case 4206 :return("No specified subwindow. ");
 case 4207 :return("Some error in object function. ");
 default: return("Unknown error:"+err);
}
}