//---- input parameters ---------------------------------------------+


extern double    LOTS=0.02; // not used in this version  ***option to turn on/off
extern int       LEVELS=3; 
extern int       MAGIC=1803;
extern bool      CONTINUE=true;
extern double    Open_Loss_To_CloseTrades=-100;
 
extern string    StdDev="==== Standard Deviation ====================";
extern int     MA_Period=10;
extern int     MA_Shift=0;     //MA shift. 
extern string    Methods="**0-SMA,1-EMA,2-SMMA,3-LWMA**";
extern int     MA_Method=1;    
extern string    ApPrice="**0-Close,1-Open,2-Hi,3-Low,4-Med,5-Typ,6-Weighted**";
extern int     Applied_Price=0; 
extern int     Shift=0;         
extern int     TimeFrame=15; // 0=Null=current chart=not recommended 
extern string    TurnOffSTD="**Set STD to 0.0 to turn off filter**";
extern double  STD=0.0020;  //  Set to value given for above MA period and timeframe   **if set to zero STD is turned off
//+------------------------------------------------------------------+
//---- input parameters 
//// don't remove used for daily range
 double  Risk_to_Reward_ratio =  3.0;  
 int First_av = 5;
 int Second_av = 10;
 int Third_av = 20;
int nDigits;

bool             MONEY_MANAGEMENT=false;
int              RISK_RATIO=2;
bool             UseEntryTime=false;
int              EntryTime=0;
double           MAX_LOTS=99;
bool             UseProfitTarget=false;
bool             UsePartialProfitTarget=false;
int              Target_AutoIncrement = 10;
int              First_Target = 10;

//+------------------------------------------------------------------+

bool Enter=true;
int nextTP;

int init()
  {
  
  {
IndicatorShortName("TSR");
   if(Symbol()=="GBPJPY" || Symbol()=="EURJPY" || Symbol()=="USDJPY" || Symbol()=="GOLD" || Symbol()=="USDMXN") nDigits = 2;
   if(Symbol()=="GBPUSD" || Symbol()=="EURUSD" || Symbol()=="NZDUSD" || Symbol()=="USDCHF"  ||
   Symbol()=="USDCAD" || Symbol()=="AUDUSD" || Symbol()=="EURUSD" || Symbol()=="EURCHF"  || Symbol()=="EURGBP"
   || Symbol()=="EURCAD" || Symbol()=="EURAUD" )nDigits = 4;

 }

//+------------------------------------------------------------------+ 
   nextTP = First_Target;
//+------------------------------------------------------------------+
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  
  //----Collects daily range info
   int R1=0,R5=0,R10=0,R20=0,RAvg=0,AutoIncrement=0;
   int RoomUp=0,RoomDown=0,StopLoss_Long=0,StopLoss_Short=0;
   double   SL_Long=0,SL_Short=0;
   double   low0=0,high0=0;
   string   Text="";
   int i=0;

   R1 =  (iHigh(NULL,PERIOD_D1,1)-iLow(NULL,PERIOD_D1,1))/Point;
   for(i=1;i<=First_av;i++)
      R5    =    R5  +  (iHigh(NULL,PERIOD_D1,i)-iLow(NULL,PERIOD_D1,i))/Point;
   for(i=1;i<=Second_av;i++)
      R10   =    R10 +  (iHigh(NULL,PERIOD_D1,i)-iLow(NULL,PERIOD_D1,i))/Point;
   for(i=1;i<=Third_av;i++)
      R20   =    R20 +  (iHigh(NULL,PERIOD_D1,i)-iLow(NULL,PERIOD_D1,i))/Point;

   R5 = R5/First_av;
   R10 = R10/Second_av;
   R20 = R20/Third_av;
   RAvg  =  (R1+R5+R10+R20)/4; //RAvg  =  (R5+R10+R20)/3;new setting    
   // from the TSR daily range indicator 
   low0  =  iLow(NULL,PERIOD_D1,0);
   high0 =  iHigh(NULL,PERIOD_D1,0);
   RoomUp   =  RAvg - (Bid - low0)/Point;
   RoomDown =  RAvg - (high0 - Bid)/Point;
   StopLoss_Long  =  RoomUp/Risk_to_Reward_ratio;
   SL_Long        =  Bid - StopLoss_Long*Point;
   StopLoss_Short =  RoomDown/Risk_to_Reward_ratio;
   SL_Short       =  Bid + StopLoss_Short*Point;
  
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  
 //////////////AutoIncrement calculation  R1 = Previous Day range, R5 = 5 day,  R10=10 Day
 //////////////AutoIncrement replaces the need to manaully set increment.  PreviousDay R1 is more heavily weighted
 //////////////then the R5 range.  
                                                                        //Equation history for reference
  AutoIncrement = ((((R5*0.4) + (R1*0.6))  / (LEVELS + 1)) / (2));     //((((R5*0.4) + (R1*0.6))  / (LEVELS + 1)) / (2));
                                                                      // (((R5)/(LEVELS + 1))/2);    
  
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////////////////////////////////////////////
  
   int Slippage=5;                                 
   int ticket, cpt, profit, total=0, BuyGoalProfit, SellGoalProfit, PipsLot;
   double ProfitTarget=AutoIncrement*1, BuyGoal=0, SellGoal=0, spread=(Ask-Bid)/Point, InitialPrice=0;
//----

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//---- StdDev indicator Settings
  
  double sval=iStdDev(NULL,TimeFrame,MA_Period,MA_Shift,MA_Method,Applied_Price,Shift);
  
  

//----//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  If StdDev is below STD setting the EA will pause until market picks up
  
  if(sval<=STD)
  {
  
   Comment( "                                          ","\n",   
            "**Market is not volatile enough to enter**","\n",
            "StdDev is currently:  " + sval,"\n",
            "StdDev needs to be: " +  STD,"\n",
            "AutoIncrement: " +  AutoIncrement,"\n",
            "Lots:  ",LOTS,"\n",
            "Levels: " + LEVELS,"\n",
            "5 Day Range:" + R5,"\n",
            "Previous Day Range: " + R1,"\n");
            
   return(0);
   }
   
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//+------------------------------------------------------------------+
  if (AccountProfit()<= Open_Loss_To_CloseTrades)
   {
    for(i=OrdersTotal()-1;i>=0;i--)
       {
       OrderSelect(i, SELECT_BY_POS);
       int type   = OrderType();
               
       bool result = false;
              
       switch(type)
          {
          //Close opened long positions
          case OP_BUY  : result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),Slippage,Pink);
                         break;
               
          //Close opened short positions
          case OP_SELL : result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),Slippage,Pink);
                          
          }
          
       if(result == false)
          {
            Sleep(3000);
          }  
       }
      Print ("Account Cutoff Limit Reached. All Open Trades Have Been Closed");
      return(0);
   }  
   
   Comment("Balance: ",AccountBalance(),", Account Equity: ",AccountEquity(),", Account Profit: ",AccountProfit(),
           "\nMy Account Cutoff Limit: ",Open_Loss_To_CloseTrades);
  
//+------------------------------------------------------------------+
  
  //----Money Management 
  
   if(AutoIncrement<MarketInfo(Symbol(),MODE_STOPLEVEL)+spread) AutoIncrement=1+MarketInfo(Symbol(),MODE_STOPLEVEL)+spread;
   if(MONEY_MANAGEMENT) LOTS=NormalizeDouble(AccountBalance()*AccountLeverage()/1000000*RISK_RATIO,0)*MarketInfo(Symbol(),MODE_MINLOT);
   if(LOTS<MarketInfo(Symbol(),MODE_MINLOT))
   {
      Comment("Not Enough Free Margin to begin");
      return(0);
   }
   for(cpt=1;cpt<LEVELS;cpt++) PipsLot+=cpt*AutoIncrement;
   for(cpt=0;cpt<OrdersTotal();cpt++)
   {
      OrderSelect(cpt,SELECT_BY_POS,MODE_TRADES);
      if(OrderMagicNumber()==MAGIC && OrderSymbol()==Symbol())
      {
         total++;
         if(!InitialPrice) InitialPrice=StrToDouble(OrderComment());
         if(UsePartialProfitTarget && UseProfitTarget && OrderType()<2)
         {
            double val=getPipValue(OrderOpenPrice(),OrderType());
            takeProfit(val,OrderTicket()); 
         }
      }
   }
   if(total<1 && Enter && (!UseEntryTime || (UseEntryTime && Hour()==EntryTime)))
   {
      if(AccountFreeMargin()<(100*LOTS))
      {
         Print("Not enough free margin to begin");
         return(0);
      }
      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      // - Open Check - Start Cycle
      InitialPrice=Ask;
      SellGoal=InitialPrice-(LEVELS+1)*AutoIncrement*Point;
      BuyGoal=InitialPrice+(LEVELS+1)*AutoIncrement*Point;
      for(cpt=1;cpt<=LEVELS;cpt++)
      {
         OrderSend(Symbol(),OP_BUYSTOP,LOTS,InitialPrice+cpt*AutoIncrement*Point,2,SellGoal,BuyGoal,DoubleToStr(InitialPrice,MarketInfo(Symbol(),MODE_DIGITS)),MAGIC,0);
         OrderSend(Symbol(),OP_SELLSTOP,LOTS,InitialPrice-cpt*AutoIncrement*Point,2,BuyGoal+spread*Point,SellGoal+spread*Point,DoubleToStr(InitialPrice,MarketInfo(Symbol(),MODE_DIGITS)),MAGIC,0);
      }
      
      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    } // initial setup done - all channels are set up
    else // We have open Orders
    {
      BuyGoal=InitialPrice+AutoIncrement*(LEVELS+1)*Point;
      SellGoal=InitialPrice-AutoIncrement*(LEVELS+1)*Point;
      total=OrdersHistoryTotal();
      for(cpt=0;cpt<total;cpt++)
      {
         OrderSelect(cpt,SELECT_BY_POS,MODE_HISTORY);
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGIC &&  StrToDouble(OrderComment())==InitialPrice){EndSession();return(0);}
      }
      if(UseProfitTarget && CheckProfits(LOTS,OP_SELL,true,InitialPrice)>ProfitTarget) {EndSession();return(0);}
      BuyGoalProfit=CheckProfits(LOTS,OP_BUY,false,InitialPrice);
      SellGoalProfit=CheckProfits(LOTS,OP_SELL,false,InitialPrice);
      if(BuyGoalProfit<ProfitTarget)
      // - Incriment Lots Buy
      {
         for(cpt=LEVELS;cpt>=1 && BuyGoalProfit<ProfitTarget;cpt--)
         {
            if(Ask<=(InitialPrice+(cpt*AutoIncrement-MarketInfo(Symbol(),MODE_STOPLEVEL))*Point))
            {
               ticket=OrderSend(Symbol(),OP_BUYSTOP,cpt*LOTS,InitialPrice+cpt*AutoIncrement*Point,2,SellGoal,BuyGoal,DoubleToStr(InitialPrice,MarketInfo(Symbol(),MODE_DIGITS)),MAGIC,0);
            }
            if(ticket>0) BuyGoalProfit+=LOTS*(BuyGoal-InitialPrice-cpt*AutoIncrement*Point)/Point;
         }
      }
      if(SellGoalProfit<ProfitTarget)
      // - AutoIncrement Lots Sell
      {
         for(cpt=LEVELS;cpt>=1 && SellGoalProfit<ProfitTarget;cpt--)
         {
            if(Bid>=(InitialPrice-(cpt*AutoIncrement-MarketInfo(Symbol(),MODE_STOPLEVEL))*Point))
            {
               ticket=OrderSend(Symbol(),OP_SELLSTOP,cpt*LOTS,InitialPrice-cpt*AutoIncrement*Point,2,BuyGoal+spread*Point,SellGoal+spread*Point,DoubleToStr(InitialPrice,MarketInfo(Symbol(),MODE_DIGITS)),MAGIC,0);
            }
            if(ticket>0) SellGoalProfit+=LOTS*(InitialPrice-cpt*AutoIncrement*Point-SellGoal-spread*Point)/Point;
         }
      }
   }
//+------------------------------------------------------------------+   

    Comment("mGRID EXPERT ADVISOR ver 2.0\n",
            "FX Acc Server:",AccountServer(),"\n",
            "Date: ",Month(),"-",Day(),"-",Year()," Server Time: ",Hour(),":",Minute(),":",Seconds(),"\n",
            "Minimum Lot Sizing: ",MarketInfo(Symbol(),MODE_MINLOT),"\n",
            "Account Balance:  $",AccountBalance(),"\n",
            "Symbol: ", Symbol(),"\n",
            "Price:  ",NormalizeDouble(Bid,4),"\n",
            "Pip Spread:  ",MarketInfo("EURUSD",MODE_SPREAD),"\n",
            "Lots:  ",LOTS,"\n",
            "Levels: " + LEVELS,"\n",
            "Free Margin: " + AccountFreeMargin(),"\n",
            "Free Equity: " + AccountEquity(),"\n",
            "Increment: " +  AutoIncrement,"\n",
            "5 Day Range:" + R5,"\n",
            "Daily Range: " + R1,"\n");
   return(0);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//+------------------------------------------------------------------+

int CheckProfits(double LOTS, int Goal, bool Current, double InitialPrice)
{
   int profit=0, cpt;
   if(Current)//return current profit
   {
      for(cpt=0;cpt<OrdersTotal();cpt++)
      {
         OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
         if(OrderSymbol()==Symbol() && StrToDouble(OrderComment())==InitialPrice)
         {
            if(OrderType()==OP_BUY) profit+=(Bid-OrderOpenPrice())/Point*OrderLots()/LOTS;
            if(OrderType()==OP_SELL) profit+=(OrderOpenPrice()-Ask)/Point*OrderLots()/LOTS;
         }
      }
      return(profit);
   }
   else
   {
      if(Goal==OP_BUY)
      {
         for(cpt=0;cpt<OrdersTotal();cpt++)
         {
            OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
            if(OrderSymbol()==Symbol() && StrToDouble(OrderComment())==InitialPrice)
            {
               if(OrderType()==OP_BUY) profit+=(OrderTakeProfit()-OrderOpenPrice())/Point*OrderLots()/LOTS;
               if(OrderType()==OP_SELL) profit-=(OrderStopLoss()-OrderOpenPrice())/Point*OrderLots()/LOTS;
               if(OrderType()==OP_BUYSTOP) profit+=(OrderTakeProfit()-OrderOpenPrice())/Point*OrderLots()/LOTS;
            }
         }
         return(profit);
      }
      else
      {
         for(cpt=0;cpt<OrdersTotal();cpt++)
         {
            OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
            if(OrderSymbol()==Symbol() && StrToDouble(OrderComment())==InitialPrice)
            {
               if(OrderType()==OP_BUY) profit-=(OrderOpenPrice()-OrderStopLoss())/Point*OrderLots()/LOTS;
               if(OrderType()==OP_SELL) profit+=(OrderOpenPrice()-OrderTakeProfit())/Point*OrderLots()/LOTS;
               if(OrderType()==OP_SELLSTOP) profit+=(OrderOpenPrice()-OrderTakeProfit())/Point*OrderLots()/LOTS;              
            }
         }
         return(profit);
      }
   }
}

bool EndSession()
{
   int cpt, total=OrdersTotal();
   for(cpt=0;cpt<total;cpt++)
   {
      Sleep(3000);
      OrderSelect(cpt,SELECT_BY_POS,MODE_TRADES);
      if(OrderSymbol()==Symbol() && OrderType()>1) OrderDelete(OrderTicket());
      else if(OrderSymbol()==Symbol() && OrderType()==OP_BUY) OrderClose(OrderTicket(),OrderLots(),Bid,3);
      else if(OrderSymbol()==Symbol() && OrderType()==OP_SELL) OrderClose(OrderTicket(),OrderLots(),Ask,3);
      
      }
      if(!CONTINUE)  Enter=false;
      return(true);
}


double getPipValue(double ord,int dir)
{
   double val;
   RefreshRates();
   if(dir == 1) val=(NormalizeDouble(ord,Digits) - NormalizeDouble(Ask,Digits));
   else val=(NormalizeDouble(Bid,Digits) - NormalizeDouble(ord,Digits));
   val = val/Point;
   return(val);   
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//========== FUNCTION takeProfit

void takeProfit(int current_pips, int ticket)
{
   if(OrderSelect(ticket, SELECT_BY_TICKET))
   {

      if(current_pips >= nextTP && current_pips < (nextTP + Target_AutoIncrement))
      {
         if(OrderType()==1)
         {
            if(OrderClose(ticket, MAX_LOTS, Ask, 3))
            nextTP+=Target_AutoIncrement;
            else
            Print("Error closing order : ",GetLastError()); 
         } 
         else
         {
            if(OrderClose(ticket, MAX_LOTS, Bid, 3))
            nextTP+=Target_AutoIncrement;
            else
            Print("Error closing order : ",GetLastError());  
         }        
      }
   }
}

