#property copyright "Copyright 2017, NosceTeIpsum"
#property description "v2.0, updated on 21 Dec 2017"
#property strict

#include      <stdlib.mqh>

extern double PipStep=30;
extern double TP=10;
extern double StartingLot=0.01;
extern int MaxTrades=20;
extern string Multiplier="1,3,6,12,24,48,96,192,384,768,1536,3072,6144,12288,24576,49152,98304,196608,393216,786432";
extern bool StartBuy=true;
extern double MinProfit=0.10;
extern double TPProfit=2.00;
extern int MaxTPCount=0;
extern int CycleToStartMinProfit=7;
extern int MagicNumber=777;


double lot2;
double sumlots=0;
double tpp=0;
string multi[];
int count=0;
int TPcount=0;


//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
 ObjectDelete("TP_Price");
  }
  
int OnInit()
  {
   AutoDigit();
   ObjectCreate(ChartID(),"TP_Price", OBJ_HLINE, 0, 0, tpp);
   ObjectSet("TP_Price", OBJPROP_COLOR, clrAqua);
   ObjectSet("TP_Price",OBJPROP_STYLE,STYLE_DASH);

   int k=StringSplit(Multiplier,StringGetCharacter(",",0),multi);
   ArrayResize(multi,MaxTrades,0);
  if(k>0)
  {
  for(int i=k;i<(MaxTrades-1);i++)
  {
         multi[i]=multi[k-1];
        }
     }
   return(INIT_SUCCEEDED);
  }

void OpenBuy()
 {
    int ticket;
        if (!GlobalVariableCheck("InTrade")) {
               GlobalVariableSet("InTrade", TimeCurrent());  // set lock indicator
               ticket = OrderSend(Symbol(),OP_BUY,lot2,Ask,3,0,0,"",MagicNumber,0,clrNONE);
               GlobalVariableDel("InTrade");   // clear lock indicator
               if(ticket == -1) ShowError("Order Buy");
        }
 }

void OpenSell()
 {
    int ticket;
        if (!GlobalVariableCheck("InTrade")) {
               GlobalVariableSet("InTrade", TimeCurrent());  // set lock indicator
               ticket = OrderSend(Symbol(),OP_SELL,lot2,Bid,3,0,0,"",MagicNumber,0,clrNONE);
               GlobalVariableDel("InTrade");   // clear lock indicator
               if(ticket == -1) ShowError("Order Sell"); 
        }
 }


void ManageBuySell() 
 {
   int lasttradetime=0;
   double lastopenprice=0;
   double maxlots = 0;
   double sump=0;
   int y=0; 
   sumlots=0;

   count=0;
   for (y = 0; y < OrdersTotal(); y++)
   {
      if(OrderSelect (y, SELECT_BY_POS, MODE_TRADES)){
      if (OrderSymbol()!=Symbol() || OrderMagicNumber() != MagicNumber) { continue; } 
      if(OrderType()==OP_SELL){
      sumlots=sumlots-OrderLots();
      sump=OrderOpenPrice()*-1*OrderLots()+sump; }
      else{
      sumlots=sumlots+OrderLots();
      sump=OrderOpenPrice()*OrderLots()+sump; }
      if (OrderOpenTime() > lasttradetime) { 
        lasttradetime = OrderOpenTime();
        lastopenprice = OrderOpenPrice();
      } 
      count++;
      }
   }
   
   lot2=NormalizeDouble(StartingLot*StringToDouble(multi[count]),2);
   
   if (count==0) { //no orders, two poss i.e. beginning or after complete cycle
     string lastorder=""; 
     lasttradetime = 0;
     
    //find the last open order, if buy then it must be TP on buy side n vice versa
   for(int i=(OrdersHistoryTotal()-1);i>=0;i--)
 {
   if(OrderSelect(i, SELECT_BY_POS,MODE_HISTORY)){
   if(OrderSymbol()!=Symbol() || OrderMagicNumber()!=MagicNumber) continue;
     if (OrderOpenTime() > lasttradetime) {
     lasttradetime = OrderOpenTime();
     if(OrderType()==OP_BUY) lastorder="buy";
     if(OrderType()==OP_SELL) lastorder="sell";
     }
    }
    
 }
 
   if(lastorder==""){ //if no previous record, follow setting which direction to start
   if(StartBuy) OpenBuy(); else OpenSell();}
   else
   {
   if(lastorder=="buy")  OpenBuy();
   if(lastorder=="sell")  OpenSell();
   }

   }
   else {
   if ((sumlots<0) && ((Bid-lastopenprice)>PipStep*Point) && (lastopenprice>0)) OpenBuy();
   if ((sumlots>0) && ((lastopenprice-Ask)>PipStep*Point) && (lastopenprice>0)) OpenSell();
    }

   //find TP
   sumlots=0;
   sump=0;
   double avgp=0;
   double totalbuylot=0;
   double totalselllot=0;
   count=0;
   
   for (y = 0; y < OrdersTotal(); y++)
   {
      if(OrderSelect (y, SELECT_BY_POS, MODE_TRADES)){
      if (OrderSymbol()!=Symbol() || OrderMagicNumber() != MagicNumber) continue; 
    
      if(OrderType()==OP_SELL){
      sumlots=sumlots-OrderLots();
      sump=(OrderOpenPrice()*-1*OrderLots())+sump; 
      totalselllot=OrderLots()+totalselllot;}
      else if(OrderType()==OP_BUY){
      sumlots=sumlots+OrderLots();
      sump=(OrderOpenPrice()*OrderLots())+sump;
      totalbuylot=OrderLots()+totalbuylot; } 
      count++;
      }
   }
   
   
   if (MathAbs(sumlots)>0) { //sumlots=-0.15+0.31 =0.16, sump=(0.24*133.894)+(0.06*133.887)+(0.01*133.889)-(0.12*133.73)-(0.03*133.727)=21.44726
     RefreshRates();
     if(sumlots<0) {
     avgp=NormalizeDouble((sump-(totalbuylot*(Ask-Bid)))/sumlots,Digits); //Ask-Bid=0.03
     tpp=NormalizeDouble(-TP*Point+avgp,Digits); }
     if(sumlots>0) {
     avgp=NormalizeDouble((sump+(totalselllot*(Ask-Bid)))/sumlots,Digits); //avgp=134.0735
     tpp=NormalizeDouble(TP*Point+avgp,Digits); }

   }  

   
}
    

  
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
void OnTick()
  {

  if(!IsTrade()) return;
  
  Comment("TPCount = ",TPcount);
  
  if(TPcount>(MaxTPCount-1)) return;
  
  if(count>(CycleToStartMinProfit-1) && AccountProfit() > MinProfit)
  CloseAll();
  
  if(AccountProfit() > TPProfit)
  CloseAll();

  if((sumlots>0) && tpp != 0 && Bid >= tpp && AccountProfit() > MinProfit)
  CloseAll();

  if((sumlots<0) && tpp != 0 && Ask <= tpp && AccountProfit() > MinProfit )
  CloseAll();
  
  ManageBuySell();   
 
  ObjectMove("TP_Price",0,0,tpp);
  }
//+------------------------------------------------------------------+

void CloseAll () {   // #function of CloseAll
if (OrdersTotal()==0) {return;}  // if total==0
for(int _i=OrdersTotal()-1;_i>=0;_i--)
      {  //# for loop
      if (OrderSelect(_i,SELECT_BY_POS,MODE_TRADES))
         {
               if(OrderMagicNumber() == MagicNumber){              
               
               while(!OrderClose(OrderTicket(),OrderLots(),(OrderType() == OP_BUY) ? Bid : Ask,3,(OrderType() == OP_BUY) ? Blue : Red)) 
                  {
                     ShowError(StringConcatenate("Close ",(OrderType() == OP_BUY) ? "Buy " : "Sell ")); 
                     Sleep(100);
                     RefreshRates();
                  } 
               
               }
         }  // # if 
}  // # for loop
tpp=0;
TPcount++;
} 

void ShowError(string label)
{
	string Error;
	int    error = GetLastError();
	
	Error        = StringConcatenate("Terminal: ",TerminalName(),"\n",
	                                  label," error ",error,"\n",
	                                  ErrorDescription(error));
	if(error != 0) Alert(Error);
}

void AutoDigit()
{
  
   if (Digits == 3 || Digits == 5)
   {
   PipStep*=10;
   TP*=10;
   }
}

bool IsTrade()
{
   bool trade = true;
   
   if(!IsTesting())
   {
      if(!IsTradeAllowed()) 
      {
         Print("Allow live trading is disabled, press F7, \nselect Common tab, check Allow live trading");
         trade = false;
      }
   
      if(!IsExpertEnabled()) 
      {
         Print("Expert Advisor is disabled, click AutoTrading button to activate it ");
         trade = false;
      }   
      
      if(MarketInfo(Symbol(),MODE_TRADEALLOWED)==0)
      {
         Print("Trade is not allowed at server! bail out!");
         trade = false;
      }
      
      if(!IsConnected())
      {
         Print("No connection to server! bail out!");
         trade = false;
      } 
   }
   
   return(trade);
}

