// ------------------------------------------------------------------------------------------ //
//                      M A G N E T O   E X P E R T   A D V I S O R                           //
//                       Semi Automatic Break Carry Trading System                            //
//                          by fosgate_r    © January 2009                                    //
//                      URL : http://forexfreeea.blogspot.com/                                //
// ------------------------------------------------------------------------------------------ //


#property  copyright "© January 2009 fosgate_r"
#property  link "http://forexfreeea.blogspot.com/"
#include <stdlib.mqh>


// ------------------------------------------------------------------------------------------ //
//                            E X T E R N A L   V A R I A B L E S                             //
// ------------------------------------------------------------------------------------------ //

extern   double   BaseLot  = 0.1;
extern   bool     BEclose  = false;
extern   double   BEprofit = 0;
extern   int      Magic    = 20081008;

// ------------------------------------------------------------------------------------------ //
//                            I N T E R N A L   V A R I A B L E S                             //
// ------------------------------------------------------------------------------------------ //

double   lotsi, PendingLot, hline=0, lline=0, gap=0;
string   strtmp, rangetxt, eacmd;
int      lotc[] = { 1,3,6,12,24,48,96 };
int      OpenOrders, OpenPendings, LastOpen;


// ------------------------------------------------------------------------------------------ //
//                             I N I T I A L I S A T I O N                                    //
// ------------------------------------------------------------------------------------------ //

int init()
{
   Comment("");
   return(0);    
}


// ------------------------------------------------------------------------------------------ //
//                            D E - I N I T I A L I S A T I O N                               //
// ------------------------------------------------------------------------------------------ //

int deinit()
{
   Comment("");
   return(0);
}


// ------------------------------------------------------------------------------------------ //
//                                M A I N   P R O C E D U R E                                 //
// ------------------------------------------------------------------------------------------ //

int start()
{  
   int      i;
   hline=0; lline=0; gap=0; rangetxt="";     
   CntOrd(Magic);

   
   // When Nothing is Opened
   // ======================
         
   if (OpenOrders==0 && OpenPendings==0 && ObjectFind("HLine")>=0 && ObjectFind("LLine")>=0)
   {
      lotsi = BaseLot * lotc[0];
      hline = ObjectGet("HLine",OBJPROP_PRICE1);
      lline = ObjectGet("LLine",OBJPROP_PRICE1);
      gap   = NormalizeDouble(hline-lline,Digits) / Point;
      eacmd = DoubleToStr(hline,Digits)+" "+DoubleToStr(lline,Digits)+" "+DoubleToStr(gap,0);
      
      BuyStop (Magic, lotsi, hline, gap, 2*gap);
      SellStop(Magic, lotsi, lline, gap, 2*gap);      
      ObjectDelete("HLine"); ObjectDelete("LLine");
   }


   // When One is Opened and One is Pending
   // =====================================
      
   if (OpenOrders==1 && OpenPendings==1 && PendingLot==(BaseLot*lotc[0]))
   {
      lotsi = BaseLot * lotc[1];
      eacmd = DoubleToStr(hline,Digits)+" "+DoubleToStr(lline,Digits)+" "+DoubleToStr(gap,0);
      ClosePendings(Magic);
      Sleep(5000);
      if (LastOpen==OP_SELL)     BuyStop (Magic, lotsi, hline, gap, 2*gap);
      if (LastOpen==OP_BUY)      SellStop(Magic, lotsi, lline, gap, 2*gap);      
   }
   

   // When Keep Going
   // ===============
      
   if (OpenOrders>=2 && OpenPendings==0)
   {
      lotsi = BaseLot * lotc[OpenOrders];
      eacmd = DoubleToStr(hline,Digits)+" "+DoubleToStr(lline,Digits)+" "+DoubleToStr(gap,0);
      if (LastOpen==OP_SELL)     BuyStop (Magic, lotsi, hline, gap, 2*gap);
      if (LastOpen==OP_BUY)      SellStop(Magic, lotsi, lline, gap, 2*gap);      
   }


   // When Accomplished
   // =================
      
   if (OpenOrders==0 && OpenPendings==1)
   {
      ClosePendings(Magic);
      Sleep(5000);
   }


   // Break Even Close
   // ================

   if (OpenOrders>0 && BEclose && CalcProfit(Magic)>=BEprofit)
   {
      CloseOrders(Magic);
      Sleep(5000);   
      ClosePendings(Magic);
      Sleep(5000);
   }
   
   rangetxt = "\nLevels   :   H = " +   DoubleToStr(hline,Digits) +
                         "    L = " +   DoubleToStr(lline,Digits) +
                         "    Gap = " + DoubleToStr(gap,0);
   if (BEclose)
       rangetxt = rangetxt + "\nBREAK EVEN CLOSING ACTIVATED AT  $ "
                           + DoubleToStr(BEprofit,2);
       
       
   // Comments
   // ========
   
   strtmp = "\nMAGNETO EA - © January 2009 fosgate_r";
   strtmp = strtmp + "\nCurrent Server Time : " + TimeToStr(TimeCurrent());
   strtmp = strtmp + "\nLot Size : " + DoubleToStr(BaseLot,2);
   strtmp = strtmp + "     Profit : $ " + DoubleToStr(CalcProfit(Magic),2)
                   + "   or   " + CalcPips(Magic) + " pips";
   strtmp = strtmp + rangetxt;
   Comment(strtmp);


   // The Impossible
   // ==============
   
   if (OpenOrders==1000)
   {   Buy(Magic,BaseLot,0,0); Sell(Magic,BaseLot,0,0); CloseOrders(Magic);   }
   return(0);
}


// ------------------------------------------------------------------------------------------ //
//                                 C O U N T   O R D E R S                                    //
// ------------------------------------------------------------------------------------------ //

void CntOrd(int mgc)
{
   string      txt1;   
   OpenOrders   = 0;
   OpenPendings = 0;
   
   for (int i = 0; i < OrdersTotal(); i++)
   {
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      if (OrderMagicNumber() == mgc && OrderSymbol()==Symbol())
      {
         if (OrderType()==OP_BUY     || OrderType()==OP_SELL)
            {  OpenOrders++;     ExtractCmd(OrderComment()); LastOpen   = OrderType();  }
         if (OrderType()==OP_BUYSTOP || OrderType()==OP_SELLSTOP)
            {  OpenPendings++;   ExtractCmd(OrderComment()); PendingLot = OrderLots();  }
      }
   }      
   return(0);
}


// ------------------------------------------------------------------------------------------ //
//                         E X T R A C T   O R D E R   C O M M E N T                          //
// ------------------------------------------------------------------------------------------ //

void ExtractCmd(string cmdtxt)
{
   int   i, j;
   i     = StringFind(cmdtxt," ",0);
   hline = StrToDouble(StringSubstr(cmdtxt,0,i));
   j     = StringFind(cmdtxt," ",i+1);
   lline = StrToDouble(StringSubstr(cmdtxt,i+1,j-i-1));
   gap   = StrToDouble(StringSubstr(cmdtxt,j+1,StringLen(cmdtxt)-j-1));
}


// ------------------------------------------------------------------------------------------ //
//                                 C A L C U L A T E    P I P S                               //
// ------------------------------------------------------------------------------------------ //

int CalcPips(int mgc)
{
   int pips = 0;
   double p = 0;
   
   for (int i=0; i<OrdersTotal(); i++)
   {
        OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
        if  (OrderMagicNumber()==mgc && OrderSymbol()==Symbol())
        {
            if (OrderType()==OP_BUY)
            {
               p = (Ask - OrderOpenPrice()) / Point;
               pips = pips + NormalizeDouble(p,0);
            }
            if (OrderType()==OP_SELL)
            {
               p = (OrderOpenPrice() - Bid) / Point;
               pips = pips + NormalizeDouble(p,0);
            }        
        }
   }   
   return(pips);
}


// ------------------------------------------------------------------------------------------ //
//                              C A L C U L A T E    P R O F I T                              //
// ------------------------------------------------------------------------------------------ //

double CalcProfit(int mgc)
{
   double profit = 0;
   for (int i=0; i<OrdersTotal(); i++)
   {
        OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
        if  (OrderMagicNumber()==mgc && OrderSymbol()==Symbol())
             profit = profit + OrderProfit() + OrderSwap();
   }   
   return(profit);
}


// ------------------------------------------------------------------------------------------ //
//                                  B U Y   F U N C T I O N                                   //
// ------------------------------------------------------------------------------------------ //

int Buy(int mgc, double lot,  double Tpft, double Slos)
{ 
    int     Ticket = 0, err = 0;
    double  TP = 0,      SL = 0;
    
    if (Tpft>0)   TP = NormalizeDouble(Ask + (Tpft*Point), Digits);
    if (Slos>0)   SL = NormalizeDouble(Ask - (Slos*Point), Digits);

    if (IsTradeAllowed() == true)
    {       
       for(int c=0; c<5; c++)
       {
          RefreshRates();
          Ticket = OrderSend(Symbol(),OP_BUY,lot,Ask,3,SL,TP,eacmd, mgc,0,Blue);
          err    = GetLastError();
          if(err==0)  break;
          else
          {
             Print("Errors opening BUY order");
             Print(ErrorDescription(err),", error ",err);
             if(err==4 || err==137 ||err==146 || err==136)   {Sleep(5000);continue;}
             else break; //normal error                               // Busy errors
          }
       }
    } 	    
    return(Ticket);
}


// ------------------------------------------------------------------------------------------ //
//                                S E L L   F U N C T I O N                                   //
// ------------------------------------------------------------------------------------------ //

int Sell(int mgc, double lot, double Tpft, double Slos)
{        
    int     Ticket = 0, err = 0;
    double  TP = 0,      SL = 0;
    
    if (Tpft>0)   TP = NormalizeDouble(Bid - (Tpft*Point), Digits);
    if (Slos>0)   SL = NormalizeDouble(Bid + (Slos*Point), Digits);

    if (IsTradeAllowed() == true)
    { 
       for(int c=0; c<5; c++)
       { 
         RefreshRates();
         Ticket = OrderSend(Symbol(),OP_SELL,lot,Bid,3,SL,TP,eacmd,mgc,0,Red);
         err    = GetLastError();
         if(err==0)  break;
         else
         {
            Print("Errors opening SELL order");
            Print(ErrorDescription(err),", error ",err);
            if(err==4 || err==137 ||err==146 || err==136)   {Sleep(5000);continue;} 
            else  break; //normal error                              // Busy errors
         }
       }
    } 	    
    return(Ticket);      
}


// ------------------------------------------------------------------------------------------ //
//                             B U Y   S T O P   F U N C T I O N                              //
// ------------------------------------------------------------------------------------------ //

int BuyStop(int mgc, double lot, double prc, double Tpft, double Slos)
{
    int      Ticket = 0, err = 0;
    double   TP = 0,      SL = 0;
    
    if (Tpft>0)   TP = NormalizeDouble(prc + (Tpft * Point) , Digits);
    if (Slos>0)   SL = NormalizeDouble(prc - (Slos * Point) , Digits);
    prc = NormalizeDouble(prc,Digits);

    if (IsTradeAllowed() == true)
    {       
       for(int c=0; c<5; c++)
       {
          RefreshRates();
          Ticket = OrderSend(Symbol(),OP_BUYSTOP,lot,prc,3,SL,TP,eacmd,mgc,0,Blue);
          err    = GetLastError();
          if(err==0)  break;
          else
          {
             Print("Errors opening BUY order");
             Print(ErrorDescription(err),", error ",err);
             if(err==4 || err==137 ||err==146 || err==136)   {Sleep(5000);continue;}
             else break; //normal error                                //Busy errors
          }
       }
    } 	    
    return(Ticket);      
}


// ------------------------------------------------------------------------------------------ //
//                           S E L L   S T O P   F U N C T I O N                              //
// ------------------------------------------------------------------------------------------ //

int SellStop(int mgc, double lot, double prc, double Tpft, double Slos)
{        
      int      Ticket = 0, err = 0;
      double   TP = 0,      SL = 0;
      
      if (Tpft>0)   TP = NormalizeDouble(prc - Tpft * Point , Digits);
      if (Slos>0)   SL = NormalizeDouble(prc + Slos * Point , Digits);
      prc = NormalizeDouble(prc,Digits);

      if (IsTradeAllowed() == true)
      { 
       for(int c=0; c<5; c++)
       { 
         RefreshRates();
         Ticket = OrderSend(Symbol(),OP_SELLSTOP,lot, prc,0,SL,TP,eacmd,mgc,0,Red);
         err    = GetLastError();
         if(err==0)  break;
         else
         {
            Print("Errors opening SELL order");
            Print(ErrorDescription(err),", error ",err);
            if(err==4 || err==137 ||err==146 || err==136)   {Sleep(5000);continue;} 
            else  break; //normal error                               //Busy errors
         }
       }
      } 	    
      return(Ticket);      
}


// ------------------------------------------------------------------------------------------ //
//                                  C L O S E  O R D E R S                                    //
// ------------------------------------------------------------------------------------------ //

void CloseOrders(int mgc)
{
      int cnt,c,total=0,ticket=0,err=0;
      
      if (IsTradeAllowed() == true)
      { 
       total = OrdersTotal();
       for(cnt=total-1;cnt>=0;cnt--)
       {
          OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);

          if(OrderMagicNumber()==mgc && OrderSymbol()==Symbol())
          {
             switch(OrderType())
             {
                case OP_BUY      :
                   for(c=0;c<5;c++)
                   {
                      RefreshRates();
                      OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),3,Yellow);
                      err = GetLastError();
                      if (err==0)   break;
                      else
                      {
                         Print("Errors Closing BUY order");
                         Print(ErrorDescription(err),", error ",err);
                         if(err==0 || err==4 || err==136 || err==137 || err==138 || err==146)
                         { Sleep(5000); continue; }                            // Busy errors
                      }
                   }   
                   break;
               
                case OP_SELL     :
                   for(c=0;c<5;c++)
                   {
                      RefreshRates();
                      OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),3,Yellow);
                      err = GetLastError();
                      if (err==0) break;
                      else
                      {
                         Print("Errors Closing SELL order");
                         Print(ErrorDescription(err),", error ",err);
                         if(err==0 || err==4 || err==136 || err==137 || err==138 || err==146)
                         { Sleep(5000); continue; }                            // Busy errors
                      }
                   }   
                   break;
             } // end of switch
          } // end of if
       } // end of for
      }       
      return(0);
}


// ------------------------------------------------------------------------------------------ //
//                     C L O S E    P E N D I N G   O R D E R S                               //
// ------------------------------------------------------------------------------------------ //

void ClosePendings(int mgc)
{
      int cnt,total=0;
      bool result  = false;
            
      if (IsTradeAllowed() == true)
      { 
       total = OrdersTotal();
       for(cnt=total-1;cnt>=0;cnt--)
       {
          OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);

          if(OrderMagicNumber()==mgc && OrderSymbol()==Symbol())
          {
             switch(OrderType())
             {
                // Close Pending Orders
                // ====================
                case OP_BUYLIMIT  :
                case OP_BUYSTOP   :
                case OP_SELLLIMIT :
                case OP_SELLSTOP  : result = OrderDelete( OrderTicket() );
                      
                break;
             } // end of switch
          } // end of if
       } // end of for
      }      
      return(0);
}


// ------------------------------------------------------------------------------------------ //
//                        E N D   O F   E X P E R T   A D V I S O R                           //
// ------------------------------------------------------------------------------------------ //

