
//+------------------------------------------------------------------+
//|                                        TickTick Robotics Series  |
//|                                         LinearRegression EA.mq4  |
//|                                                Joseph Bervell    |
//|                                          FX Hedge Solutions LLC, |
//|          CONTRIBUTED TO TRADINGSYSTEMFOREX FORUM                 |
//+------------------------------------------------------------------+


     #property copyright "JbKengen"
     #property link      "jbkengen@gmail.com"
  

#include <OrderZ.mqh>

extern double InitialLotsize=0.02;
extern double TakeProfitInDollars=10.0;
extern int    GridSize=31;
extern string SecondaryVariables = "~~~~~~~~~~~~~";
extern bool   martingale=true;
extern double multiplier=1.59;
extern bool   Use_SL_and_TP=false;
extern int    sl=50;
extern int    tp=50;
extern bool   oppositeclose=false;
extern bool   CloseOnExpiration = false;
extern int    expirationDays = 7; 
extern bool   usedailytarget=false;
extern double dailytarget=100;
extern bool   lotsoptimized=false;
extern double risk=1;
extern double maxlot=10;
extern double lotdigits=2;
extern bool   basketpercent=false;
extern double profit=10;
extern double loss=30;
extern int    waitingtime=1440;
extern int    level=10;
extern bool   lotincrement=false;
extern double increment=0.1;
extern bool   tradefriday=true;
extern int    magic=1;
extern bool   stealthmode=true;

double point;
double minlot;
double stoplevel;
int prec=0;
int a=0;
int b=0;
  
int i;
double lastprofit;
int history;

datetime t0,t1,lastbuyopentime,lastsellopentime,waiting;
double lastbuyopenprice,lastsellopenprice,lastbuyprofit,lastsellprofit;
double lotsfactor=1,InitialLotsizesizesfactor=1,ilots,lastbuylot,lastselllot,lastlot,mlots;
double ask,bid,cb,min,max;
int bc=-1,tpb,tps,cnt,istart,iend,total,ticket;
int lastorder,buyorderprofit,sellorderprofit;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+

int init(){
   if(Digits==3 || Digits==5) point=10*Point;
   else point=Point;
   minlot=MarketInfo(Symbol(),MODE_MINLOT);
   if(minlot==0.01)prec=2;
   if(minlot==0.1)prec=1;
   return(0);
}

//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+

int deinit(){
   return(0);
}

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+

int start(){

   if(basketpercent){
      double ipf=profit*(0.01*AccountBalance());
      double ilo=loss*(0.01*AccountBalance());
      cb=AccountEquity()-AccountBalance();
      if(cb>=ipf||cb<=(ilo*(-1))){
         closebuy();
         closesell();
         waiting=TimeCurrent();
         return(0);
      }
   }
   if(basketpercent && (TimeCurrent()-waiting)<(waitingtime*60))return(0);
   if(lotsoptimized){
      history=OrdersHistoryTotal();
      if(history>0){
         //for(i=0;i<history;i++){
            OrderSelect(history,SELECT_BY_POS,MODE_HISTORY);
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic){
               lastprofit=OrderProfit();
            }
         //}
      }
   }
   Comment("\ntimecurrent = "+DoubleToStr(TimeCurrent(),0),"\nwaiting = "+DoubleToStr(waiting,0)
   ,"\ndifference = "+DoubleToStr(TimeCurrent()-waiting,0),"\nwaitingtime = "+DoubleToStr(waitingtime*60,0));
   if(lotsoptimized && (martingale==false || (martingale && lastprofit>=0))){InitialLotsize=NormalizeDouble((AccountBalance()/1000)*0.01*risk,lotdigits);if(InitialLotsize>maxlot)InitialLotsize=maxlot;}
   if(dailyprofit()>=dailytarget && usedailytarget || a>0){
      a++;
      for(int i=OrdersTotal()-1; i>=0; i--){
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if(OrderSymbol()!=Symbol() || OrderMagicNumber()!=magic) continue;
         if(OrderType()==OP_BUY)  OrderCloseZ(OrderTicket(),OrderLots(),Bid,MarketInfo(Symbol(),MODE_SPREAD),CLR_NONE);
         else 
         if(OrderType()==OP_SELL) OrderCloseZ(OrderTicket(),OrderLots(),Ask,MarketInfo(Symbol(),MODE_SPREAD),CLR_NONE);
         else OrderDelete(OrderTicket());
      }
      if(total()==0) a=0;
      return(0);
   }
   if(!tradefriday && DayOfWeek()==5 && total()==0){return(0);}
   if(profit()>=TakeProfitInDollars || b>0){
      b++;
      for(i=OrdersTotal()-1; i>=0; i--){
        OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
        if(OrderSymbol()!=Symbol() || OrderMagicNumber()!=magic) continue;
        if(OrderType()==OP_BUY)OrderCloseZ(OrderTicket(),OrderLots(),Bid,MarketInfo(Symbol(),MODE_SPREAD),CLR_NONE);
        else 
        if(OrderType()==OP_SELL)OrderCloseZ(OrderTicket(),OrderLots(),Ask,MarketInfo(Symbol(),MODE_SPREAD),CLR_NONE);
        else OrderDelete(OrderTicket());
      }
      if(total()==0) b=0;
   }  
         
   if(CloseOnExpiration == true && total()>0 && TimeCurrent()-OrderOpenTime() > expirationDays *24*3600)
   {
      closesell(); 
      closebuy();
      delete1(OP_BUYLIMIT);
      delete1(OP_SELLLIMIT);
   }    
     
   if(total()==0 && a==0){
     if(signal()>0){        
        if(stealthmode){
           if(!Use_SL_and_TP)OrderSendZ(Symbol(),OP_BUY,InitialLotsize,Ask,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Blue);
           else OrderSendZ(Symbol(),OP_BUY,InitialLotsize,Ask,MarketInfo(Symbol(),MODE_SPREAD),Ask-sl*point,Ask+tp*point,"",magic,0,Blue);
        }
        else{
           if(!Use_SL_and_TP){
              if(OrderSendZ(Symbol(),OP_BUY,InitialLotsize,Ask,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Blue)>0){
                 for(i=1;i<level;i++){
                    if(martingale)OrderSendZ(Symbol(),OP_BUYLIMIT,NormalizeDouble(InitialLotsize*MathPow(multiplier,i),prec),Ask-(GridSize*i)*point,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Blue);
                    if(lotincrement)OrderSendZ(Symbol(),OP_BUYLIMIT,NormalizeDouble(InitialLotsize+(i*increment),prec),Ask-(GridSize*i)*point,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Blue);
                 }
              } 
           }
           else{
              if(OrderSendZ(Symbol(),OP_BUY,InitialLotsize,Ask,MarketInfo(Symbol(),MODE_SPREAD),Ask-sl*point,Ask+tp*point,"",magic,0,Blue)>0){
                 for(i=1;i<level;i++){
                    if(martingale)OrderSendZ(Symbol(),OP_BUYLIMIT,NormalizeDouble(InitialLotsize*MathPow(multiplier,i),prec),Ask-(GridSize*i)*point,MarketInfo(Symbol(),MODE_SPREAD),(Ask-(GridSize*i)*point)-sl*point,(Ask-(GridSize*i)*point)+tp*point,"",magic,0,Blue);
                    if(lotincrement)OrderSendZ(Symbol(),OP_BUYLIMIT,NormalizeDouble(InitialLotsize+(i*increment),prec),Ask-(GridSize*i)*point,MarketInfo(Symbol(),MODE_SPREAD),(Ask-(GridSize*i)*point)-sl*point,(Ask-(GridSize*i)*point)+tp*point,"",magic,0,Blue);
                 }
              } 
           }
        }
     }
     if(signal()<0) {        
        if(stealthmode){
           if(!Use_SL_and_TP) OrderSendZ(Symbol(),OP_SELL,InitialLotsize,Bid,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Red);
           else OrderSendZ(Symbol(),OP_SELL,InitialLotsize,Bid,MarketInfo(Symbol(),MODE_SPREAD),Bid+sl*point,Bid-tp*point,"",magic,0,Red);
        }
        else{
           if(!Use_SL_and_TP){
              if(OrderSendZ(Symbol(),OP_SELL,InitialLotsize,Bid,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Red)>0){
                 for(i=1;i<level;i++){
                    if(martingale)OrderSendZ(Symbol(),OP_SELLLIMIT,NormalizeDouble(InitialLotsize*MathPow(multiplier,i),prec),Bid+(GridSize*i)*point,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Red);
                    if(lotincrement)OrderSendZ(Symbol(),OP_SELLLIMIT,NormalizeDouble(InitialLotsize+(i*increment),prec),Bid+(GridSize*i)*point,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Red);
                 }
              } 
           }
           else{
              if(OrderSendZ(Symbol(),OP_SELL,InitialLotsize,Bid,MarketInfo(Symbol(),MODE_SPREAD),Bid+sl*point,Bid-tp*point,"",magic,0,Red)>0){
                 for(i=1;i<level;i++){
                    if(martingale)OrderSendZ(Symbol(),OP_SELLLIMIT,NormalizeDouble(InitialLotsize*MathPow(multiplier,i),prec),Bid+(GridSize*i)*point,MarketInfo(Symbol(),MODE_SPREAD),(Bid+(GridSize*i)*point)+sl*point,(Bid+(GridSize*i)*point)-tp*point,"",magic,0,Red);
                    if(lotincrement)OrderSendZ(Symbol(),OP_SELLLIMIT,NormalizeDouble(InitialLotsize+(i*increment),prec),Bid+(GridSize*i)*point,MarketInfo(Symbol(),MODE_SPREAD),(Bid+(GridSize*i)*point)+sl*point,(Bid+(GridSize*i)*point)-tp*point,"",magic,0,Red);
                 }
              } 
           }
        }
     } 
   }
 

   if(total()>0 && total()<level && stealthmode){
      if(lasttype()==OP_BUY){
        if(oppositeclose){closesell(); delete1(OP_SELLLIMIT); return(0);}   
         if(lastprice()-Ask>=GridSize*point)  {
           if(!Use_SL_and_TP){
             if(martingale)OrderSendZ(Symbol(),OP_BUY,NormalizeDouble(lastlot()*multiplier,prec),Ask,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Blue);
             if(lotincrement)OrderSendZ(Symbol(),OP_BUY,NormalizeDouble(lastlot()+increment,prec),Ask,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Blue);
           }
           else{
             if(martingale)OrderSendZ(Symbol(),OP_BUY,NormalizeDouble(lastlot()*multiplier,prec),Ask,MarketInfo(Symbol(),MODE_SPREAD),Ask-sl*point,Ask+tp*point,"",magic,0,Blue);
             if(lotincrement)OrderSendZ(Symbol(),OP_BUY,NormalizeDouble(lastlot()+increment,prec),Ask,MarketInfo(Symbol(),MODE_SPREAD),Ask-sl*point,Ask+tp*point,"",magic,0,Blue);
           } 
        }
     }
     if(lasttype()==OP_SELL){      
       if(oppositeclose){closebuy(); delete1(OP_BUYLIMIT); return(0);}
         if(Bid-lastprice()>=GridSize*point)  {
           if(!Use_SL_and_TP){
             if(martingale)OrderSendZ(Symbol(),OP_SELL,NormalizeDouble(lastlot()*multiplier,prec),Bid,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Red);
             if(lotincrement)OrderSendZ(Symbol(),OP_SELL,NormalizeDouble(lastlot()+increment,prec),Bid,MarketInfo(Symbol(),MODE_SPREAD),0,0,"",magic,0,Red);
           }
           else{
             if(martingale)OrderSendZ(Symbol(),OP_SELL,NormalizeDouble(lastlot()*multiplier,prec),Bid,MarketInfo(Symbol(),MODE_SPREAD),Bid+sl*point,Bid-tp*point,"",magic,0,Red);
             if(lotincrement)OrderSendZ(Symbol(),OP_SELL,NormalizeDouble(lastlot()+increment,prec),Bid,MarketInfo(Symbol(),MODE_SPREAD),Bid+sl*point,Bid-tp*point,"",magic,0,Red);
           } 
        }
     }
   } 
   return(0);
}

int total(){
   int i=0, total=0;
   while(i<OrdersTotal()){
     OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
     if(OrderSymbol()!=Symbol()|| OrderMagicNumber()!=magic)continue;
     total++;
     i++;
   }
   return(total);
}
  
double profit(){
   int i=0;
   double prof=0;
   while(i<OrdersTotal()){
     OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
     if(OrderSymbol()!=Symbol()|| OrderMagicNumber()!=magic)continue;
     prof+=OrderProfit();
     i++;
   } 
   return(prof);
}

int lasttype(){ 
   int i=0, type=-1;
   while(i<OrdersTotal()){
     OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
     if(OrderSymbol()!=Symbol()|| OrderMagicNumber()!=magic)continue;
     type=OrderType();
     i++;
   } 
   return(type);
}

double lastprice(){ 
   int i=0;
   double prc=0;
   while(i<OrdersTotal()){
     OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
     if(OrderSymbol()!=Symbol()|| OrderMagicNumber()!=magic)continue;
     prc=OrderOpenPrice();
     i++;
   } 
   return(prc);
}

double lastlot(){
   int i=0;
   double lot=0;
   while(i<OrdersTotal()){
     OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
     if(OrderSymbol()!=Symbol()|| OrderMagicNumber()!=magic)continue;
     lot=OrderLots();
     i++;
   } 
   return(lot);
}

double dailyprofit(){
  int i=0;
  int day=TimeDay(TimeCurrent()),month=TimeMonth(TimeCurrent()),year=TimeYear(TimeCurrent());
  double prof=0;
  while(i<OrdersHistoryTotal()){
     OrderSelect(i,SELECT_BY_POS,MODE_HISTORY);
     if(OrderSymbol()!=Symbol() || OrderMagicNumber()!=magic)continue;
     if(TimeDay(OrderOpenTime())!=day) break;
     if(TimeMonth(OrderOpenTime())!=month) break;
     if(TimeYear(OrderOpenTime())!=year) break;
     prof+=OrderProfit();
     i++;
  }
  return(prof);
}

//|---------close

void closebuy(){
   total=OrdersTotal();
   if(total>0){
      for(i=0;i<total;i++){
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic && OrderType()==OP_BUY){
            OrderClose(OrderTicket(),OrderLots(),Bid,0);
         }
      }
   }
}

void closesell(){
   total=OrdersTotal();
   if(total>0){
      for(i=0;i<total;i++){
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic && OrderType()==OP_SELL){
            OrderClose(OrderTicket(),OrderLots(),Ask,0);
         }
      }
   }
}

//|---------delete

void delete1(int type){
   if(OrdersTotal()>0){
      for(i=OrdersTotal();i>=0;i--){
        OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
        if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic && OrderType()==type){
          OrderDelete(OrderTicket());
        }   
      }
   }
}

//--------------------------------------------------------------------------- 

int signal(){
  int a=0;
  
  double GannLine0     = iCustom(NULL, 0, "Gann Hi-lo Activator SSL",  0, 0);
  double GannLine1     = iCustom(NULL, 0, "Gann Hi-lo Activator SSL",  0, 1);
  double GannLine2     = iCustom(NULL, 0, "Gann Hi-lo Activator SSL",  0, 2);
  double GannLine3     = iCustom(NULL, 0, "Gann Hi-lo Activator SSL",  0, 3);

  
  
  if(Close[2] < GannLine2 && Close[1] > GannLine1 && Close[0] > GannLine0) a--;
  if(Close[2] > GannLine2 && Close[1] < GannLine1 && Close[0] < GannLine0) a++;

//---------------------------------------------------------------------------  

  if(a<0) return(1);
  if(a>0) return(-1);
  
  return(0);
}
//--------------------------------------------------------------------------- 