//+------------------------------------------------------------------+
//|                                             MA Martingale v3.mq4 |
//|                                                    Ramiro Alonso |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, Ramiro Alonso - Version 3.3"
#property link      "www.forexfactory.com/forum/Martingale Baggio Method"

#include <stdlib.mqh>
#include <stderror.mqh> //Handles errors.
#include <info.mq4> //Handles information displayed on chart.
#include <log.mq4> //Creates and manages expert log file.
#include <AllOrdersControl.mq4> //Place in memory the array containing orders ejecuted by EA.
                                //It makes faster and secure ejecution of this EA.
#include <OrdersCount.mqh>  //Registers in log file martingale frequency orders statistic.
                              
extern int Magic = 9999;//Number used by EA to identify orders placed by itself and manage them.

extern int TakeProfit=34; //Fixed pips profit target on each order.
extern int PipsStep=32; //Fixed pip loss until a new order is entered in the same way.

extern int MaxTrades = 9; //Max number of orders in a martingale.
extern int EmergencyClose = 9; //Order number to close martingale at break even.

extern bool TrailingProfit=false; //Change take profit of all orders in martingale to the same
            // price of the last one entered.
extern bool TrailingStop=false; //Change stop loss when last order's TP is hit. The rest of the
         //martingale keeps open with a SL in profit, letting profits run.

extern double FactorLot = 2; //Multiplier of previous lotsize. This is the lot size growth factor of the next order.
extern double FactorPips = 1;//Multiplier of previos PipsStep. This is the pip loss growth factor of the next order.
extern int OrdenSalto = 5;//Number of order to make a jump (Salto) on the FactorLot. It could be negative also (fall).
extern double Salto = 1;//Determine size jump on growth of the lot size.

extern double SecureProfit=0.1;//Profit target of any martingale as balance % for close all.

extern int TradesCriticQtty = 4; //If martingale opened order # TradesCriticQtty, then disables
            // the others EA execution, modifying a global variable flag.
            
extern bool TradeOncePerBar=false; //Trades once per bar.

extern bool TradeBands = true;
extern bool TradeMA = true;

extern bool TradeLong = true;
extern bool TradeShort = true;

extern bool ReverseBands=false; //Read inverse the indicator signals. If buy, then sell and viceversa.
extern bool ReverseMA=false;

extern bool MiniAccount=true; //If EA work on a mini or standar.
extern bool mm=true; //If it is "true" EA manage money management as percentage of balance.

extern double risk=0.15; //Lot size of initial trade as percentage of balance
extern double InitialFixedLots=0.01; //Minimum lot size admitted by broker/trader.
extern double MaxLots=50;//Maximum lot size admitted by broker/trader.

extern string MAMethod_desc="0-Simple/ 1-Exponential/ 2-Smoothed/ 3-Weighted";
extern int MAMethod = MODE_SMMA; //Method of Moving Average Indicator.
extern int MAPeriod = 100;//Period of Moving Average Indicator.
extern string MAPrice_desc="0-Close/ 1-Open/ 2-High/ 3-Low/ 4-8 Others";
extern int MAPrice = MODE_OPEN; //Prices of Moving Avergae Indicator.

extern int MALevel = 120; //Detemines the first level from Moving Average.

extern string StopTrading_desc="Stops trading when all opened orders get closed";
extern bool StopTrading = false; //Stops trading if there isn't open orders.

extern int slippage = 40;//Slippage for close orders.

extern string ForceOrderType_desc="Force open trade. 0-Buy/ 1-Sell /6-None";
extern int ForceOrderType = 6;

extern string UpdateVar_Desc="Trader set values when EA lose them by restart";
extern bool UpdateVar = false; //Force variables values update.
extern double NewLastLotSize = 0; //Variable lost
extern int NewMaxTradesAux = 0; //Variable lost
extern int NewPreviousOpenOrders = 0; //variable lost
extern int NewMyOrderType=6; //variable lost

int cnt, cnt2, NumberOfTries = 5, error, leverage=0, LotDecimals=2;
int BandsOrderType = 6, MAOrderType = 6;
double lotsi=0, myLotAux, tp, sl, EnterPrice, SaltoAux;
double PipsStepAux, Margin = 0, StopLoss = 0, BreakEvenPrice = 0;
double BreakEvenAux =0;
string text = "";
bool ContinueOpening=true, MarginFlag = true;
datetime TimeBar = 0; //Used for start trade new martingale only once per bar.

//Static variable called LastLotSize is stored in permanent memory for later retrieve 
//on EA reloading (i.e. after unnormal computer shut down).
static double LastLotSize = 0;
static int MaxTradesAux = 0;
static int PreviousOpenOrders = 0;
static int myOrderType=6;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//-----------  
   
   //This is necessary each time EA needs recognize it opened orders.
   AllOrdersInit(Magic);
   
	if(_ExpertOrdersTotal>0)
   {
     //Si se reinició el EA y no se almacenó el mayor tamaño de lote aseguro este valor.
     //Si bien LastLotSize es una variable static que no se pierde al cerrar el EA
     //aseguro el valor de LastLotSize con _ExpertBiggerLot porque de lo contrario
     //no se van a ingresar las ordenes siguientes necesarias de la martingala.
     //Este valor puede ser erróneo si LastLotSize > 50. _ExpertBiggerLot será igual 50.
     if(LastLotSize <= 0) { LastLotSize = _ExpertBiggerLot; }
     if(PreviousOpenOrders <= 0) { PreviousOpenOrders = _ExpertOrdersTotal; }
     if(myOrderType >= 6) { myOrderType = _ExpertOrdersType; }
   }

//---- Creates a log.txt file to save events information from expert execution.
   string log_file = DoubleToStr(Magic,0);
   log_open( log_file);
   log( "Log file successfully opened at "+TimeToStr(TimeCurrent(),TIME_DATE));
   
   log("LastLotSize:"+DoubleToStr(LastLotSize,2)+" MaxTradesAux:"+
   DoubleToStr(MaxTradesAux,0)+" PreviousOpenOrders:"+DoubleToStr(PreviousOpenOrders,0)+
   " myOrderType:"+DoubleToStr(myOrderType,0));
//---- Detects critics trades
   CheckCriticTrade(10);
      
//---- Creates array for martingales frequency orders.
   if(IsTesting()) init_OrdersCount(MaxTrades);   
   
//---- Creates Labels text for information display.
   info_init(false);
   info_clear();
   
   if(StopTrading==false || IsTradeAllowed() || IsExpertEnabled())
   {
     info( 0, "MA Martingale v3.2 EA is allowed to trade.", Aquamarine, 8);
	  info( 1, "On first tick this message will desapear", Aquamarine );
	}
	else
	{
	   info( 0, "Allow EA trading by setting StopTrading = false", Red, 8 );
	   info( 1, "Press F7 and mark case Allow Live Trading on Common page", Red );
	}
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   Comment("");
   info_clear();
   info_deinit();
  
   if(IsTesting())
   {   
      text = "Frequencia de ordenes en Martingalas |";
      for(int w=0; w<MaxTrades; w++)
      {
         if(groups[w]!=0) 
         {
            text = text+StringConcatenate(" ", DoubleToStr(groups[w],0) )+
            " de "+StringConcatenate(DoubleToStr(w+1,0)," |");
         }
      }
      log(text);    
    }
   
//--------   
   log("LastLotSize:"+DoubleToStr(LastLotSize,2)+" MaxTradesAux:"+
   DoubleToStr(MaxTradesAux,0)+" PreviousOpenOrders:"+DoubleToStr(PreviousOpenOrders,0)+
   " myOrderType:"+DoubleToStr(myOrderType,0));
   
//--------   
   int DeinitReason = UninitializeReason();
   switch(DeinitReason)
   {
        case 0: text="Normal deinit. No forced causes";                          break;
        case 1: text="REASON_REMOVE: Expert removed from chart";                 break;
        case 2: text="REASON_RECOMPILE: Expert recompiled";                      break;
        case 3: text="REASON_CHARTCHANGE: Symbol or timeframe changed on chart"; break;
        case 4: text="REASON_CHARTCLOSE: Chart closed or Test Stopped";          break;
        case 5: text="REASON_PARAMETERS: Input parameters was changed by user";  break;
        case 6: text="REASON_ACCOUNT: Other account activated";                  break;
        default: text="Deinit reason not defined";                               break;
   }

   log("Deinit Reason :"+DeinitReason+" "+text);
   
   log( "Close log file, the expert finishes work at "+TimeToStr(TimeCurrent(),TIME_DATE)+
   " ---------------------------------");
   log_close();
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----   
   //Identifica las ordenes abiertas por el EA y las carga en una matriz para manejarlas
   //mas rápido y unívoco.
   AllOrdersInit(Magic);
  
   //Updates array values with Martingale orders quantity statistic. Only in backtests.
   if (PreviousOpenOrders>_ExpertOrdersTotal && IsTesting())
   {   
	  int numeral = _ExpertOrdersTotal-MaxTradesAux;
	  update_OrdersCount(numeral);
	}
 
   //This condition is necessary for reset PreviousOpenOrders value when every thing is closed,
   //and not before it is closed. If not, some orders could remain opened.
   if(_ExpertOrdersTotal<1)
   {
      //If there isn't opened orders of this MagicEA, avoid execution if it is disabled,
      //and show information about this set up.
      if(StopTrading==true || !IsTradeAllowed() || !IsExpertEnabled() ||
         !CheckCriticTrade(10) && !IsTesting() && ForceOrderType ==6)
      {
         info_clear();
         text = "Magic :"+DoubleToStr(Magic,0);
         if(!CheckCriticTrade(10)) { text=text+" Critic Trade on other EA";}
         info( 0, text,Lime, 8);
         
         if(StopTrading) { text="StopTrading: YES"; }
         else {text="StopTrading: No";}
         
         if(IsTradeAllowed()) { text=text+" IsTradeAllowed: Yes"; }
         else {text=text+" IsTradeAllowed(): NO";}
         
         if(IsExpertEnabled()) { text=text+" IsExpertEnabled: Yes"; }
         else {text=text+" IsExpertEnabled: NO";}
               
         info( 1, text, Aquamarine );
         return;
      }  
      else
      {
          //Reset trading variables values, and let the EA check new trading conditions.
          if(PreviousOpenOrders>_ExpertOrdersTotal && TradeOncePerBar)
          {
            //When full martingale is closed, TimeBar identifies current bar to avoid start
            //a new one in the same bar if parameter is set.
            TimeBar = Time[0]; 
          }
          Comment("");
          LastLotSize = 0;
          MaxTradesAux = 0;
          PreviousOpenOrders = _ExpertOrdersTotal;
          myOrderType=6;
          BreakEvenPrice =0;
          BreakEvenAux = 0;
      }
   }
   
   //Manual variable's update. No matter if there isn't opened orders.
   if(UpdateVar==true)
   {
      LastLotSize = NewLastLotSize;
      MaxTradesAux = NewMaxTradesAux;
      PreviousOpenOrders = NewPreviousOpenOrders;
      myOrderType = NewMyOrderType;
   }

   
   //Si una orden tocó su TP, entonces cierra las demás de la serie si no hay Trailing Stop.
   if (PreviousOpenOrders>_ExpertOrdersTotal && _ExpertOrdersTotal > 0 && !TrailingStop) 
   {	
      //Busca asegurarse que se hayan cerrado todas las ordenes. En fowartest ocurrió que una
      //orden intermedia quedó sin cerrar por un problema momentáneo de conexión.
      //De esta manera el EA cierra todo y luego revisa si efectivamente cerró todo.
      CierraTodo();
      
      //Aseguro que no ingrese nuevas ordenes.
      ContinueOpening=False;
      myOrderType = 6;
      BreakEvenPrice = 0;
      BreakEvenAux = 0;
      
      //Facilita en conteo de ordenes por martingala en back tests.
      if(IsTesting())
      {
         AllOrdersInit(Magic);
         if(_ExpertOrdersTotal<1)
         {
            PreviousOpenOrders = _ExpertOrdersTotal;
         }
      }
      
      MaxTradesAux = 0;
      //Este return es necesario para que no reasigne el valor de PreviousOpenOrders cuando no
      //se cerraron juntas todas las ordenes de una misma martingala.
      return;
   }
   
   //Si una orden tocó su TP, entonces modifica Stop Loss en las restantes de la serie.
   if (PreviousOpenOrders>_ExpertOrdersTotal && _ExpertOrdersTotal > 0 && TrailingStop) 
   {
      //Calculate Stop Loss price for Buy & Sell orders.
      if(_OrderType[0]==OP_BUY)
      {
         StopLoss = NormalizeDouble(_OrderOpenPrice[0],Digits)+MarketInfo(Symbol(),MODE_SPREAD)*Point;
      }
      if(_OrderType[0]==OP_SELL)
      {
         StopLoss = NormalizeDouble(_OrderOpenPrice[0],Digits)-MarketInfo(Symbol(),MODE_SPREAD)*Point;
      }
      //Execute stop loss modification.
      ChangeSL(StopLoss);
      //Reset LastLotSize value. This is thought for further coding development when EA
      //closes the last order only, remaining opened the rest ones, and if the maket
      //continues against the position, EA opens again the last order closed. If it retraces
      //the martingales will close at each TP.
      if(LastLotSize == 0) { LastLotSize = _ExpertBiggerLot;}
      else LastLotSize = LastLotSize/FactorLot;
   }
   
   
   
   //Evalua si se abrieron el maximo de ordenes admitidas, y permite o no abrir nuevas si
   //fuera necesario.
   PreviousOpenOrders=_ExpertOrdersTotal;
   if (_ExpertOrdersTotal>=(MaxTrades+MaxTradesAux)) 
   {
	  ContinueOpening=False;
   } else {
	  ContinueOpening=True;
   }
   
   //Cierra todo si la martingala alcanza un valor mayor o igual a cero a partir de EmergencyClose.
   if(_ExpertProfitTotal>=0 && _ExpertOrdersTotal>=(EmergencyClose+MaxTradesAux))
   {
      CierraTodo();
      ContinueOpening=False;
      myOrderType = 6;
      MaxTradesAux = 0;
      BreakEvenPrice = 0;
      BreakEvenAux = 0;
   }
   
   //Close all if martingale has reach profit target (not take profit price).
   //Or set a stop loss at breakeven/positive price level.
   if(_ExpertProfitTotal>=0)
   {
      //If martingale has reached SecureProfit amount close all or place a stop loss.
      double ProfitTarget = NormalizeDouble(AccountBalance()*SecureProfit/100,2);
      if(_ExpertProfitTotal>=ProfitTarget)
      {
         //If TrainlingStop no set, then close all.
         if(!TrailingStop) { CierraTodo() ; }
      }
      //If Martingale is in profit, place a Stop Loss at breakeven price.
      //If breakeven price isn't known, save it for later use.
      if(TrailingStop && _ExpertOrdersTotal>1)
      {
         if(_OrderType[0]==OP_BUY)
         {
            if(BreakEvenPrice >Bid || BreakEvenPrice ==0) { BreakEvenPrice = Bid; }
            StopLoss = NormalizeDouble(BreakEvenPrice-MarketInfo(Symbol(),MODE_SPREAD)*Point,Digits);
         }
         if(_OrderType[0]==OP_SELL)
         {
            if(BreakEvenPrice <Ask || BreakEvenPrice ==0) { BreakEvenPrice = Ask; }
            StopLoss = NormalizeDouble(BreakEvenPrice+MarketInfo(Symbol(),MODE_SPREAD)*Point,Digits);
         }
         //Execute stop loss modification.
         //ChangeSL(StopLoss);
         if(BreakEvenAux != BreakEvenPrice)
         {
            log("BreakEvenPrice :"+DoubleToStr(BreakEvenPrice,Digits));
            Print("BreakEvenPrice :"+DoubleToStr(BreakEvenPrice,Digits));
            BreakEvenAux = BreakEvenPrice;
         }
      }
   }
   
   
   //Si no hay ninguna orden abierta evalua los indicadores técnicos para ver si se presenta
   //una señal de entrada.
   //No se comienza una nueva martingala en una barra en que se cerró una anterior.
   if (_ExpertOrdersTotal<1 && TimeBar !=Time[0])
   {
      //Reset values before read indicators.
      myOrderType=6;
      BandsOrderType =6;
      MAOrderType = 6; 

     //+------------------------------------------------------+
     //|Check indicators signals for new trading.             |
     //|First check MA bands cross over. Then, check MA cross |
     //+------------------------------------------------------+
	  if(TradeBands && BandsOrderType == 6)
	  {  
	     //First check bands trading.
	     //Identifica una señal de COMPRA = BUY.
	     if(iClose(0,0,0)>(iMA(0,0,MAPeriod,0,MAMethod,MAPrice,0)+(MALevel*Point)))
	     { BandsOrderType=0; }
	  
   	  //Identifica una señal de VENTA = SELL.
	     if(iClose(0,0,0)<(iMA(0,0,MAPeriod,0,MAMethod,MAPrice,0)-(MALevel*Point)))
	     { BandsOrderType=1; }
	     
	     //Invierte la ejecución de la señal. Si señal Buy, entoces Sell y viceversa.
	     if (ReverseBands && BandsOrderType!=6)
	     {
	        switch(BandsOrderType)
	        {
	           case 0: BandsOrderType=1;  break;
	           case 1: BandsOrderType=0;  break;
	        }
	        
	        //Avoid start a new martingale after a big movement, except reverse trading is set.
	        //if(MathAbs(iHigh(0,0,1)-iLow(0,0,1))>MALevel/2*Point) { BandsOrderType=6;}
	     }
	  } //Fin TradeBands
	  
	  // Second signal: check moving average trading.
	  if(TradeMA && MAOrderType == 6)
	  {
	     //Identifica una señal de COMPRA = BUY. 
	     if(iLow(0,0,1)>iMA(0,0,MAPeriod,0,MAMethod,MAPrice,1) &&
	     iLow(0,0,2)>iMA(0,0,MAPeriod,0,MAMethod,MAPrice,2) &&
	     iLow(0,0,3)<iMA(0,0,MAPeriod,0,MAMethod,MAPrice,3) &&
	     iLow(0,0,4)<iMA(0,0,MAPeriod,0,MAMethod,MAPrice,4) &&
	     iOpen(0,0,0)>iMA(0,0,MAPeriod,0,MAMethod,PRICE_HIGH,0))
	     { MAOrderType=0; }
	  
	  
	     //Identifica una señal de VENTA = SELL.
	     if(iHigh(0,0,1)<iMA(0,0,MAPeriod,0,MAMethod,MAPrice,1) &&
	     iHigh(0,0,2)<iMA(0,0,MAPeriod,0,MAMethod,MAPrice,2) &&
	     iHigh(0,0,3)>iMA(0,0,MAPeriod,0,MAMethod,MAPrice,3) &&
	     iHigh(0,0,4)>iMA(0,0,MAPeriod,0,MAMethod,MAPrice,4) &&
	     iOpen(0,0,0)<iMA(0,0,MAPeriod,0,MAMethod,PRICE_LOW,0))
	     { MAOrderType=1; }
	
	     if (ReverseMA && MAOrderType!=6)
	     {
	        switch(MAOrderType)
	        {
	           case 0: MAOrderType=1;  break;
	           case 1: MAOrderType=0;  break;
	        }
	        
	        //Avoid start a new martingale after a big movement, except reverse trading is set.
	        //if(MathAbs(iHigh(0,0,1)-iLow(0,0,1))>MALevel/2*Point) { MAOrderType=6;}
	     }   	     
	   } //Fin TradeMA
	   
	   if(MAOrderType!=6) {myOrderType = MAOrderType;}
	   if(BandsOrderType!=6) {myOrderType = BandsOrderType;}
	   
	   
	   //Disable trade long or trade short.
	   if(myOrderType==0 && !TradeLong) { myOrderType=6;}	     
	   if(myOrderType==1 && !TradeShort) { myOrderType=6;}


      //Force enter a new trade.
	   if(ForceOrderType==0 || ForceOrderType==1) { myOrderType=ForceOrderType; }
	  
	   //if(ForceOrderType<6)
	   //{
	   //   text = "Force new trade ";
	   //   if(ForceOrderType==0) {text = text+"BUY";}
	   //   else {text = text+"SELL";}
	     
	   //if(MessageBox(text,"Manual Trade",MB_YESNO|MB_ICONQUESTION)!=IDYES) {myOrderType=6;}
	   //}	  	   
	         
	} //Fin señales-----------.
	

	//When opened orders is equal to "OrdenSalto", a jump/fall on the lot size growth
   //in next order will increase/decrease equal to "Salto".
   if(_ExpertOrdersTotal==(OrdenSalto+MaxTradesAux-1))SaltoAux=Salto;
   else SaltoAux = 1;
        
   if (!MiniAccount)
   {
      leverage=100000;
      LotDecimals=1;
   }
   else
   {
      leverage=10000;
      LotDecimals=2;
   }
   
   //Determine lot size as % of balance on first order only.
   if(mm && _ExpertOrdersTotal<1)
   { 
      lotsi=NormalizeDouble(AccountBalance()*risk/leverage,LotDecimals);
   }
   
   //Used when initial lot size is fixed.
   if(mm!=true && _ExpertOrdersTotal<1)
   {
      lotsi=InitialFixedLots;
   }
      
   //Si ya hay ordenes abiertas determina el tamaño del lote en función de la última
   //orden abierta en la serie.
   if(_ExpertOrdersTotal>0)
   {
      //Si se reinició el EA y no se almacenó el mayor tamaño de lote aseguro este valor.
      //Si bien LastLotSize es una variable static que no se pierde al cerrar el EA
      //aseguro el valor de LastLotSize con _ExpertBiggerLot porque de lo contrario
      //no se van a ingresar las ordenes siguientes necesarias de la martingala.
      //Este valor puede ser erróneo si LastLotSize > 50. _ExpertBiggerLot será igual 50.
     if(LastLotSize <= 0) { LastLotSize = _ExpertBiggerLot; }
     if(PreviousOpenOrders <= 0) { PreviousOpenOrders = _ExpertOrdersTotal; }
     if(myOrderType >= 6) { myOrderType = _ExpertOrdersType; }
     
     lotsi=NormalizeDouble(LastLotSize*FactorLot*SaltoAux,LotDecimals);
   }
   
   //Asegura que el tamaño del lote sea igual o mayor al InitialFixedLots.
   if(lotsi<=InitialFixedLots) { lotsi=InitialFixedLots; }
   
   //Determina el aumento en la diferencia de pips entre una orden y otra de la martingala.
   PipsStepAux=PipsStep;
   if(_ExpertOrdersTotal>0)
   {
     PipsStepAux=NormalizeDouble(PipsStep*MathPow((1+FactorPips/100),_ExpertOrdersTotal-1),0);  
   }
   
   //Register in log file each new lower free margin produced during testing.
   //Difference between new lower free margin is take in $20 step.
   if(IsTesting() && myOrderType!=6)
   {
      if(Margin == 0) Margin = AccountFreeMargin();
       
      if( NormalizeDouble(AccountFreeMargin(),0) < Margin-20 )
      {  
         log("New lower Free Margin :"+DoubleToStr(AccountFreeMargin(),0));
         Margin = NormalizeDouble(AccountFreeMargin(),0);
      }
   }
   
////////////////////

              
   //Se informa en observaciones de ordenes pendientes el MagicNumber del EA y el número de
   //orden de la serie de la martingala.
   text="Magic: "+DoubleToStr(Magic,0)+". Order: "+(_ExpertOrdersTotal-MaxTradesAux+1)+" of "+MaxTrades;
   
   //+------------------------------------------------------------------------------------------+
   //|Abre ordenes si se dieron las condiciones de los indicadores y si hay margen en la cuenta.|
   //+------------------------------------------------------------------------------------------+
   if(ContinueOpening==true)
   {
   
      int NewOrder;
      switch(myOrderType)
      {
         //BUY
         case 0:
            //Si no hay ordenes abiertas o la última pierde PipsStep abre nuevas ordenes.
            if(_ExpertOrdersTotal<1 ||(_OrderOpenPrice[0]-Ask)>=PipsStepAux*Point)
            {
            
               if(!CheckMarginAviable()) { return; }
               
               EnterPrice=NormalizeDouble(Ask,Digits);
               if(_ExpertOrdersTotal>0) tp=_OrderOpenPrice[0]+(TakeProfit-PipsStep)*Point;
               else tp = Ask+TakeProfit*Point;
               sl = 0;

               //Determina el tamaño del lote inferior a MaxLots.         
               myLotAux = NormalizeDouble(MathMod(lotsi,MaxLots),2);
         
               if(myLotAux!=0)
               {
                  //Reservo el valor del tamaño del lote anterior completo para cuando tenga que
                  //fraccionar una orden en no más de MaxLots ó 50.
                  //Esto tiene que estar dentro del if de "pierde PipsStep". De lo contrario myLotsi
                  //se recalcula con cada pip.
                  NewOrder = AbreOrdenes(myOrderType, PreviousOpenOrders,myLotAux,Blue);

                  if(NewOrder>0) LastLotSize = lotsi; //Si no falló el ingreso de la orden
               }
               
               //If martingale sequence full lot size (lotsi) is bigger than MaxLots, then open
               //so many orders with lot = MaxLots as it is necessary.
               if((lotsi/MaxLots)>=1)
		         {
		             //Determine how many order with lot=MaxLots are necessary
		             cnt2 = NormalizeDouble((lotsi-myLotAux)/MaxLots,0);
		              //If previous calc. is bigger than 0 and less than 1 (i.e. 0.999), then
		              //value is 1.
		             if(cnt2<1) {cnt2=1;}
		             for(cnt=cnt2;cnt>0 ;cnt--)
		             {
		               NewOrder = AbreOrdenes(myOrderType, PreviousOpenOrders,MaxLots,Blue);
		               if(NewOrder>0) MaxTradesAux++;//Si no falló el ingreso de la orden fraccionada
		             }
		         }
		         
		         //Change take profit price if TrailingProfit=true from 2º order to MaxTrades order.
		         if(NewOrder>0 && _ExpertOrdersTotal>0 && TrailingProfit==true)
               {
                  ChangeTP(tp,PreviousOpenOrders);
               }
		         
		         //If lot is exact equal to MaxLots, could be a confusion with MaxTradesAux's
		         //count, because order is placed from second AbreOrdenes. Not from the first
		         //with myLotAux.
		         if(myLotAux==0 && lotsi==MaxLots) { MaxTradesAux--;}
            }
            break;
   
         //SELL
         case 1:
            //Ingresa nuevas ordenes si no hay abiertas o la última pierde PipsStep
            if(_ExpertOrdersTotal<1 ||(Bid-_OrderOpenPrice[0])>=PipsStepAux*Point)
            {
               if(!CheckMarginAviable()) { return; }
               
               EnterPrice=NormalizeDouble(Bid,Digits);
               if(_ExpertOrdersTotal>0) tp=_OrderOpenPrice[0]-(TakeProfit-PipsStep)*Point;
               else tp = Bid-TakeProfit*Point;
               sl = 0;
         
               myLotAux = NormalizeDouble(MathMod(lotsi,MaxLots),2);
		    
               if(myLotAux!=0)
               {
                  NewOrder = AbreOrdenes(myOrderType, PreviousOpenOrders,myLotAux,Red);
                  if(NewOrder>=0) LastLotSize = lotsi; 
               }
       
               if((lotsi/MaxLots)>=1)
		         {
		             cnt2 = NormalizeDouble((lotsi-myLotAux)/MaxLots,0);
		             if(cnt2<1) {cnt2=1;}
		             for(cnt=cnt2;cnt>0 ;cnt--)
		             {
                     NewOrder = AbreOrdenes(myOrderType, PreviousOpenOrders,MaxLots,Red);
                     if(NewOrder>=0) MaxTradesAux++; 
                   }
               }
               
               if(NewOrder>=0 && _ExpertOrdersTotal>0 && TrailingProfit==true)
               {
                  ChangeTP(tp,PreviousOpenOrders);
               }
         
               //Esto sirve para evitar un conteo erroneo de la cantidad de ordenes ingresadas
               //cuando el tamaño del lote de una orden es exactamente igual a MaxLots ó 50.
               if(myLotAux==0 && lotsi==MaxLots) { MaxTradesAux--;}
       
            }
            break;
      }//Fin switch myOrderType
      
      //Si llegó el puntero hasta acá Margin>0 & ninguna orden tocó TP.
      //Esto hay que asignarlo ni bien se ingresa una orden nueva. Ver caso 04/01/07 EURJPY.
      //En un tic se produjo una entrada buy y al siguiente, dio un salto tan alto que se cerró,
      //pero como el EA actualizaba al inicio de un nuevo tic no tenia actualizado la cantidad
      //de ordenes abiertas.
      AllOrdersInit(Magic);
      
      PreviousOpenOrders=_ExpertOrdersTotal;
            
    } //Fin ContinueOpening
   
   //+--------------------------------------------+
   //| Text showed on chart's top left corner.    |
   //+--------------------------------------------+
   string text1 = "Magic :"+DoubleToStr(Magic,0)+
   " - Floating P/L: "+DoubleToStr(_ExpertProfitTotal,2);
   
   if(ReverseBands || ReverseMA) {text1=text1+" Reverse Signal Enabled";}
   
   string text2 = "Orders Opened: "+DoubleToStr(_ExpertOrdersTotal,0)+
   " - Sequence :"+DoubleToStr((_ExpertOrdersTotal-MaxTradesAux),0)+"/"+MaxTrades+
   " - PreviousOpenOrders: "+DoubleToStr(PreviousOpenOrders,0);
   
   string text3 =  "LastLotSize : "+DoubleToStr(LastLotSize,2)+
   " - NextLotSize :"+DoubleToStr(lotsi,2);
   
   switch(myOrderType)
   {
      case 0:  //BUY
         text3=text3+" - Next Enter :"+DoubleToStr(_OrderOpenPrice[0]-PipsStepAux*Point,Digits);
         break;
      case 1: //SELL
         text3=text3+" - Next Enter :"+DoubleToStr(_OrderOpenPrice[0]+PipsStepAux*Point,Digits);
         break;
      default:  //Not defined
         text3=text3+" No Type Order";
         break;
   }
   
   if(ForceOrderType==0) { string text4="FORCE BUY"; }
   else if(ForceOrderType==1) { text4="FORCE SELL"; }
   else text4="Auto Trading";
   
   if(UpdateVar) {text4 = text4+"- Variable´s Update: MANUAL";}
   else {text4 = text4+"- Variable´s Update: Auto";}
   
   //If critic trades quantity is opened, check if global variable semaphore CriticTrades
   //is updated. In this case value must be cero or Magic. Semaphore is restore to cero
   //when complete martingale is closed, by CierraTodo() function.
   //Critic global variable must be delete or modify manually if it is necessary.
   if(_ExpertOrdersTotal>=TradesCriticQtty)
   {
      if(!CriticTrades(10,Magic,0))
      {
         text4=text4+" Critic Trade Not Updated";
      }
   }
     
   if(ContinueOpening==true)
   {
      if(StopTrading==true)
      {
         string text5 = "EA will stop at martingale close";
      }
      else text5 = "ContinueOpening - Account Margin :"+DoubleToStr(AccountFreeMargin(),2);
   }
   else text5 = "No signals or Max Trades Entered - Free Margin"+DoubleToStr(AccountFreeMargin(),2);
   
   //Display information on top left corner.   
   info( 0, text1, Lime, 8 );
	info( 1, text2, Aquamarine );
	info( 2, text3, Aquamarine );
	info( 3, text4, Aquamarine );
	info( 4, text5, Aquamarine );  


//----
   return(0);
  }
//----------------------------  END of ejecution of every market tick.
  

//+------------------------------------------------+
//| Manage martingale closing                      |
//+------------------------------------------------+
void CierraTodo()
{
//----
      
   for(int h=OrdersTotal() ; h>=0; h--)
	{
	  OrderSelect(h, SELECT_BY_POS, MODE_TRADES);
	  if (OrderSymbol()==Symbol() && OrderMagicNumber() == Magic) 
	  {
	     for(int i = 1 ; i <= NumberOfTries; i++)
	     {
	        bool TicketClosed = OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(OrderClosePrice(),Digits),slippage,Yellow);
	        
	        if(!TicketClosed)
   	     {
   	        error = GetLastError(); 
   	        text = "Error :"+error+" "+ErrorDescription(error)+" cerrando orden: "+
   	        DoubleToStr(OrderTicket(),2)+". Reintento :"+DoubleToStr(i,0)+"/"+NumberOfTries;
		        Print(text);
		        log(text);
		        Sleep(5000); //5 segundos
		     }
		     else   break;
	     } //end for i
	        
	     if(!TicketClosed)
   	  {
   	     int error = GetLastError();
   	     text = "No se pudo cerrar orden: "+DoubleToStr(OrderTicket(),0)+" Error: "+error+
   	     " "+ErrorDescription(error);
		     Print(text);
		     log(text);
		  }
	  }
	} //end for h
	
	CheckMarginAviable();
	
	//Restore cero value to semaphore. There isn't any critic martingale from this MagicEA.
	CriticTrades(10, 0, Magic);
	
//----
   return;
} 


//+-----------------------------------------------------------------------------------------+
// Modifies take profit of opened orders to ensure exact and simultaneous close of all the
// martingale. It also avoids problems on internet connection, because take profit is placed
// on broker server.
//+-----------------------------------------------------------------------------------------+
void ChangeTP(double TP, int OrderOnThisMartingale)
{    
   for(int h=0; h<OrdersTotal()-1; h++)
   {
      OrderSelect(h, SELECT_BY_POS, MODE_TRADES);
      
      if (OrderSymbol()==Symbol() && OrderMagicNumber() == Magic) 
	   {
	        //This avoid change TP on the martingale's last/s order/s when its lot size
	        //is bigger than MaxLotSize.
	        if(OrderOnThisMartingale <= 0)
	        { break; }
	    
	        OrderOnThisMartingale--;
	           
	        for(int i = 1 ; i <= NumberOfTries; i++)
	        {
	           bool TicketModify = OrderModify(OrderTicket(),0,0,TP,0,Lime);
	        
	           if(!TicketModify)
   	        {
   	           error = GetLastError(); 
   	           text = "Error :"+error+" "+ErrorDescription(error)+" modificando TP orden: "+
   	           DoubleToStr(OrderTicket(),0)+". Reintento :"+i+"/"+NumberOfTries;
		           Print(text);
		           log(text);
		           Sleep(5000); //5 segundos
		        }
		        else   break;
	        } //end for i
	        
	        if(!TicketModify)
	        {
	           text="No se pudo modificar TP orden :"+OrderTicket();
	           Print(text);
	           log(text);
	        }
	    }   
   } //end for h

//----
   return;
} //End ChangeTP() -----------

//+-------------------------------------------------------+
//|Function for change stop loss on each martingale order |
//+-------------------------------------------------------+
void ChangeSL(double SL)
{        
   for(int h=0; h<OrdersTotal(); h++)
   {
      OrderSelect(h, SELECT_BY_POS, MODE_TRADES);
      
      if (OrderSymbol()==Symbol() && OrderMagicNumber() == Magic) 
	   {
	        for(int i = 1 ; i <= NumberOfTries; i++)
	        {
	           bool TicketModify = OrderModify(OrderTicket(),0,SL,OrderTakeProfit(),0,Lime);
	        
	           if(!TicketModify)
   	        {
   	           error = GetLastError(); 
   	           text = "Error :"+error+" "+ErrorDescription(error)+" modificando SL orden: "+
   	           DoubleToStr(OrderTicket(),0)+". Reintento :"+i+"/"+NumberOfTries;
		           Print(text);
		           log(text);
		           Sleep(5000); //5 segundos
		        }
		        else   break;
	        } //end for i
	        
	        if(!TicketModify)
	        {
	           text="No se pudo modificar SL orden :"+OrderTicket();
	           Print(text);
	           log(text);
	        }
	    }  //end if Symbol & Magic. 
   } //end for h

//----
   return;
} //End ChangeSL() ---------------------------------

//+--------------------------------------------------------+
//  Open new orders and mange errors
//+--------------------------------------------------------+  
int AbreOrdenes(int OrdenTipo, int OrderOnThisMartingale, double Lote, color Color )
{
//----
   
	for(int i = 1 ; i <= NumberOfTries; i++)
	{
	   int TicketOpened = OrderSend(Symbol(),OrdenTipo,Lote,EnterPrice,slippage,sl,tp,text,Magic,0,Color);
	     
	   if(TicketOpened<1)
      {
          error = GetLastError(); 
          text= "Error :"+error+" "+ErrorDescription(error)+" opening orden #"+
          OrderOnThisMartingale+"/"+MaxTrades+". Reintento :"+i+"/"+NumberOfTries;
		    Print(text);
		    log(text);
		    Sleep(10000); //10 segundos
	   }
		else
		{
		   text = "Ticket Opened by EA :"+TicketOpened+" "+text;
		   Print(text);
		   if(!IsTesting()) {log(text);}
		   break;
		}
	 } //end for i
	        
	 if(TicketOpened<1)
    {
       int error = GetLastError();
       text = "Could not open order: "+DoubleToStr(myLotAux,2)+" lots of "+
       Symbol()+" a EnterPrice "+DoubleToStr(EnterPrice,Digits)+
       " & TP: "+DoubleToStr(tp,Digits);
       
	    Print(text);
	    log(text);
	    
	    text= "Error :"+error+" - "+ErrorDescription(error);
	    Print(text);
	    log(text);
	 }
	 
//----
   return(TicketOpened);
} //End AbreOrdenes()-------------------


//+----------------------------------------------------+
//| Avoid enter new order if there isn't enough margin.|
//+----------------------------------------------------+
bool CheckMarginAviable()
{
   string texto;
   //Si no hay margen no hace nada, y la primera vez cambia el estado de MarginFlag
   //para registrar en el log file cada nuevo free margin.
   if(AccountFreeMarginCheck(Symbol(),myOrderType,lotsi)<=0)
   {
      texto = "Free Margin :"+DoubleToStr(AccountFreeMargin(),2)+
      " Not enough margin for next order." ;
      Print(texto);
         
      if(MarginFlag)
      {
         log(texto);
         info( 4, texto, Red );
      }
      MarginFlag = false;
      return(false);
   }
   else if(!MarginFlag)  //If there is enough margin again, it shows the information.
   {
      texto="Free Margin :"+DoubleToStr(AccountFreeMargin(),2)+
      " avaible, enough for new order." ;
      Print(texto);
      log(texto);
      MarginFlag = true;   
   }
   return(true);
}
// End CheckMarginAviable().


//+----------------------------------------------------------------------------------+
//| Used to avoid start new martingales if current opened one reached x orders o more|
//| Initialize a global variable identifying the Magic Number with a critic trade.   |
//+----------------------------------------------------------------------------------+
bool CheckCriticTrade(int Retries)
{
   int _error = 0;
   
   //This function is disabled on testing mode.
   if(!IsTesting())
   {
      for(int i = 1 ; i <= Retries; i++)
      {
         //First check if CriticTrade global variable exists.
         if(GlobalVariableCheck("CriticTrade"))
         {
            //Then leave this for/next loop.
            if(GlobalVariableGet("CriticTrade") ==0 || GlobalVariableGet("CriticTrade") ==Magic)
               { return(true); }
            else {return(false);}
         } //end if GlobalVariableCheck.
         else
         // if the GlobalVariableCheck returns FALSE, it means that it does not exist or  
         // an error has occurred during checking.
         {
            _error = GetLastError();
            // if it is still an error, display information, wait for 0.1 second, and 
            // restart checking.
            if(_error != 0)
            {
               log("CriticTrade()-GlobalVariableCheck(\"CriticTrade\")-Error # "+_error);
               Sleep(100); //0.1 segundo
            }
         } // end else
       
         // if there is no error, it means that there is just no global variable.
         // try to create it. If the GlobalVariableSet > 0, it means that the global variable
         // has been successfully created. Leave the function.
        if(GlobalVariableSet( "CriticTrade", 0.0 ) > 0 ) 
        {
            return(true);
        }
        else
        // if the GlobalVariableSet has returned a value <= 0, it means that an error 
        // occurred at creation of the variable.
        {
          _error = GetLastError();
          // display information, wait for 0.1 second, and try again.
          if(_error != 0)
            {
              log("CriticTrade()-GlobalVariableCheck(\"CriticTrade\")-Error # "+_error );
              Sleep(100);
            }
         }
       
      }//end for.
      
      //If loop for/next is finished it is because an error ocurred, and no solution after
      //retries of GlobalVariableCheck() or GlobalVariableSet().
      return(false);
      
  } //end if !IsTesting().
  
} //end init_CriticTrade


//+-------------------------------------------------------------------------+
//| Before this function is called global variable must exists. EA needs to |
//| change its value, putting on alert the other EAs.                       |
//| Magic Number is used to indentify the EA in problems.                   |
//+-------------------------------------------------------------------------+
bool CriticTrades(int Retries, double NewStatus, double OldStatus)
{
   int _error = 0;
   
   //This function is disabled on testing mode.
   if(!IsTesting())
   {
      for(int i = 1 ; i <= Retries; i++)
      {
         // Try to change value of the CriticTrade from OldStatus to NewStatus
         // if succeed, leave the function returning TRUE ("successfully completed")
         if(GlobalVariableSetOnCondition( "CriticTrade", NewStatus, OldStatus ))
               { return(true); }
         else
         // if not, 2 reasons for it are possible: CriticTrade not equal to OldStatus, 
         // or an error occurred (this is what we will check).
         {
            _error = GetLastError();
            // if it is still an error, display information and try again.
            if(_error != 0)
            {
               log("CriticTrade()-GlobalVariableSetOnCondition(\"CriticTrade\,"+
               DoubleToStr(NewStatus,0)+" "+DoubleToStr(OldStatus,0)+" -Error # "+_error );
               continue;
            }
         }
         // if there is no error, it means that CriticTrade not equal to NewStatus
         // or another expert is executing a trading, then display information and wait...
         Sleep(100); //0.1 segundo.
            
       }//end for.
       
       //If loop for finishes retries means that error couldn't been solved, and variable
       //is not updated.
       return(false);
       
   } //end if !IsTesting().
   
} //end CriticTrade
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++