//+--------------+
//|One(Buy/Sell) |
//+--------------+
#property copyright "Ron Thompson"
#property link      "http://www.ForexMT4.com/"

// This code is NEVER to be SOLD individually 
// This code is NEVER to be INCLUDED as part of a collection that is SOLD


// This is really a script, so...
//#property show_inputs


// EA SPECIFIC
       string MeIs                =    "1SELL" ;

extern double Lots                =       1.0 ;
extern double ProfitMade          =       2   ; 
extern double LossLimit           =       0   ;
extern double BreakEven           =       0   ;
extern double TrailStop           =       0   ;
extern int    Slippage            =       0   ;

// Trade control
int           MagicNumber;
double        LL2SL=25;
double        myPoint;                              // support for 3/5 decimal places
int           loopcount;                            // count of order attempts
int           maxloop=25;                           // maximum number of attempts to handle errors

// Bar handling
datetime      bartime=0;                            // used to determine when a bar has moved

// used for verbose error logging
#include <stdlib.mqh>


//+-------------+
//| Custom init |
//|-------------+
// Called ONCE when EA is added to chart or recompiled

int init()
  {
   // get normalized Point based on Broker decimal places
   myPoint = SetPoint();

   if(MeIs=="1SELL")
     {
      MagicNumber=142555;
      OpenSell();
     }
      
   if(MeIs=="1BUY")
     {
      MagicNumber=142222;
      OpenBuy();
     }
   
   Print("Init Complete "+MeIs);
   Comment(" ");
  }

//+----------------+
//| Custom DE-init |
//+----------------+
// Called ONCE when EA is removed from chart

int deinit()
  {
   Print("DE-Init Complete "+MeIs);
   //Comment(" ");
  }




//+-----------+
//| Main      |
//+-----------+
// Called EACH TICK and each Bar[]

int start()
  {
   int cnt;

   double CurrentProfit;
   int    OrdersPerSymbol;
      
   double SL;
   double TP;
   
   int gle;  // GetLastError
   

   // since this is a script, we need to loop here till the order closes
   // therefore this 'while' with no indent
   while(true)
   {

   //
   // Order Management
   //

   for(cnt=OrdersTotal();cnt>=0;cnt--)
     {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if( OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber )
        {
        
         if(OrderType()==OP_BUY)
           {
            CurrentProfit=(Bid-OrderOpenPrice()) ;

            //
            // Modify for break even
            //=======================
            //
            // OrderStopLoss will be equal to OrderOpenPrice if this event happens
            // thus it will only ever get executed one time per ticket
            if( BreakEven>0 )
              {
               if (CurrentProfit >= BreakEven*myPoint && OrderOpenPrice()>OrderStopLoss())
                 {
                  SL=OrderOpenPrice()+(Ask-Bid);
                  TP=OrderTakeProfit();
                  OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP, White);
                  gle=GetLastError();
                  if(gle==0)
                    {
                     Print("MODIFY BUY BE Ticket="+OrderTicket()+" SL="+SL+" TP="+TP);
                    }
                     else 
                    {
                     Print("-----ERROR----- MODIFY BUY  BE Bid="+Bid+" error="+gle+" "+ErrorDescription(gle));
                    }
                 }
              }


            //
            // check for trailing stop
            //=========================
            //
            // This starts trailing after 'TrailStop' pips of profit
            if( TrailStop>0 && Close[0]>OrderOpenPrice()+(TrailStop*myPoint) )  
              {                 
               if( OrderStopLoss() < Bid-(TrailStop*myPoint) )
                 {
                  SL=Bid-(TrailStop*myPoint);
                  TP=OrderTakeProfit();
                  OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP,0,White);
                  gle=GetLastError();
                  if(gle==0)
                    {
                     Print("MODIFY BUY TS Ticket="+OrderTicket()+" SL="+SL+" TP="+TP);
                    }
                     else 
                    {
                     Print("-----ERROR----- MODIFY BUY TS Bid="+Bid+" error="+gle+" "+ErrorDescription(gle)+" ");
                    }
                 }
              }


            // Did we make a profit
            //======================
            if(ProfitMade>0 && CurrentProfit>=(ProfitMade*myPoint))
              {
               CloseBuy("PROFIT");
              }
              

            // Did we take a loss
            //====================
            if(LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*myPoint))
              {
               CloseBuy("LOSS");
              }
              
           } // if BUY


         if(OrderType()==OP_SELL)
           {
            // add up pips
            // CurrentProfit=(Close[0]-OrderOpenPrice()) * (-1) ;
            // add up dollars
            // CurrentProfit=OrderProfit();

            CurrentProfit=(OrderOpenPrice()-Ask);

            //
            // Modify for break even
            //=======================
            //
            // OrderStopLoss will be equal to OrderOpenPrice if this event happens
            // thus it will only ever get executed one time per ticket
            if( BreakEven>0 )
              {
               if (CurrentProfit >= BreakEven*myPoint && OrderOpenPrice()<OrderStopLoss())
                 {
                  SL=OrderOpenPrice()-(Ask-Bid);
                  TP=OrderTakeProfit();
                  OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP, Red);
                  gle=GetLastError();
                  if(gle==0)
                    {
                     Print("MODIFY SELL BE Ticket="+OrderTicket()+" SL="+SL+" TP="+TP);
                    }
                     else 
                    {
                     Print("-----ERROR----- MODIFY SELL BE Ask="+Ask+" error="+gle+" "+ErrorDescription(gle));
                    }
                 }
              }


            //
            // check for trailing stop
            //=========================
            //
            // This starts trailing after 'TrailStop' pips of profit
            if( TrailStop>0 && Close[0]<OrderOpenPrice()-(TrailStop*myPoint) )  


              {                 
               if( OrderStopLoss() > Ask+(TrailStop*myPoint) )
                 {
                  SL=Ask+(TrailStop*myPoint);
                  TP=OrderTakeProfit();
                  OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP,0,Red);
                  gle=GetLastError();
                  if(gle==0)
                    {
                     Print("MODIFY SELL TS Ticket="+OrderTicket()+" SL="+SL+" TP="+TP);
                    }
                     else 
                    {
                     Print("-----ERROR----- MODIFY SELL TS Ask="+Ask+" error="+gle+" "+ErrorDescription(gle));
                    }

                 }

              }


            // Did we make a profit
            //======================
            if( ProfitMade>0 && CurrentProfit>=(ProfitMade*myPoint) )
              {
               CloseSell("PROFIT");
              }
             

            // Did we take a loss
            //====================
            if( LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*myPoint) )
              {
               CloseSell("LOSS");
              }

           } //if SELL
           
        } // if(OrderSymbol)
        
     } // for


   // get out of script once order count reaches zero

   Sleep(500);   
   RefreshRates();
   
   OrdersPerSymbol=0;
   for(cnt=OrdersTotal();cnt>=0;cnt--)
     {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if( OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) OrdersPerSymbol++;
     }

   if(OrdersPerSymbol==0)
     {
      Print(MeIs+" exiting while loop");
      break;
     }

   Comment(MeIs+" Open Orders="+OrdersPerSymbol+"    CurrentProfit="+CurrentProfit+" ProfitMade="+(ProfitMade*myPoint) );

  } //unindented while
  } // start()






//ENTRY LONG (buy, Ask) 
void OpenBuy()
     {
      int      gle=0;
      int      ticket=0;
      
      double SL=0;
      double TP=0;
      int loopcount;

      // PLACE order is independent of MODIFY order. 
      // This is mandatory for ECNs and acceptable for retail brokers

      loopcount=0;
      while(true)          
        {
         // place order - NO TP OR SL
         ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,0,0,MeIs,MagicNumber,White);
         gle=GetLastError();
         if(gle==0)
           {
            Print("BUY PLACED Ticket="+ticket+" Ask="+Ask+" Lots="+Lots);
            break;
           }
          else 
           {
            Print("-----ERROR-----  Placing BUY order: Lots="+Lots+" Bid="+Bid+" Ask="+Ask+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); 
            
            RefreshRates();
            Sleep(500);

            // give up after loopcount tries
            loopcount++;
            if(loopcount>maxloop)
              {
               Print("-----ERROR-----  Giving up on placing BUY order"); 
               return(gle);
              }
           }
        }//while - place order 


      // modify the order for users TP & SL
      loopcount=0;
      while(true)
        {
         // don't set TP and SL both to zero, they're already there
         if(LossLimit==0 && ProfitMade==0) break;
         
         if(LossLimit  ==0) SL=0;
         if(ProfitMade ==0) TP=0;
         if(LossLimit   >0) SL=Ask-((LossLimit+LL2SL)*myPoint );
         if(ProfitMade  >0) TP=Ask+((ProfitMade+LL2SL)*myPoint );
         OrderModify(ticket,OrderOpenPrice(),SL,TP,0,White);
         gle=GetLastError();
         if(gle==0)
           {
            Print("BUY MODIFIED Ticket="+ticket+" Ask="+Ask+" Lots="+Lots+" SL="+SL+" TP="+TP);
            break;
           }
          else 
           {
            Print("-----ERROR-----  Modifying BUY order: Lots="+Lots+" SL="+SL+" TP="+TP+" Bid="+Bid+" Ask="+Ask+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); 
            
            RefreshRates();
            Sleep(500);

            loopcount++;
            if(loopcount>maxloop)
              {
               Print("-----ERROR-----  Giving up on modifying BUY order"); 
               return(gle);
              }
           }
        }//while - modify order
        
        
     }//BUYme



   //ENTRY SHORT (sell, Bid)
void OpenSell()
     {
      int      gle=0;
      int      ticket=0;
      
      double SL=0;
      double TP=0;
      int loopcount;

      // PLACE order is independent of MODIFY order. 
      // This is mandatory for ECNs and acceptable for retail brokers

      loopcount=0;
      while(true)
        {
         ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,0,0,MeIs,MagicNumber,Red);
         gle=GetLastError();
         if(gle==0)
           {
            Print("SELL PLACED Ticket="+ticket+" Bid="+Bid+" Lots="+Lots);
            break;
           }
            else 
           {
            Print("-----ERROR-----  placing SELL order: Lots="+Lots+" SL="+SL+" TP="+TP+" Bid="+Bid+" Ask="+Ask+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); 
                            
            RefreshRates();
            Sleep(500);

            loopcount++;
            if(loopcount>maxloop)
              {
               Print("-----ERROR-----  Giving up on placing SELL order"); 
               return(gle);
              }
           }
        }//while

      
      // modify the order for users TP & SL
      loopcount=0;
      while(true)
        {
         // don't set TP and SL both to zero, they're already there
         if(LossLimit==0 && ProfitMade==0) break;
         
         if(LossLimit  ==0) SL=0;
         if(ProfitMade ==0) TP=0;
         if(LossLimit   >0) SL=Bid+((LossLimit+LL2SL)*myPoint );
         if(ProfitMade  >0) TP=Bid-((ProfitMade+LL2SL)*myPoint );
         OrderModify(ticket,OrderOpenPrice(),SL,TP,0,Red);
         gle=GetLastError();
         if(gle==0)
           {
            Print("SELL MODIFIED Ticket="+ticket+" Bid="+Bid+" Lots="+Lots+" SL="+SL+" TP="+TP);
            break;
           }
            else 
           {
            Print("-----ERROR-----  modifying SELL order: Lots="+Lots+" SL="+SL+" TP="+TP+" Bid="+Bid+" Ask="+Ask+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); 
                            
            RefreshRates();
            Sleep(500);

            loopcount++;
            if(loopcount>maxloop)
              {
               Print("-----ERROR-----  Giving up on placing SELL order"); 
               return(gle);
              }
           }

        }//while

     }//SELLme



void CloseBuy (string myInfo)
  {
   int gle;
   int cnt;
   int OrdersPerSymbol;

   int loopcount=0;
   
   string bTK=" Ticket="+OrderTicket();
   string bSL=" SL="+OrderStopLoss();
   string bTP=" TP="+OrderTakeProfit();
   string bPM;
   string bLL;
   string bER;

   bPM=" PM="+ProfitMade;
   bLL=" LL="+LossLimit;

   while(true)
     {
      OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,White);
      gle=GetLastError();
      bER=" error="+gle+" "+ErrorDescription(gle);

      if(gle==0)
        {
         Print("CLOSE BUY "+myInfo+ bTK + bSL + bTP + bPM + bLL);
         break;
        }
       else 
        {
         Print("-----ERROR----- CLOSE BUY "+myInfo+ bER +" Bid="+Bid+ bTK + bSL + bTP + bPM + bLL);
         RefreshRates();
         Sleep(500);
        }


      loopcount++;
      if(loopcount>maxloop)
        {
         Print("-----ERROR-----  Giving up on closing SELL order"); 
         return(gle);
        }
                     
     }//while
  
  }


void CloseSell (string myInfo)
  {
   int gle;
   int cnt;
   int OrdersPerSymbol;

   int loopcount=0;

   string sTK=" Ticket="+OrderTicket();
   string sSL=" SL="+OrderStopLoss();
   string sTP=" TP="+OrderTakeProfit();
   string sPM;
   string sLL;
   string sER;
      
   sPM=" PM="+ProfitMade;
   sLL=" LL="+LossLimit;

   while(true)
     {
      OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,Red);
      gle=GetLastError();
      sER=" error="+gle+" "+ErrorDescription(gle);
      
      if(gle==0)
        {
         Print("CLOSE SELL "+myInfo + sTK + sSL + sTP + sPM + sLL);
         break;
        }
      else 
        {
         Print("-----ERROR----- CLOSE SELL "+myInfo+ sER +" Ask="+Ask+ sTK + sSL + sTP + sPM + sLL);
         RefreshRates();
         Sleep(500);
        }

      loopcount++;
      if(loopcount>maxloop)
        {
         Print("-----ERROR-----  Giving up on closing SELL order"); 
         return(gle);
        }
                 
     }//while                 
  }      


// Function to correct the value of Point
// for brokers that add an extra digit to price
// Courtesy of Robert Hill

double SetPoint()
{
   double mPoint;
  
   if (Digits < 4)
      mPoint = 0.01;
   else
      mPoint = 0.0001;
  
   return(mPoint);
}

