// Digger R&D version AAA
// Entry: Random or Reverse
// TP: Trailing stop according to Volatility

#include <Trade\Trade.mqh>

#define              N 5                    
input int            SLFactor=5;  
               
enum                 lastDealEnum {no,buy,sell}; 
lastDealEnum         lastDeal = buy;
datetime             BarTime=D'03.12.1977'; 
CTrade Trade;

void OnTick()
{

   if(NewBar())
      if(!PositionSelect(Symbol())) 
         Trade();

   TrailingStop();

   return;
}

bool NewBar()
{
   datetime New_Time[1];
   int copied=CopyTime(_Symbol,_Period,0,1,New_Time);
   if(copied>0)
     {
      if(BarTime!=New_Time[0])
        {
         BarTime=New_Time[0];
         return(true);
        }
     }
   else
     {
      Alert(GetLastError());
      ResetLastError();
      return(false);
     }
   return(false);
}

bool TradeDirection()
{
   
   // Random Directiom
   bool r=(rand()>32768/2);      
   return(r);

   // Reverse entry
/*   if(lastDeal==buy) 
   {
      lastDeal=sell; 
      return(false);
   }
   if(lastDeal==sell) 
   {
      lastDeal=buy; 
      return(true);
   }
*/   
   return(true);
}

void Trade()
{
   double LotSize=0;

   if(TradeDirection())
     {
      LotSize=0.1;
      SendBuyOrder(LotSize);
     }
   else
     {
      LotSize=0.1;
      SendSellOrder(LotSize);
     }
   return;
}

void TrailingStop()
{

   MqlRates rates[N];
   if(CopyRates(_Symbol,_Period,0,N,rates)!=N)
   {
      Alert("CopyRates of ",_Symbol," failed, no history");
      return;
   }

   double AverageVolatility=0;
   for(int i=0; i<N; i++)
   {
      AverageVolatility=AverageVolatility + rates[i].high - rates[i].low;
   }
   AverageVolatility=AverageVolatility/N;
   
   
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);
  
   for(int i = PositionsTotal()-1; i >= 0; i--)
   {
      string symbol = PositionGetSymbol(i);
      
      if(_Symbol == symbol)
      {
         ulong PositionTicket = PositionGetInteger(POSITION_TICKET);
         double CurrentStopLoss = PositionGetDouble(POSITION_SL);

         if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
         {
            if(MathAbs(Ask-CurrentStopLoss) > AverageVolatility*SLFactor)
            {
               double SL=NormalizeDouble(Ask-AverageVolatility*SLFactor,_Digits);
               Trade.PositionModify(PositionTicket, SL, 0);
            }
         }

         if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
         {
            if(MathAbs(CurrentStopLoss-Bid) > AverageVolatility*SLFactor)
            {
               double SL = NormalizeDouble(Bid + AverageVolatility*SLFactor,_Digits);
               Trade.PositionModify(PositionTicket, SL, 0);
            }
         }
      }
   }
   return;
}
  
void SendBuyOrder(double pLotSize)
{
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);
   
   if(!Trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, pLotSize, Ask, 0, 0))
   {
      Alert("Can not open buy position by symbol ",_Symbol);
      return;
   }
   return;
}
  
void SendSellOrder(double pLotSize)
{
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);
   
   if(!Trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, pLotSize, Bid, 0, 0))
   {
      Alert("Can not open sell position by symbol  ",_Symbol);
      return;
   }
   return;
}
