//+------------------------------------------------------------------+
//|                                        Williama PriceTrapper.mq4 |
//|                        Based on the great strategie of Williama  |
//|                  Coded by Naufrage, All rights granted to you :) |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""

//---- input parameters
extern int       pips=15; // number of pips between each level
extern double    lots=0.01;
extern int       NbLevels=3; // Number of levels of the pending orders (for each target, buy and sell)
extern int       ProfitTarget=0; //Minimum profit target, in pips. Whatever happen, at least this profit is made (unless we run out of free margin...).
extern bool      ContinueTrading=true; // launch a new setup after the current one?

int Magic=17663;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   int ticket, cpt, profit, total, BuyGoalProfit, SellGoalProfit;
   double BuyGoal=0, SellGoal=0, spread=(Ask-Bid)/Point;
//----
   total=0;
   for(cpt=0;cpt<OrdersTotal();cpt++)
   {
      OrderSelect(cpt,SELECT_BY_POS,MODE_TRADES);
      if(OrderMagicNumber()==Magic && OrderSymbol()==Symbol()) total++;
   }
   if(total<1 && ContinueTrading) //we can set up a new "price catcher"
   {
      if(AccountFreeMargin()<(10000*lots))
      {
         Print("Not enough free margin to begin");
         return(0);
      }
      SellGoal=Ask-(NbLevels+1)*pips*Point;
      BuyGoal=Ask+(NbLevels+1)*pips*Point;
      for(cpt=1;cpt<=NbLevels;cpt++)
      {
         ticket=OrderSend(Symbol(),OP_BUYSTOP,lots,Ask+cpt*pips*Point,2,SellGoal,BuyGoal,"InitialSetup",Magic,0,Green);
         if(ticket==0)
         {
            Print("Error opening BUYSTOP order : ",GetLastError()); 
            return(0); 
         }
         ticket=OrderSend(Symbol(),OP_SELLSTOP,lots,Bid-cpt*pips*Point,2,BuyGoal+spread*Point,SellGoal-spread*Point,"InitialSetup",Magic,0,Green);
         if(ticket==0)
         {
            Print("Error opening SELLSTOP order : ",GetLastError()); 
            return(0); 
         } 
      }
    } // initial setup done
    else
    {
      OrderSelect(0, SELECT_BY_POS, MODE_TRADES);
      cpt=0;
      while(OrderType()!=OP_BUY && OrderType()!=OP_BUYSTOP)
      {
         OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
         cpt++;
      }
      BuyGoal=OrderTakeProfit();
      SellGoal=OrderStopLoss();
      // check if pending orders must be canceled
      if(Ask>=BuyGoal || (Ask<=SellGoal))
      {
         for(cpt=0;cpt<total;cpt++)
         {
            OrderSelect(cpt,SELECT_BY_POS, MODE_TRADES);
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic) OrderDelete(OrderTicket());
         }
         return(0);
      }
      else if((Ask+pips*Point)<=BuyGoal && (Ask-pips*Point)>=SellGoal)
      // now we check if profit will be made no matter which goal is reached, and add pending orders if necessary
      {
         //first, check profit if the BuyGoal is reached
         profit=0;
         for(cpt=0;cpt<total;cpt++)
         {
            OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
            {
               if(OrderType()==OP_BUY) profit+=(BuyGoal-OrderOpenPrice())/Point;
               if(OrderType()==OP_SELL) profit-=((BuyGoal+spread*Point)-OrderOpenPrice())/Point;
               if(OrderType()==OP_BUYSTOP && OrderOpenPrice()>Ask) profit+=(BuyGoal-OrderOpenPrice())/Point;
            }
         }
         cpt=1;
         BuyGoalProfit=profit;
         while(profit<ProfitTarget)
         {
            if((Ask+MarketInfo(Symbol(),MODE_STOPLEVEL)*Point)<(BuyGoal-cpt*pips*Point))
            {
               OrderSend(Symbol(),OP_BUYSTOP,lots,BuyGoal-cpt*pips*Point,2,SellGoal,BuyGoal,"",Magic,0,Green);
               profit+=cpt*pips;
            }
            cpt++;
            if(cpt>NbLevels+1) cpt=1;
         }
         // then, check profit if SellGoal is reached
         profit=0;
         for(cpt=0;cpt<total;cpt++)
         {
            OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
            {
               if(OrderType()==OP_BUY) profit-=(OrderOpenPrice()-SellGoal)/Point;
               if(OrderType()==OP_SELL) profit+=(OrderOpenPrice()-(SellGoal-spread*Point))/Point;
               if(OrderType()==OP_SELLSTOP && OrderOpenPrice()<Bid) profit+=(OrderOpenPrice()-(SellGoal-spread*Point))/Point;
            }
         }
         cpt=1;
         SellGoalProfit=profit;
         while(profit<ProfitTarget)
         {
            if((Bid+MarketInfo(Symbol(),MODE_STOPLEVEL)*Point)>(SellGoal+cpt*pips*Point))
            {
               OrderSend(Symbol(),OP_SELLSTOP,lots,(SellGoal-spread*Point)+cpt*pips*Point,2,BuyGoal+spread*Point,SellGoal-spread*Point,"",Magic,0,Green);
              profit+=cpt*pips;
            }
            cpt++;
            if(cpt>NbLevels+1) cpt=1;
         }
      }
     }
   string sComment   = "";
   string sep         = "----------------------------------------\n";
   string nl         = "\n";
   sComment = "Williama EA v.0.1" + nl;
   sComment = sComment + "Lots=" + DoubleToStr(lots,2) + nl;
   sComment = sComment + "Buy Goal= " + DoubleToStr(BuyGoal,4) + nl; 
   sComment = sComment + "Buy Goal Profit (in pips)=" + BuyGoalProfit + nl + nl;
   sComment = sComment + "Sell Goal= " + DoubleToStr(SellGoal,4) + nl; 
   sComment = sComment + "Sell Goal Profit (in pips)=" + SellGoalProfit + nl + nl;
   sComment = sComment + "Pips of each level=" + pips + nl;
   sComment = sComment + "Number of levels for each goal: " + NbLevels + nl;
   sComment = sComment + sep;  
   Comment(sComment);
//----
   return(0);
  }
//+------------------------------------------------------------------+