//+-----------------------------------------------------------------------------------+
//|                                                       TIMING_SYSTEM_EA.mq4 |
//+-----------------------------------------------------------------------------------+

#define doBuy -2
#define doSell 2
#define doStop 0



extern string help_magicGrid_1    = "magic number ordini griglia";
extern string help_magicGrid_2    = "CAMBIARLO SOLO DI 10 IN 10";
extern string help_magicGrid_3    = "es.: 1, 11, 21, ... NON 1, 2, 3, ...";
extern int         magicGrid      = 1000;

extern string help_starLot        = "lotto ordine base";
extern double      startLot       =    0.10;

extern string help_steptime       = "Step Time";
extern double      steptime       =    3;

extern string help_stepip         = "Step Pips";
extern double      stepip         =    5;
double      slip           =    1;

extern string help_Takeprofit     = "Take profit in pip";
extern double      Takeprofit     =   20;
extern string help_Stoploss       = "Stop loss in pip";
extern double      Stoploss       =    5;



extern string help_saveMoney_1    = "soldi MINIMI da SALVARE SUL CONTO (0 = disattivato)";
extern string help_saveMoney_2    = "se EQUITY va sotto chiude TUTTI GLI ORDINI";
extern double      saveMoney      =   0.00;
extern string help_moneyTrail     = "trailing stop IN SOLDI SUL CONTO (0 = disattivato)";
extern double      moneyTrail     =   0.00;
extern string help_dailyProfit    = "obiettivo IN SOLDI PER LA GIORNATA (0 = disattivato)";
extern double      dailyProfit    =   0.00;
extern string help_targetMoney_1  = "obiettivo IN SOLDI SUL CONTO (0 = disattivato)";
extern string help_targetMoney_2  = "se EQUITY raggiunge obiettivo chiude TUTTI GLI ORDINI";
extern double      targetMoney    =   0.00;

/*extern*/ string help_closePending   = "true = oltre ORDINI APERTI cancella ANCHE PENDENTI";
/*extern*/ bool        closePending   =  true;

bool        hedged         =  false; // only internal use

double   iAsk,  iBid;
double   lots,  pip, spread;

int Xsignal;
int    magic       = 100; string comment     = "";
double openPrice   = 0.0; double minPips     = 0.0;
double stopLoss    = 0.0; double lossPrice   = 0.0;
double takeProfit  = 0.0; double profitPrice = 0.0;

datetime firstStart = 0;

bool Buystop = false;
bool Sellstop = false;
int precedente;
double price;
double ordersTP;double minProf;
double xlots;
bool stop = false;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
   //----
   print(WindowExpertName() + " starts...");

   // general cleaning to avoid overlaping
   //ObjectsDeleteAll();
   //HideTestIndicators(true);
   
   // Pseudo code: SE prima volta che avvio programma ALLORA visualizza il nome EA

   // do a first loop to visualize graphics
   // also if market is closed and there aren't ticks
   if (firstStart == 0)
   {
      firstStart = TimeCurrent();
      Alert(WindowExpertName() + " starts at " + TimeToStr(firstStart));
   }
   start();

   //----
   return(0);
}

//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
   //----
   // to close all opened orders
   //closeAll();
   
   // better not to print so let last significative message
   //print("...ForexGump stop");
   
   // no delete so user can see graphics
   // also after EA closure
   //ObjectsDeleteAll();

   //----
   return(0);
}

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
 

   bool                       toTrade;
   if (moneyManagement() < 0) toTrade = false;
   else                       toTrade = true;
   
   int checkSignal = signal();
   
   
     
   if (toTrade && BuyLots() == 0 && SellLots() == 0)
      {
      
       
       if (checkSignal == doBuy)
          {
           magic   = magicGrid;
           lots    = startLot;
           stopLoss =  NormalizeDouble(Stoploss, Digits);
           takeProfit = NormalizeDouble(Takeprofit, Digits);
           comment = "Apertura Ordine Buy ";
           // if order ok then reset also hedged to allow it
           buy( Symbol());
           stop = false;
          }
       
       else if (checkSignal == doSell)
          {
           magic   = magicGrid;
           lots    = startLot;
           stopLoss =  NormalizeDouble(Stoploss, Digits);
           takeProfit = NormalizeDouble(Takeprofit, Digits);
           comment = "Apertura Ordine Sell ";
           sell(Symbol());
           stop = false;
          }
      }
   
   else {}
   
   Comment( "==========================",".\n",
            "Powered by Massmarco80    ",".\n",
            "magicGrid     ",(magicGrid ),".\n",
            "startlot      ",(startLot ),".\n",                  
            "Soglia PIP    ", (stepip * pip),".\n",           
            "Segnale  ", (checkSignal),".\n",            
            "==========================",".");
   
   
   
 
   
   return(0);
  }

//+------------------------------------------------------------------+
//| Funzioni                                                         |
//+------------------------------------------------------------------+

int time ()
     {
      
      if (Seconds() > precedente)
        {
          if (Seconds() - precedente > steptime+slip) precedente = Seconds() ;
          else {}
        }
      else if (precedente > Seconds())
        {
          if ((60 - precedente) + Seconds() > steptime+slip) precedente = Seconds() ;
          else  {}
        }
      return (precedente);
     }

double pips ()
     {
      int var = time();
      //double price;
      if (time() == Seconds()) price = Bid;
      return (Bid - price);
     } 
     
    
int signal()
{

   
   
   
   
   
   
  
   
   if (ObjectFind( "SECOND") < 0)
   {
      ObjectCreate("SECOND", OBJ_LABEL,         0, 0, 0);
      ObjectSet(   "SECOND", OBJPROP_BACK,      false);
      ObjectSet(   "SECOND", OBJPROP_CORNER,    1);
      ObjectSet(   "SECOND", OBJPROP_XDISTANCE, 10);
      ObjectSet(   "SECOND", OBJPROP_YDISTANCE, 65);
   }
   ObjectSetText(  "SECOND", "SECOND " + DoubleToStr(time (), 2)  , 12, "Tahoma", MediumBlue);
  
   
   if (ObjectFind( "PIPS") < 0)
   {
      ObjectCreate("PIPS", OBJ_LABEL,         0, 0, 0);
      ObjectSet(   "PIPS", OBJPROP_BACK,      false);
      ObjectSet(   "PIPS", OBJPROP_CORNER,    1);
      ObjectSet(   "PIPS", OBJPROP_XDISTANCE, 10);
      ObjectSet(   "PIPS", OBJPROP_YDISTANCE, 85);
   }
   
   
   ObjectSetText(  "PIPS", "PIPS " +  DoubleToStr(pips ()/pip, 1) , 12, "Tahoma", Red);
  
   
    if (ObjectFind( "STEP") < 0)
   {
      ObjectCreate("STEP", OBJ_LABEL,         0, 0, 0);
      ObjectSet(   "STEP", OBJPROP_BACK,      false);
      ObjectSet(   "STEP", OBJPROP_CORNER,    1);
      ObjectSet(   "STEP", OBJPROP_XDISTANCE, 10);
      ObjectSet(   "STEP", OBJPROP_YDISTANCE, 105);
   }
   
   
   ObjectSetText(  "STEP", "STEP " +  DoubleToStr(stepip , 1) , 12, "Tahoma", MediumBlue);
   
   
 if (pips() > stepip*pip) return (doBuy);
 else if (pips() < -1*stepip*pip) return (doSell);
 else return (doStop);
   
   
 

}

// Funzione print per la scritta a centro grafico
   
int print(string text, bool flashing = false)
{
   if (ObjectFind( "Check text") < 0)
   {
      ObjectCreate("Check text", OBJ_LABEL,         0, 0, 0);
      // back means it paitns the background
      ObjectSet(   "Check text", OBJPROP_COLOR,     Yellow);
      ObjectSet(   "Check text", OBJPROP_BACK,      true);
      ObjectSet(   "Check text", OBJPROP_CORNER,    0);
      ObjectSet(   "Check text", OBJPROP_XDISTANCE, 300);
      ObjectSet(   "Check text", OBJPROP_YDISTANCE, 50);
   }
   ObjectSetText(  "Check text", TimeToStr(iTime(NULL, PERIOD_M1, 0), TIME_MINUTES) + " " + text, 12, "Tahoma");

   // flashing effect
   if      (flashing && ObjectGet("Check text", OBJPROP_COLOR) == Yellow) ObjectSet("Check text", OBJPROP_COLOR, Red);
   else if (flashing && ObjectGet("Check text", OBJPROP_COLOR) == Red)   ObjectSet("Check text", OBJPROP_COLOR, Yellow);
   else                                                                  ObjectSet("Check text", OBJPROP_COLOR, Yellow);

   // for debugging porpouses uncomment the print
   // to log journal and mt4 file
   //Print(text);

   return(0);
}


   
double BuyLots()
   {
   int lot;
   double BLotti=0.0;
   int total  = OrdersTotal(); 
   for(lot = 0; lot < total; lot++)
      {
      OrderSelect(lot, SELECT_BY_POS, MODE_TRADES);
      if (OrderMagicNumber()==magicGrid && OrderType()==OP_BUY ) 
      {
       BLotti =NormalizeDouble((BLotti + OrderLots()),2);
       }
      }
      //Comment(" Numero lotti" +(NumeroLotti ));   
      return(BLotti); 
       
   }
   
double SellLots()
   {
   int lot;
   double SLotti=0.0;
   int total  = OrdersTotal(); 
   for(lot = 0; lot < total; lot++)
      {
      OrderSelect(lot, SELECT_BY_POS, MODE_TRADES);
      if (OrderMagicNumber()==magicGrid && OrderType()==OP_SELL ) 
      {
       SLotti =NormalizeDouble((SLotti + OrderLots()),2);
       }
      }
      //Comment(" Numero lotti" +(NumeroLotti ));   
      return(SLotti); 
       
   } 
 


int checkPoint(string symbol)
{
   RefreshRates();

   // Calcola l'esatta fazione del cross valutazio che si sta utilizzando
   // serve per trasformare i pips in virgola esatta.
   double   iPoint =  MarketInfo(symbol, MODE_POINT);
   if      (iPoint == 0.01)    pip = 0.01;
   else if (iPoint == 0.001)   pip = 0.01;
   else if (iPoint == 0.0001)  pip = 0.0001;
   else if (iPoint == 0.00001) pip = 0.0001;

   // Calcolo lo soread differenza tra Prezzo di acquisto e vendita 

   iBid = MarketInfo(symbol, MODE_BID);
   iAsk = MarketInfo(symbol, MODE_ASK);

   spread = NormalizeDouble((iAsk - iBid)/pip, Digits);

   // Calcolo il numero di pips minimi che accetta il Broker per ordini Stop e Take
   double iDigits =  MarketInfo(symbol, MODE_DIGITS);
   if (   iDigits == 3 || iDigits == 5) minPips = MarketInfo(symbol, MODE_STOPLEVEL)/10;
   else                                 minPips = MarketInfo(symbol, MODE_STOPLEVEL);

   // Scritta in basso a destra Valuta + Spread
   if (symbol == Symbol())
   {
      if (ObjectFind( "Spread") < 0)
      {
         ObjectCreate("Spread", OBJ_LABEL, 0, 0, 0);
         ObjectSet(   "Spread", OBJPROP_BACK, true);
         ObjectSet(   "Spread", OBJPROP_CORNER, 3);
         ObjectSet(   "Spread", OBJPROP_XDISTANCE, 10);
         ObjectSet(   "Spread", OBJPROP_YDISTANCE, 10);
      }
      ObjectSetText(  "Spread", Symbol() + " spread " + DoubleToStr(spread, 1) + " pips " + " Candle Time " + TimeToStr((TimeCurrent() - iTime (0,0,0)),TIME_SECONDS)  , 12, "Tahoma", Red);
   }

   return(0);
}

double   moneyStop        = 0.0;
double   yesterTot        = 0.0; int yesterOrd     = 0;
double   yesterTake       = 0.0; int yesterOrdTake = 0;
double   yesterLoss       = 0.0; int yesterOrdLoss = 0;
datetime lastMoneyUpdate  =   0;

int moneyManagement()
{
   checkPoint(Symbol());

   // Qui mi calcola il trailing stop sul conto a inizio giornata ( Totale conto meno i soldi impostati nelle variabili )
   // Esempio, ho conto da 300 e voglio rischiare 100, monei stop sarà 200 se conto sali ex. 320 moneystop = 220
   if (moneyTrail == 0) moneyStop = 0;
   else                 moneyStop = MathMax(moneyStop, AccountEquity() - moneyTrail);
   
   // printStop il prezzo limite terrà conto anche del savemoney impostato tra le variabili perciò usarà il più alto
   double               printStop = MathMax(moneyStop, saveMoney);

   // if case update IIS7 data file

   if (iTime(NULL, PERIOD_M1, 0) != lastMoneyUpdate)
   {
      lastMoneyUpdate = iTime(NULL, PERIOD_M1, 0);

      int handle;
      handle = FileOpen("ForexGump " + AccountNumber() + ".htm", FILE_BIN|FILE_WRITE);

      if(handle < 1)
      {
         Alert(Symbol(), " Error updating account data log file");
      }
      else
      {
         FileWrite(handle, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
         FileWrite(handle, "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>ForexGump<title></title></head><body>");
         FileWrite(handle, TimeToStr(iTime(NULL, PERIOD_M1, 0), TIME_DATE|TIME_SECONDS), "<br/>");
         FileWrite(handle, "Account ", AccountNumber(), "<br/>");
         FileWrite(handle, AccountName(), "<br/><br/>");

         FileWrite(handle, "Balance ", AccountBalance(), " €<br/>");
         FileWrite(handle, "Equity ", AccountEquity(), " €<br/>");
         FileWrite(handle, "Free margin ", DoubleToStr(AccountFreeMargin(), 2), " €<br/>");
         FileWrite(handle, "Money stop at ", printStop, " €<br/>");

         int pos; double orderTot = 0.0;
         FileWrite(handle, "<br/>Running orders<br/>");
         for (pos = 0; pos < OrdersTotal(); pos++)
         {
            OrderSelect(pos, SELECT_BY_POS, MODE_TRADES);
            if (OrderType() == OP_BUY || OrderType() == OP_SELL)
            {
               FileWrite(handle, OrderSymbol(), " ", OrderLots(), " ", OrderComment(), " ", OrderProfit(), " €<br/>");
               orderTot += OrderProfit();
            }
         }
         FileWrite(handle, "<br/>Running tot ", orderTot, " €<br/>");

         FileWrite(handle, "<br/>Waiting orders<br/>");
         for (pos = 0; pos < OrdersTotal(); pos++)
         {
            OrderSelect(pos, SELECT_BY_POS, MODE_TRADES);
            if (OrderType() == OP_BUYSTOP || OrderType() == OP_SELLSTOP)
            {
               FileWrite(handle, TimeToStr(OrderOpenTime(), TIME_DATE|TIME_MINUTES), " ", OrderSymbol(), " ", 
                                 OrderLots(), " ", OrderComment(), "<br/>");
            }
         }

         orderTot  = 0.0;           int    orderOrd     = 0;
         int    orderOrdTake = 0;   int    orderOrdLoss = 0;
         double orderTake    = 0.0; double orderLoss    = 0.0;
         FileWrite(handle, "<br/>Today closed<br/>");
         for (pos = 0; pos < OrdersHistoryTotal(); pos++)
         {
            OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY);
            if ((OrderType() == OP_BUY || OrderType() == OP_SELL) &&
                TimeDayOfWeek(OrderCloseTime()) == TimeDayOfWeek(iTime(NULL, PERIOD_M5, 0)))
            {
               FileWrite(handle, OrderSymbol(), " ", OrderLots(), " ", OrderComment(), " ", OrderProfit(), " €<br/>");
               orderTot += OrderProfit(); orderOrd += 1;
               if (OrderProfit() > 0) {orderTake += OrderProfit(); orderOrdTake += 1;}
               if (OrderProfit() < 0) {orderLoss -= OrderProfit(); orderOrdLoss += 1;}
            }
         }
         FileWrite(handle, "<br/>Today tot ", orderOrdTake, " x ", orderTake, " € - ", 
                           orderOrdLoss, " x ", orderLoss, " € = ", orderOrd, " x ", orderTot, " €<br/>");

         // calculate yesterday total only the first time
         // since then it can't change till the next day
         if (yesterTot == 0 || TimeDayOfWeek(iTime(NULL, PERIOD_M5, 0)) != TimeDayOfWeek(iTime(NULL, PERIOD_M5, 1)))
         {
            yesterTot  = 0; yesterOrd     = 0;
            yesterTake = 0; yesterOrdTake = 0;
            yesterLoss = 0; yesterOrdLoss = 0;
            
            for (pos = 0; pos < OrdersHistoryTotal(); pos++)
            {
               OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY);
               if ((OrderType() == OP_BUY || OrderType() == OP_SELL) &&
                   TimeDayOfWeek(OrderCloseTime()) == TimeDayOfWeek(iTime(NULL, PERIOD_M5, 0) - 24*60*60))
               {
                  yesterTot += OrderProfit(); yesterOrd +=1;
                  if (OrderProfit() > 0) {yesterTake += OrderProfit(); yesterOrdTake += 1;}
                  if (OrderProfit() < 0) {yesterLoss -= OrderProfit(); yesterOrdLoss += 1;}
               }
            }
         }
         FileWrite(handle, "Yestd tot ", yesterOrdTake, " x ", yesterTake, " € - ", 
                           yesterOrdLoss, " x ", yesterLoss, " € = ", yesterOrd, " x ", yesterTot, " €<br/>");

         FileWrite(handle, "</body></html>");
         FileClose(handle);
      }
   }

   // Scritta in basso al centro grafico Equity + Stop sul conto richiama printStop
   
   if (ObjectFind("Account Alarm") < 0)
   {
      ObjectCreate("Account Alarm", OBJ_LABEL, 0, 0, 0);
      ObjectSet(   "Account Alarm", OBJPROP_BACK, true);
      ObjectSet(   "Account Alarm", OBJPROP_CORNER, 2);
      ObjectSet(   "Account Alarm", OBJPROP_XDISTANCE, 10);
      ObjectSet(   "Account Alarm", OBJPROP_YDISTANCE,  10);
   }

   ObjectSetText(  "Account Alarm", "Equity "     + DoubleToStr(AccountEquity(), 2) + 
                                    " € stop at " + DoubleToStr(printStop, 2) + " €", 12, "Tahoma", White);

   if      (printStop/AccountEquity() > 0.95) ObjectSet("Account Alarm", OBJPROP_COLOR, Red);
   else if (printStop/AccountEquity() > 0.80) ObjectSet("Account Alarm", OBJPROP_COLOR, Yellow);
   else                                       ObjectSet("Account Alarm", OBJPROP_COLOR, Lime);

   
   // Funzione Take Profit su tutti gli ordini
   
   if (ordersTP  != 0)
   {
      double openProfit = 0.0;
      for(pos = 0; pos < OrdersTotal(); pos++)
      {
         OrderSelect(pos, SELECT_BY_POS, MODE_TRADES);
         if   (OrderMagicNumber() < magicGrid ||  OrderMagicNumber() > magicGrid+10) {continue;}
         else  openProfit += OrderProfit();
      }

      if (openProfit >= ordersTP)
      {      
         // here must count closing orders because if it closes only some order
         // then next loop the openProfit will be less than take and others will stay open
         int     closingOrders = 1;
         while ( closingOrders > 0)
         {
                 closingOrders = 0;
            for (pos = 0; pos < OrdersTotal(); pos++)
            {
               OrderSelect(pos, SELECT_BY_POS, MODE_TRADES);
               if      (OrderMagicNumber() < magicGrid ||  OrderMagicNumber() > magicGrid+10) {continue;}
               // ignore errors because this saveMoney check is repeted every start() round
               else if (OrderType() == OP_BUY)             {closingOrders += 1; lots = OrderLots(); close(OrderTicket());}
               else if (OrderType() == OP_SELL)            {closingOrders += 1; lots = OrderLots(); close(OrderTicket());}
               else if (!closePending)                     {continue;} // if pending isn't set then stop here and leave pending orders 
               else if (OrderType() == OP_BUYSTOP)         {OrderDelete(OrderTicket());}
               else if (OrderType() == OP_SELLSTOP)        {OrderDelete(OrderTicket());}
               else if (OrderType() == OP_BUYSTOP)         {OrderDelete(OrderTicket());}
               else if (OrderType() == OP_SELLSTOP)        {OrderDelete(OrderTicket());}
               else if (OrderType() == OP_BUYLIMIT)        {OrderDelete(OrderTicket());}
               else if (OrderType() == OP_SELLLIMIT)       {OrderDelete(OrderTicket());}
            }
         }
         hedged = false;
         print("OK !!! ORDERS TAKE PROFIT HIT !!!", true);
         // but here not to block trading must restart after orders closure
         // no return at all to continue the money management testing
      }
   }

   // Qui chiude tutto se raggiunge il Daily profit
   
   if (dailyProfit != 0)
   {
      string today = TimeToStr(TimeCurrent(), TIME_DATE);
      double totProfit = 0.0;
      for(pos = 0; pos < OrdersHistoryTotal(); pos++)
      {
         OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY);
         if       (OrderMagicNumber() < magicGrid ||  OrderMagicNumber() > magicGrid+10) {continue;}
         else  if (TimeToStr(OrderOpenTime(), TIME_DATE) == today) totProfit += OrderProfit();
      }

      if (totProfit >= dailyProfit)
      {      
         for (pos = 0; pos < OrdersTotal(); pos++)
         {
            OrderSelect(pos, SELECT_BY_POS, MODE_TRADES);
            if      (OrderMagicNumber() < magicGrid ||  OrderMagicNumber() > magicGrid+10) {continue;}
            else if (OrderType() == OP_BUY) { lots = OrderLots();     close(OrderTicket());}
            else if (OrderType() == OP_SELL){ lots = OrderLots();     close(OrderTicket());}
            else if (!closePending)               continue; // if pending isn't set then stop here and leave pending orders
            else if (OrderType() == OP_BUYSTOP)   OrderDelete(OrderTicket());
            else if (OrderType() == OP_SELLSTOP)  OrderDelete(OrderTicket());
            else if (OrderType() == OP_BUYSTOP)   OrderDelete(OrderTicket());
            else if (OrderType() == OP_SELLSTOP)  OrderDelete(OrderTicket());
            else if (OrderType() == OP_BUYLIMIT)  OrderDelete(OrderTicket());
            else if (OrderType() == OP_SELLLIMIT) OrderDelete(OrderTicket());
         }

         print("OK !!! DAILY TARGET HIT !!!", true);
         return(-1); 
      }
   }

   // Qui funzione per  targhet giornaliero, se imposto più bassa del conto da errore, altrimenti chiude tutti quando equity raggiunge importo. 
   if (targetMoney != 0 && targetMoney <= AccountBalance())
   {
      print("ERROR: targetMoney parameters IS LESS THAN account!!!", true);
      Alert("ERROR: targetMoney parameters IS LESS THAN account!!!");
      return(-1);
   }

   if (targetMoney != 0 && AccountEquity() >= targetMoney)
   {
      for (pos = 0; pos < OrdersTotal(); pos++)
      {
         OrderSelect(pos, SELECT_BY_POS, MODE_TRADES);
         if      (OrderMagicNumber() < magicGrid ||  OrderMagicNumber() > magicGrid+10) {continue;}
         else if (OrderType() == OP_BUY) { lots = OrderLots();     close(OrderTicket());}
         else if (OrderType() == OP_SELL) { lots = OrderLots();    close(OrderTicket());}
         else if (!closePending)               continue; // if pending isn't set then stop here and leave pending orders
         else if (OrderType() == OP_BUYSTOP)   OrderDelete(OrderTicket());
         else if (OrderType() == OP_SELLSTOP)  OrderDelete(OrderTicket());
         else if (OrderType() == OP_BUYSTOP)   OrderDelete(OrderTicket());
         else if (OrderType() == OP_SELLSTOP)  OrderDelete(OrderTicket());
         else if (OrderType() == OP_BUYLIMIT)  OrderDelete(OrderTicket());
         else if (OrderType() == OP_SELLLIMIT) OrderDelete(OrderTicket());
      }

      print("OK !!! ACCOUNT TARGET HIT !!!", true);
      return(-1); 
   }

   // Funzione che chiude tutto quando raggiunge saveMoney (impostato tra parametri esterni)
   if (saveMoney != 0 && AccountEquity() <= saveMoney)
   {
      // immediatly close ALL orders
      for (pos = 0; pos < OrdersTotal(); pos++)
      {
         OrderSelect(pos, SELECT_BY_POS, MODE_TRADES);
         if      (OrderMagicNumber() < magicGrid ||  OrderMagicNumber() > magicGrid+10) {continue;}
         else if (OrderType() == OP_BUY)  { lots = OrderLots();    close(OrderTicket());}
         else if (OrderType() == OP_SELL)  { lots = OrderLots();   close(OrderTicket());}
         else if (!closePending)               continue; // if pending isn't set then stop here and leave pending orders
         else if (OrderType() == OP_BUYSTOP)   OrderDelete(OrderTicket());
         else if (OrderType() == OP_SELLSTOP)  OrderDelete(OrderTicket());
         else if (OrderType() == OP_BUYSTOP)   OrderDelete(OrderTicket());
         else if (OrderType() == OP_SELLSTOP)  OrderDelete(OrderTicket());
         else if (OrderType() == OP_BUYLIMIT)  OrderDelete(OrderTicket());
         else if (OrderType() == OP_SELLLIMIT) OrderDelete(OrderTicket());
      }

      print("SAVE MONEY STOP: GAME OVER !!!", true);
      return(-1); 
   }

   // Funzione che chiude tutto quando raggiunge moneystop (impostato tra parametri esterni)
   if (moneyStop != 0 && AccountEquity() <= moneyStop)
   {
      // find and close all orders to preserve equity
      // included the pending or they could start and be immediatly closed
      for (pos = 0; pos < OrdersTotal(); pos++)
      {
         OrderSelect(pos, SELECT_BY_POS, MODE_TRADES);
         if      (OrderMagicNumber() < magicGrid ||  OrderMagicNumber() > magicGrid+10) {continue;}
         else if (OrderType() == OP_BUY)  { lots = OrderLots();    close(OrderTicket());}
         else if (OrderType() == OP_SELL)  { lots = OrderLots();   close(OrderTicket());}
         else if (!closePending)               continue;
         else if (OrderType() == OP_BUYSTOP)   OrderDelete(OrderTicket());
         else if (OrderType() == OP_SELLSTOP)  OrderDelete(OrderTicket());
         else if (OrderType() == OP_BUYSTOP)   OrderDelete(OrderTicket());
         else if (OrderType() == OP_SELLSTOP)  OrderDelete(OrderTicket());
         else if (OrderType() == OP_BUYLIMIT)  OrderDelete(OrderTicket());
         else if (OrderType() == OP_SELLLIMIT) OrderDelete(OrderTicket());
      }

      print("TRAILING MONEY STOP: GAME OVER !!!", true);
      // block any further trading
      return(-1);
   }

   /*
   // if too close to moneyStop then suspend new orders
   if (moneyStop != 0 && AccountEquity() <= moneyStop*1.10)
   {
      print("Trading temporarily suspended, too little money...", true);
      return(-1);
   }

   // eventually avoid also to send orders if no enought free margin
   if (MarketInfo(Symbol(), MODE_MARGINREQUIRED)*lots > AccountFreeMargin())
   {
      print("TRADING SUSPENDED: NOT ENOUGHT FREE MARGIN...", true);
      return(-1);
   }
   */

   // in case nothing "happened" before return 0 to allow normal trading
   return(0);
}

//+------------------------------------------------------------------+
//| function to buy                                                  |
//+------------------------------------------------------------------+
string lastBuySymbol = "";
datetime lastBuyTime = 0;
double lastBuyPrice = 0.0;
int lastBuyMagic = 0;

int buy(string symbol, bool force = false)
{
   // with an Ask order we use Bid and in the stop loss the contrary for Bid orders "Bid - stopLoss*pip"
   // but using moving average cross the stop loss is in the code check itself
   checkPoint(symbol);
   double iDigits = MarketInfo(symbol, MODE_DIGITS);
   
   double stop = 0.0;
   if (stopLoss > 0) stop = NormalizeDouble(iBid - stopLoss*pip, iDigits);
   if (lossPrice > 0) stop = NormalizeDouble(lossPrice, iDigits);
   
   double take = 0.0;
   if (takeProfit > 0) take = NormalizeDouble(iAsk + takeProfit*pip, iDigits);
   if (profitPrice > 0) take = NormalizeDouble(profitPrice, iDigits);

   // reset global variables to avoid to use the same for other orders...
   stopLoss   = 0.0; lossPrice   = 0.0;
   takeProfit = 0.0; profitPrice = 0.0;
   
   double price = NormalizeDouble(iAsk, iDigits);
   if (comment == "") comment = "Buy order by Massmarco";

   // filter to avoid 146 multiple orders error on real account!!
   if (symbol == lastBuySymbol && magic == lastBuyMagic &&
       (TimeCurrent() - lastBuyTime) < 5 && MathAbs(price - lastBuyPrice) < 5*pip)
   {
      print("Blocked " + symbol + " " + comment + " multiple orders");
      lastBuyTime = TimeCurrent();
      return(-1);
   }

   // before check whether identical order is already placed
   int total = OrdersTotal();
   for (int pos = 0; pos < total; pos++)
   {
      if (OrderSelect(pos, SELECT_BY_POS, MODE_TRADES) == false)
      {
         print("OrderSelect error in BUY " + symbol + " #" + GetLastError());
         continue;
      }
/*
      // without magic check we block every other order on the same price
      // or use the parameter "force" to block orders only with same magic
      if (OrderSymbol() == symbol && (!force || OrderMagicNumber() == magic) &&
          (OrderType() == OP_BUY || OrderType() == OP_BUYSTOP) && MathAbs(OrderOpenPrice() - price) < 5*pip)
      {
         print("Blocked " + symbol + " " + comment + " same price orders");
         return(-1);
      }*/
   }

   int ticket = OrderSend(symbol, OP_BUY, lots, price, 0, stop, take, comment, magic, 0, Green);
   if (ticket < 0) {print("BUY " + symbol + " " + comment + " error #" + GetLastError()); return(-1);}
   else print("BUY " + ticket + " " + symbol + " " + comment + " sent ok");

   // set last sent order params here after positive opening   
   lastBuySymbol = symbol;
   lastBuyTime = TimeCurrent();
   lastBuyPrice = price; lastBuyMagic = magic;
   
   // in every case wait a bit to allow elaborations and avoid overlaping
   // ever if an error occured to avoid to immediatrly resend the order
   Sleep(5000);
   // set orderState in checkPosition because orders could
   // be closed or changed outside of buy() sell() or closeAll()
   return(ticket);
}



//+------------------------------------------------------------------+
//| function to sell                                                 |
//+------------------------------------------------------------------+
string lastSellSymbol = "";
datetime lastSellTime = 0;
double lastSellPrice = 0.0;
int lastSellMagic = 0;

int sell(string symbol, bool force = false)
{
   checkPoint(symbol);
   double iDigits = MarketInfo(symbol, MODE_DIGITS);

   double stop = 0.0;
   if (stopLoss > 0) stop = NormalizeDouble(iAsk + stopLoss*pip, iDigits);
   if (lossPrice > 0) stop = NormalizeDouble(lossPrice, iDigits);
   
   double take = 0.0;
   if (takeProfit > 0) take = NormalizeDouble(iBid - takeProfit*pip, iDigits);
   if (profitPrice > 0) take = NormalizeDouble(profitPrice, iDigits);

   // reset global variables to avoid to use the same for other orders...
   stopLoss   = 0.0; lossPrice   = 0.0;
   takeProfit = 0.0; profitPrice = 0.0;
   
   double price = NormalizeDouble(iBid, iDigits);
   if (comment == "") comment = "Sell order by Massmarco";

   // filter to avoid multiple orders error on real account!!
   if (symbol == lastSellSymbol && magic == lastSellMagic &&
       (TimeCurrent() - lastSellTime) < 5 && MathAbs(price - lastSellPrice) < 5*pip)
   {
      print("Blocked " + symbol + " " + comment + " multiple orders");
      lastSellTime = TimeCurrent();
      return(-1);
   }
    
   int total = OrdersTotal();
   for (int pos = 0; pos < total; pos++)
   {
      if (OrderSelect(pos, SELECT_BY_POS, MODE_TRADES) == false)
      {
         print("OrderSelect error in SELL " + symbol + " #" + GetLastError());
         continue;
      }
/*
      if (OrderSymbol() == symbol && (!force || OrderMagicNumber() == magic) &&
          (OrderType() == OP_SELL || OrderType() == OP_SELLSTOP) && MathAbs(OrderOpenPrice() - price) < 5*pip)
      {
         print("Blocked " + symbol + " " + comment + " same price orders");
         return(-1);
      }*/
   }

   int ticket = OrderSend(symbol, OP_SELL, lots, price, 0, stop, take, comment, magic, 0, Red);
   if (ticket < 0) {print("SELL " + symbol + " " + comment + " error #" + GetLastError()); return(-1);}
   else print("SELL " + ticket + " " + symbol + " " + comment + " sent ok");
   
   lastSellSymbol = symbol;
   lastSellTime = TimeCurrent();
   lastSellPrice = price; lastSellMagic = magic;

   Sleep(5000);
   return(ticket);
}



//+------------------------------------------------------------------+
//| function to close open positions                                 |
//+------------------------------------------------------------------+

// function to close a specific order
// fast = false waits 5 seconds after the closure to allow broker elaboration
// fast = true to "accelerate" program execution
void close(int ticket, bool fast = true)
{
   checkPoint(Symbol());

   if (OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES) == false)
   {
      print(Symbol() + " OrderSelect error in closing " + ticket + " #" + GetLastError());
   }

   if (OrderType() == OP_BUY)
   {
      if (!OrderClose(OrderTicket(), lots, NormalizeDouble(Bid, Digits), 0, Orange))
      {
         print(Symbol() + " error closing BUY order " + ticket + " #" + GetLastError());
      }
      else if (Symbol() == lastBuySymbol) {lastBuySymbol = "";  lastBuyTime = 0;  lastBuyPrice = 0;  lastBuyMagic = 0;}
   }
   else if (OrderType() == OP_SELL)
   {
      if (!OrderClose(OrderTicket(), lots, NormalizeDouble(Ask, Digits), 0, Orange))
      {
         print(Symbol() + " error closing SELL order " + ticket + " #" + GetLastError());
      }
      else if (Symbol() == lastSellSymbol) {lastSellSymbol = ""; lastSellTime = 0; lastSellPrice = 0; lastSellMagic = 0;}
   }
   else // then it's a pending STOP or LIMIT order
   {
      if (!OrderDelete(OrderTicket(), Red))
      {
         print(Symbol() + " error deleting PENDNG order " + ticket + " #" + GetLastError());
      }
   }
   
   // also in closing better wait for samo second
   // to allow sending and elaboration
   print(Symbol() + " close order " + ticket + " OK!");
   if (!fast) Sleep(5000);
   return(0);
}

int closeAll(bool fast = false)
{
   checkPoint(Symbol());

   int  error   = 0;
   int  total   = OrdersTotal();
   for (int pos = 0; pos < total; pos++)
   {
      if (OrderSelect(pos, SELECT_BY_POS, MODE_TRADES) == false)
      {
         print("OrderSelect error in closeAll #" + GetLastError());
         continue;
      }

      if (OrderSymbol() == Symbol() && OrderMagicNumber() >= magicGrid && OrderMagicNumber() < (magicGrid+10))
      {
         if (OrderType() == OP_BUY)
         {
            if (!OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(Bid, Digits), 0, Orange))
            {
               print("Error closing BUY order #" + GetLastError());
               error -= 1;
            }
         }
         else if (OrderType() == OP_SELL)
         {
            if (!OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(Ask, Digits), 0, Orange))
            {
               print("Error closing SELL order #" + GetLastError());
               error -= 1;
            }
         }
         else
         {
            // must delete also pending orders if any
            if (!OrderDelete(OrderTicket(), Red))
            {
               print("Error closing PENDING order #" + GetLastError());
               error -= 1;
            }
         }
      }
      // also in closing better wait for some seconds
      if (!fast) Sleep(5000);
   }

   return(error);
}


