//+------------------------------------------------------------------+
//| 110924 0615 T-foREX Follower                                     |
//| powered by   T-foREX                                             |
//| http://jobaweb.net                                               |
//+------------------------------------------------------------------+

#property copyright "T-foREX"
#property link      "http://jobaweb.net"
#property show_inputs

//---- input parameters
extern string help_orders         = "---------- ORDINI ----------";
extern string help_nMagic_1       = "magic number CAMBIARLO SOLO DI 10 IN 10";
extern string help_nMagic_2       = "es.: 1, 11, 21, ... NON 1, 2, 3, ...";
extern int         nMagic         =  1000;
extern string help_lots           = "lotto ordine base";
extern double      lots           =    0.50;
extern string help_oneOrder_1     = "apre UN SOLO ORDINE in tutto";
extern string      oneOrder_2     = "il primo blocca tutte le altre valute";
extern bool        oneOrder       =  false;
extern string help_follow         = "pip di distanza per seguire il prezzo";
extern double      follow         =   10.0;
extern string help_ordersTP_1     = "take profit IN SOLDI PER TUTTI GLI ORDINI";
extern string help_ordersTP_2     = "quando è raggiunto CHIUDE TUTTO (ZERO = NESSUNO)";
extern double      ordersTP       =    0.00;
extern string help_trailTP        = "trailing stop IN SOLDI (ZERO = NESSUNO)";
extern double      trailTP        =    0.00;
extern string help_basket         = "true = per chiudere TUTTO IN TUTTE LE VALUTE E TF";
extern bool        basket         =  false;
extern string help_takePips       = "take profit IN PIP (ZERO = NESSUNO)";
extern double      takePips       =   15.0;
extern string help_stopPips       = "stop loss fisso IN PIP (ZERO = NESSUNO)";
extern double      stopPips       =    0.0;
extern string help_trailStart     = "partenza trailing stop in pip (ZERO = SUBITO)";
extern double      trailStart     =   10.0;
extern string help_trailPips      = "trailing stop in pip (ZERO = NESSUNO)";
extern double      trailPips      =    5.0;
extern string help_timeframe      = "timeframe fisso IN MINUTI o ZERO = quello del grafico";
extern int         timeframe      =    0;
extern color       colorUp        =  Lime;
extern color       colorDn        =  Red;
extern string help_money          = "---------- GESTIONE GENERALE MONEY ----------";
extern string help_iisFile        = "ATTENZIONE: METTERE false SE WINDOWS DA ERRORI";
extern bool        iisFile        =  true;
extern string help_lotPip_1       = "lotto SOLO per visualizzare valore pip";
extern string help_lotPip_2       = "ZERO per vedere valore lotto ordine";
extern double      lotPip         =    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_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;

bool     trailMoney = false;
double   breakUp = 0.0, breakDn     = 0.0;
double   lastUp  = 0.0, lastDn      = 0.0;
double   open    = 0.0, trailProfit = 0.0;
double   pip, minPips, spread;
datetime lastCandle = 0;

double openPrice = 0.0;
int    magic     = 100; string comment     = "";
double stopLoss  = 0.0; double takeProfit  = 0.0;
double lossPrice = 0.0; double profitPrice = 0.0;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+

int init()
{
   //----
   /*
   // clean all but not the orders arrows
   string obj_name  = "";
   int    obj_total = ObjectsTotal()-1;
   for(int i = obj_total; i >= 0; i--)
   {
      obj_name = ObjectName(i);
      if (StringGetChar(obj_name, 0) != 35) ObjectDelete(obj_name);
   }
   */

   HideTestIndicators(true);

   string www = "http://jobaweb.net";
   if (ObjectFind(www) != 0)
   {
      ObjectCreate(www, OBJ_LABEL, 0, 0, 0);
      ObjectSet(www, OBJPROP_CORNER, 3);
      ObjectSet(www, OBJPROP_XDISTANCE, 5);
      ObjectSet(www, OBJPROP_YDISTANCE, 250);
      ObjectSet(www, OBJPROP_ANGLE, 90);
      ObjectSetText(www, www, 10, "Tahoma", Lime);
   }

   checkPoint();  // if need pip value
   if ((takePips != 0 && takePips < minPips) || (stopPips != 0 && stopPips < minPips) || (trailPips != 0 && trailPips < minPips))
      MessageBox("ATTENZIONE: take/stop/trail minori di quello permesso dal broker!", "jobaweb.net", 0x00000010);
   if (timeframe == 0) timeframe = Period(); // avoid below zero divide

   // confirm the start
   print("T-foREX Follower starts @ " + TimeToStr(TimeCurrent()), true);
   
   // do a previous loop to visualize graphics
   // and set break levels
   start();
 
   //----
   return(0);
}

//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+

int deinit()
{
   //----
   // NOT to close opened orders
   //closeAll();

   // better not to print so let last significative message
   //print("...T-foREX stop");
   
   // no delete so user can see graphics
   // also after EA closure
   //ObjectsDeleteAll();

   //----
   return(0);
}

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+

int start()
{
   // START IS EXECUTED EVERY TICK
   Comment("Powered by T-foREX http://jobaweb.net");

   // money management block control
   // moneyManagement alredy calls checkPoint
   bool                       toTrade;
   if (moneyManagement() < 0) toTrade = false;
   else                       toTrade = true;

   // count orders
   int    pos;
   int    totBuys   = 0,   totSells   = 0;
   int    totOpens  = 0,   totAlls    = 0;
   double stopPrice = 0.0, takePrice  = 0.0;
   double buyLots   = 0.0, sellLots   = 0.0;
   double buyProfit = 0.0, sellProfit = 0.0, totProfit = 0.0;

   for (pos = 0; pos < OrdersTotal(); pos++)
   {
      if (!OrderSelect(pos, SELECT_BY_POS, MODE_TRADES))
      {
         continue;
      }
      
      // here count every open order
      totAlls += 1;

      if (!basket && OrderSymbol() != Symbol())
      {
         // not to count only if not basket orders
         continue;
      }
      else if (OrderMagicNumber() == (nMagic+1))
      {
         totOpens  += 1; totBuys += 1;
         buyLots   += OrderLots();
         buyProfit += OrderProfit();
         totProfit += OrderProfit();

         // trailing in pips
         if ((trailPips != 0 && Bid >= (OrderOpenPrice() + trailStart*pip)) || (OrderStopLoss() != 0 && OrderStopLoss() > OrderOpenPrice()))
         {
            // trail the stop         
            if      (OrderStopLoss() != 0)      stopPrice  = MathMax(Bid - trailPips*pip, OrderStopLoss());
            else                                stopPrice  = MathMax(Bid - trailPips*pip, OrderOpenPrice());
            if      (OrderStopLoss() == 0    && stopPrice  < OrderOpenPrice()) {/* wait to set trailing sl */}
            else if (MathAbs(OrderStopLoss()  - stopPrice) > 1*pip)
               if (!OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(stopPrice, Digits), 0, 0, Blue))
                  Alert(OrderSymbol() + " buy trailing error " + GetLastError());
         }
         // if trailing money stop then disable every take/stop
         else if (trailMoney)
         {
            if (OrderStopLoss() != 0 || OrderTakeProfit() != 0)
               if (!OrderModify(OrderTicket(), OrderOpenPrice(), 0, 0, 0, Blue))
                  Alert(OrderSymbol() + " buy take/stop delete error " + GetLastError());
         }
         // else check the fix take and stop
         else
         {
            if (stopPips > 0) stopPrice = NormalizeDouble(OrderOpenPrice() - stopPips*pip, Digits);
            else              stopPrice = 0.0;
            if (takePips > 0) takePrice = NormalizeDouble(OrderOpenPrice() + takePips*pip, Digits);
            else              takePrice = 0.0;
         
            if (MathAbs(OrderStopLoss() - stopPrice) > 1*pip || MathAbs(OrderTakeProfit() - takePrice) > 1*pip)
               if (!OrderModify(OrderTicket(), OrderOpenPrice(), stopPrice, takePrice, 0, Blue))
                  Alert(OrderSymbol() + " buy take/stop error " + GetLastError());
         }
      }
      else if (OrderMagicNumber() == (nMagic+2))
      {
         totOpens   += 1; totSells += 1;
         sellLots   += OrderLots(); 
         sellProfit += OrderProfit();
         totProfit  += OrderProfit();

         if ((trailPips != 0 && Ask <= (OrderOpenPrice() - trailStart*pip)) || (OrderStopLoss() != 0 && OrderStopLoss() < OrderOpenPrice()))
         {
            if      (OrderStopLoss() != 0)      stopPrice  = MathMin(Ask + trailPips*pip, OrderStopLoss());
            else                                stopPrice  = MathMin(Ask + trailPips*pip, OrderOpenPrice());
            if      (OrderStopLoss() == 0    && stopPrice  > OrderOpenPrice()) {/* wait... */}
            else if (MathAbs(OrderStopLoss()  - stopPrice) > 1*pip)
               if (!OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(stopPrice, Digits), 0, 0, Red))
                  Alert(OrderSymbol() + " sell trailing error " + GetLastError());
         }
         else if (trailMoney)
         {
            if (OrderStopLoss() != 0 || OrderTakeProfit() != 0)
               if (!OrderModify(OrderTicket(), OrderOpenPrice(), 0, 0, 0, Blue))
                  Alert(OrderSymbol() + " sell take/stop delete error " + GetLastError());
         }
         else
         {
            if (stopPips > 0) stopPrice = NormalizeDouble(OrderOpenPrice() + stopPips*pip, Digits);
            else              stopPrice = 0.0;
            if (takePips > 0) takePrice = NormalizeDouble(OrderOpenPrice() - takePips*pip, Digits);
            else              takePrice = 0.0;

            if (MathAbs(OrderStopLoss() - stopPrice) > 1*pip || MathAbs(OrderTakeProfit() - takePrice) > 1*pip)
               if (!OrderModify(OrderTicket(), OrderOpenPrice(), stopPrice, takePrice, 0, Red))
                  Alert(OrderSymbol() + " sell take/stop error " + GetLastError());
         }
      }
   }

   // display tots to check
   if (ObjectFind( "Buy lots") < 0)
   {
      ObjectCreate("Buy lots", OBJ_LABEL,         0, 0, 0);
      ObjectSet(   "Buy lots", OBJPROP_BACK,      false);
      ObjectSet(   "Buy lots", OBJPROP_CORNER,    1);
      ObjectSet(   "Buy lots", OBJPROP_XDISTANCE, 10);
      ObjectSet(   "Buy lots", OBJPROP_YDISTANCE, 25);
   }
   ObjectSetText(  "Buy lots", totBuys + " buys lots " + DoubleToStr(buyLots, 2) + " = " + DoubleToStr(buyProfit, 2) + " €", 10, "Tahoma", Lime);

   if (ObjectFind( "Sell lots") < 0)
   {
      ObjectCreate("Sell lots", OBJ_LABEL,         0, 0, 0);
      ObjectSet(   "Sell lots", OBJPROP_BACK,      false);
      ObjectSet(   "Sell lots", OBJPROP_CORNER,    1);
      ObjectSet(   "Sell lots", OBJPROP_XDISTANCE, 10);
      ObjectSet(   "Sell lots", OBJPROP_YDISTANCE, 40);
   }
   ObjectSetText(  "Sell lots", totSells + " sells lots " + DoubleToStr(sellLots, 2) + " = " + DoubleToStr(sellProfit, 2) + " €", 10, "Tahoma", Red);

   if (ObjectFind( "Next lots") < 0)
   {
      ObjectCreate("Next lots", OBJ_LABEL,         0, 0, 0);
      ObjectSet(   "Next lots", OBJPROP_BACK,      false);
      ObjectSet(   "Next lots", OBJPROP_CORNER,    1);
      ObjectSet(   "Next lots", OBJPROP_XDISTANCE, 10);
      ObjectSet(   "Next lots", OBJPROP_YDISTANCE, 55);
   }
   ObjectSetText(  "Next lots", "Next lots " + DoubleToStr(lots, 2) + " tot " + DoubleToStr(totProfit, 2) + " €", 10, "Tahoma", Yellow);

   if (ObjectFind( "moneyTP") < 0)
   {
      ObjectCreate("moneyTP", OBJ_LABEL, 0, 0, 0);
      ObjectSet(   "moneyTP", OBJPROP_BACK, false);
      ObjectSet(   "moneyTP", OBJPROP_CORNER, 0);
      ObjectSet(   "moneyTP", OBJPROP_XDISTANCE, 300);
      ObjectSet(   "moneyTP", OBJPROP_YDISTANCE, 10);
   }
   ObjectSetText(  "moneyTP", "", 10, "Tahoma", Yellow);

   // check OPEN orders money take profit
   if (totOpens == 0)
   {
      // no open buys so display next profit
      string txtTP = "NO ORDERS ";
      if (ordersTP > 0) txtTP = txtTP + " TP @ " + DoubleToStr(ordersTP, 2);
      else              txtTP = txtTP + " NO MONEY TP";
      if (trailTP  > 0) txtTP = txtTP + " TRAILING " + DoubleToStr(trailTP, 2);
      else              txtTP = txtTP + " NO TRAILING";
      ObjectSetText("moneyTP", txtTP, 10, "Tahoma", Yellow);
   }
   else if (trailMoney)
   {
      if (totProfit <= (trailProfit - trailTP) || trailTP == 0)
      {
         // pass ZERO as nMagic to close all the orders in all symbols
         if (basket) while (closeAll(0,      true) != 0) { /* retry till all closed */ }
         else        while (closeAll(nMagic, true) != 0) { /* retry till all closed */ }
         ObjectSetText("moneyTP", "TP " + DoubleToStr(totProfit, 2) + " HIT!", 10, "Tahoma", Yellow);
         trailMoney = false; trailProfit = 0;
      }
      else
      {
         trailProfit = MathMax(trailProfit, totProfit);
         ObjectSetText("moneyTP", "TOT PROFIT "  + DoubleToStr(totProfit, 2) + 
                                  " TRAIL TP @ " + DoubleToStr(trailProfit - trailTP, 2), 10, "Tahoma", Yellow);
         // immediatly repeat the check & trailing
         return(0);
      }
   }
   else if (ordersTP > 0)
   {
      if (totProfit >= ordersTP)
      {
         // now update and follow only orders trailing
         // but before delete stop loss and take profit if any
         for (pos = 0; pos < OrdersTotal(); pos++) 
         {
            if (!basket && OrderSymbol() != Symbol()) continue;
            else OrderModify(OrderTicket(), OrderOpenPrice(), 0, 0, 0, Yellow);
         }
         trailMoney = true; trailProfit = ordersTP;
         // immediatly repeat the check & trailing
         return(0);
      }
      else
         ObjectSetText("moneyTP", "TOT PROFIT " + DoubleToStr(totProfit, 2) + " TP @ " + DoubleToStr(ordersTP, 2) +
                                  " TRAILING "  + DoubleToStr(trailTP, 2), 10, "Tahoma", Yellow);
   }

   // check S/R every other timeframe candle
   if (lastCandle != iTime(NULL, timeframe, 0))
   {
      breakBox();
      lastCandle = iTime(NULL, timeframe, 0);
   }

   if (ObjectFind( "openLine") < 0)
   {
      if (open == 0) open = (breakDn + breakUp)/2;
      ObjectCreate("openLine", OBJ_HLINE, 0,  iTime( NULL, timeframe, 0), open);
      ObjectSet(   "openLine", OBJPROP_STYLE, STYLE_SOLID);
      ObjectSet(   "openLine", OBJPROP_BACK,  false);
      ObjectSet(   "openLine", OBJPROP_COLOR, Gray);
      ObjectSet(   "openLine", OBJPROP_WIDTH, 3);
   }

   if (ObjectFind("openTxt") < 0)
   {
      ObjectCreate("openTxt", OBJ_TEXT, 0, 0, 0);
      ObjectSet(   "openTxt", OBJPROP_BACK, true);
   }
   ObjectSet("openTxt", OBJPROP_TIME1,  iTime(NULL, Period(), 0) + (WindowBarsPerChart() - WindowFirstVisibleBar())/2*Period()*60);
   ObjectSet("openTxt", OBJPROP_PRICE1, open - 1*pip);

   // then adjust the follower
   int signal = 0;
   if      (Bid > breakUp)
   {
      signal = +1;
      open = MathMax(open, Bid - follow*pip);
      ObjectSet("openLine", OBJPROP_COLOR,  Red);
      ObjectSet("openLine", OBJPROP_PRICE1, open);
      ObjectSetText("openTxt", "SELL Limit @ " + DoubleToStr(open, Digits), 10, "Tahoma", Red);
   }
   else if (Bid < breakDn)
   {
      signal = -1;
      open = MathMin(open, Bid + follow*pip);
      ObjectSet("openLine", OBJPROP_COLOR, Lime);
      ObjectSet("openLine", OBJPROP_PRICE1, open);
      ObjectSetText("openTxt", "BUY Limit @ " + DoubleToStr(open, Digits), 10, "Tahoma", Lime);
   }

   if      (!toTrade)
   {
      // no time to trade
   }
   else if (oneOrder && totAlls > 0)
   {
      // too many orders!
   }
   // alway use Bid because it's a graphic breakout
   else if (totBuys == 0 && signal == +1 && MathAbs(breakUp - lastUp) > 5*pip && Bid >= open && Bid <= (open + 1*pip))
   {
      magic = nMagic + 1;
      comment = "T-foREX BUY";
      if (buy() > 0) lastUp = breakUp;
   }
   else if (totSells == 0 && signal == -1 && MathAbs(breakDn - lastDn) > 5*pip && Bid <= open && Bid >= (open - 1*pip))
   {
      magic = nMagic + 2;
      comment = "T-foREX SELL";
      if (sell() > 0) lastDn = breakDn;
   }

   //----
   return(0);
}

int breakBox()
{
   // look back at first resistance up and down
   int  i; datetime timeUp, timeDn;
   for (i = 0; i < iBars(NULL, timeframe); i++)
   {
      breakUp = iFractals(NULL, timeframe, MODE_UPPER, i);
      if (breakUp != 0)
      {
         timeUp = iTime(NULL, timeframe, i);
         break;
      }
   }

   for (i = 0; i < iBars(NULL, timeframe); i++)
   {
      breakDn = iFractals(NULL, timeframe, MODE_LOWER, i);
      if (breakDn != 0)
      {
         timeDn = iTime(NULL, timeframe, i);
         break;
      }
   }

   // highlight break levels
   setPrice("Break Up", timeUp, iTime(NULL, timeframe, 0) + timeframe*60, breakUp, 1, colorUp);
   setPrice("Break Dn", timeDn, iTime(NULL, timeframe, 0) + timeframe*60, breakDn, 1, colorDn);

   return(0);
}

int setPrice(string price, datetime t0, datetime t1, double p, int w, color c)
{
   if (t0 <= 0 || t1 <= 0 || p <= 0) return;

   price = price + " " + Symbol();
   if(ObjectFind(price) == -1)
   {
      ObjectCreate(price, OBJ_ARROW, 0, 0, 0);
      ObjectSet   (price, OBJPROP_COLOR, c);
      ObjectSet   (price, OBJPROP_WIDTH, 1);
      ObjectSet   (price, OBJPROP_ARROWCODE, SYMBOL_RIGHTPRICE);
   }
   ObjectMove(price, 0, t1, p);

   string line = "Line " + price;
   if (ObjectFind(line) < 0)
   {
      ObjectCreate(line, OBJ_TREND, 0, 0, 0, 0, 0);
      ObjectSet   (line, OBJPROP_STYLE, STYLE_DOT);
      ObjectSet   (line, OBJPROP_WIDTH, w);
      ObjectSet   (line, OBJPROP_COLOR, c);
      ObjectSet   (line, OBJPROP_BACK, true);
      ObjectSet   (line, OBJPROP_RAY,  false);
   }
   ObjectMove(line, 0, t0, p);
   ObjectMove(line, 1, t1, p);
   
   return(0);
}

//+------------------------------------------------------------------+
//| general management                                               |
//+------------------------------------------------------------------+

int print(string text, bool flashing = false)
{
   if (ObjectFind( "Check text") < 0)
   {
      ObjectCreate("Check text", OBJ_LABEL,         0, 0, 0);
      // back means it paints the background
      ObjectSet(   "Check text", OBJPROP_COLOR,     White);
      ObjectSet(   "Check text", OBJPROP_BACK,      false);
      ObjectSet(   "Check text", OBJPROP_CORNER,    0);
      ObjectSet(   "Check text", OBJPROP_XDISTANCE, 300);
      ObjectSet(   "Check text", OBJPROP_YDISTANCE, 30);
   }
   ObjectSetText(  "Check text", TimeToStr(iTime(NULL, PERIOD_M1, 0), TIME_MINUTES) + " " + text, 10, "Tahoma");

   // flashing effect
   if      (flashing && ObjectGet("Check text", OBJPROP_COLOR) == White) ObjectSet("Check text", OBJPROP_COLOR, Red);
   else if (flashing && ObjectGet("Check text", OBJPROP_COLOR) == Red)   ObjectSet("Check text", OBJPROP_COLOR, White);
   else                                                                  ObjectSet("Check text", OBJPROP_COLOR, White);

   // for debugging porpouses uncomment the print
   // to log journal and mt4 file
   //Print(text);

   return(0);
}

int checkPoint()
{
   RefreshRates();

   // since working with different currency in same EA
   // pip value could change (eg: JPY Digits)
          pip    = Point*MathPow(10, Digits%2);
   double lotVal;  if (lotPip != 0) lotVal = lotPip; else lotVal = lots;
   double pipVal = MarketInfo(Symbol(), MODE_TICKVALUE)*MathPow(10, Digits%2)*lotVal;

   // also in spread compute must considere symbol ask and bid
   spread = NormalizeDouble((Ask - Bid)/pip, Digits);

   // minPips is the minimum stop/take allowed by broker
   if (Digits == 3 || Digits == 5) minPips = MarketInfo(Symbol(), MODE_STOPLEVEL)/10;
   else                            minPips = MarketInfo(Symbol(), MODE_STOPLEVEL);

   if (ObjectFind( "Spread") < 0)
   {
      ObjectCreate("Spread", OBJ_LABEL, 0, 0, 0);
      ObjectSet   ("Spread", OBJPROP_BACK, false);
      ObjectSet   ("Spread", OBJPROP_CORNER, 3);
      ObjectSet   ("Spread", OBJPROP_XDISTANCE, 10);
      ObjectSet   ("Spread", OBJPROP_YDISTANCE, 10);
   }
   ObjectSetText  ("Spread", Symbol()  + 
                           " 1 pip x " + DoubleToStr(lotVal, 2) + " lots = " + DoubleToStr(pipVal, 2) + 
                           " spread "  + DoubleToStr(spread, 1) + 
                           " pips", 10, "Tahoma", Red);

   return(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();

   // if case update IIS7 data file
   if (!IsTesting() && iisFile && iTime(NULL, PERIOD_M1, 0) != lastMoneyUpdate)
   {
      lastMoneyUpdate = iTime(NULL, PERIOD_M1, 0);

      int handle;
      handle = FileOpen("T-foREX " + 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>T-foREX<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/>");

         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);
      }
   }

   if (ObjectFind("Account Alarm") < 0)
   {
      ObjectCreate("Account Alarm", OBJ_LABEL, 0, 0, 0);
      ObjectSet(   "Account Alarm", OBJPROP_BACK, false);
      ObjectSet(   "Account Alarm", OBJPROP_CORNER, 2);
      ObjectSet(   "Account Alarm", OBJPROP_XDISTANCE, 10);
      ObjectSet(   "Account Alarm", OBJPROP_YDISTANCE, 10);
   }
   
   string alarmText = "Equity " + DoubleToStr(AccountEquity(), 2);
   if (saveMoney > 0) alarmText = alarmText + " stop @ " + DoubleToStr(saveMoney, 2);
   ObjectSetText("Account Alarm", alarmText, 10, "Tahoma");
   if      (AccountEquity()/AccountBalance() > 0.75) ObjectSet("Account Alarm", OBJPROP_COLOR, Red);
   else if (AccountEquity()/AccountBalance() < 0.50) ObjectSet("Account Alarm", OBJPROP_COLOR, Yellow);
   else                                              ObjectSet("Account Alarm", OBJPROP_COLOR, Lime);

   // check daily orders take 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 (OrderSymbol() == Symbol() && OrderMagicNumber() >= nMagic && OrderMagicNumber() < (nMagic+10) && 
             TimeToStr(OrderOpenTime(), TIME_DATE) == today) totProfit += OrderProfit();
      }

      if (totProfit >= dailyProfit)
      {      
         while(closeAll(nMagic) != 0) {/* be sure to close all oreders */}
         print("OK !!! DAILY TARGET HIT !!!", true);
         return(-1); 
      }
   }

   // check if parameter errors
   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)
   {
      while(closeAll(nMagic) != 0) {/* be sure to close all oreders */}
      print("OK !!! ACCOUNT TARGET HIT !!!", true);
      return(-1); 
   }

   // above all save money if fixed
   if (saveMoney != 0 && AccountEquity() <= saveMoney)
   {
      while(closeAll(nMagic) != 0) {/* be sure to close all oreders */}
      print("SAVE MONEY STOP: GAME OVER !!!", 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                                                  |
//+------------------------------------------------------------------+

int buy()
{
   for (int i = 1; IsTradeContextBusy(); i++)
   {
      print("TRAD CONTEXT BUSY... ATTEMPT " + i, true);  
      Sleep(1000);
   }

   int ticket = 0;
   if (IsTradeAllowed()) 
   {
		RefreshRates();

      double             stop = 0.0;
      if (stopLoss  > 0) stop = NormalizeDouble(Bid - stopLoss*pip, Digits);
      if (lossPrice > 0) stop = NormalizeDouble(lossPrice, Digits);
   
      double               take = 0.0;
      if (takeProfit  > 0) take = NormalizeDouble(Ask + takeProfit*pip, Digits);
      if (profitPrice > 0) take = NormalizeDouble(profitPrice, Digits);

      if (comment == "") comment = "Buy order by T-foREX";

      ticket = OrderSend(Symbol(), OP_BUY, lots, NormalizeDouble(Ask, Digits), 0, stop, take, comment, magic, 0, Blue);
   }

   if (ticket < 0) {Alert("BUY " + Symbol() + " " + comment + " error #" + GetLastError()); return(-1);}
   else             print("BUY " + ticket + " " + Symbol() + " " + comment + " sent ok");
   
   // 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 (1000);
   return(ticket);
}

//+------------------------------------------------------------------+
//| function to sell                                                 |
//+------------------------------------------------------------------+

int sell()
{
   for (int i = 1; IsTradeContextBusy(); i++)
   {
      print("TRAD CONTEXT BUSY... ATTEMPT " + i, true);  
      Sleep(1000);
   }

   int ticket = 0;
   if (IsTradeAllowed()) 
   {
      RefreshRates();

      double             stop = 0.0;
      if (stopLoss  > 0) stop = NormalizeDouble(Ask + stopLoss*pip, Digits);
      if (lossPrice > 0) stop = NormalizeDouble(lossPrice, Digits);

      double               take = 0.0;
      if (takeProfit  > 0) take = NormalizeDouble(Bid - takeProfit*pip, Digits);
      if (profitPrice > 0) take = NormalizeDouble(profitPrice, Digits);

      if (comment == "") comment = "Sell order by T-foREX";

      ticket = OrderSend(Symbol(), OP_SELL, lots, NormalizeDouble(Bid, Digits), 0, stop, take, comment, magic, 0, Red);
   }

   if (ticket < 0) {Alert("SELL " + Symbol() + " " + comment + " error #" + GetLastError()); return(-1);}
   else             print("SELL " + ticket + " " + Symbol() + " " + comment + " sent ok");

   Sleep (1000);
   return(ticket);
}

//+------------------------------------------------------------------+
//| function to close open positions                                 |
//+------------------------------------------------------------------+

// general closure function ALSO IN ALL CHARTS
// unless pass the nMagic
int closeAll(int nMagic, bool fast = false)
{
   int error = 0, total = OrdersTotal() - 1;
   for (int pos = total; pos >= 0; pos--)
   {
      if (!OrderSelect(pos, SELECT_BY_POS, MODE_TRADES))
      {
         // also if OrderSelect error continue with next
         print("OrderSelect error # " + GetLastError());
         continue;
      }
      
      // WARNING could have all diferent symbols!
      RefreshRates();
      int    digits = MarketInfo(OrderSymbol(), MODE_DIGITS);
      double bid    = MarketInfo(OrderSymbol(), MODE_BID);
      double ask    = MarketInfo(OrderSymbol(), MODE_ASK);
      
      if (nMagic == 0 || (OrderSymbol() == Symbol() && OrderMagicNumber() >= nMagic && OrderMagicNumber() < (nMagic+10)))
      {
         if (OrderType() == OP_BUY)
         {
            if (!OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(bid, digits), 0, Blue))
            {
               Alert("Error closing BUY order #" + GetLastError());
               error -= 1;
            }
         }
         else if (OrderType() == OP_SELL)
         {
            if (!OrderClose(OrderTicket(), OrderLots(), NormalizeDouble(ask, digits), 0, Red))
            {
               Alert("Error closing SELL order #" + GetLastError());
               error -= 1;
            }
         }
         else
         {
            // must delete also pending orders if any
            if (!OrderDelete(OrderTicket(), Yellow))
            {
               Alert("Error closing PENDING order #" + GetLastError());
               error -= 1;
            }
         }
      }
      
      // also in closing better wait for some seconds
      if (fast) Sleep(100); else Sleep(1000);
   }

   return(error);
}

//+------------------------------------------------------------------+

