//+------------------------------------------------------------------+
//|                                                   Pip Nailer.mq4 |
//|                                                      Flying Fish |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Flying Fish"
#property link      ""
         string ExpertName = "Pip Nailer";
//---- input parameters
         int    Ticket;
         int    MagicNumber = 15125;
extern   double RiskPercent = 0.02;
extern   bool   useFixedLot = false;
extern   double lotSize = 0;
         
         double AO[4], AC[4], SAR[4];
         bool   acFlag = false;
         bool   aoFlag = false;
         
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {   
//----
   MagicNumber = MagicNumber + Period();
   int totalOrders = OrdersTotal();
   for (int i = 0; i < totalOrders; i++)
   {
    OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
    if(OrderMagicNumber() == MagicNumber &&
       OrderSymbol() == Symbol())
    {
     Ticket = OrderTicket();
     return(0); 
    }
   }
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {  
//----    
   if (!NewBar()) return(0);

   if (Ticket > 0)
   {
    OrderSelect(Ticket, SELECT_BY_TICKET);
    if (OrderCloseTime() != 0)
     Ticket = 0;
   }

   for( int i=0; i<4; i++)
   {
       AO[i] = iAO(NULL,0,i);
       AC[i] = iAC(NULL,0,i);
      SAR[i] = iSAR(NULL,0,0.02, 0.20, i);
   }
   
   bool signalAO  = checkSignal(AO);
   bool signalAC  = checkSignal(AC);
   bool signalSAR = checkSAR(SAR);
   
   if (Ticket > 0)
   {
    if (signalAC) acFlag = true;
    if (signalAO) aoFlag = true;
    if (acFlag && aoFlag) 
     Ticket = CloseOrder(Ticket);
   }
   
   if (signalAO && signalAC && signalSAR) 
   {
    if (SAR[1] < (Open[1]+Close[1])/2)
     Ticket = OpenOrder(LONG_VALUE);
    else
     Ticket = OpenOrder(SHORT_VALUE);
     
    acFlag = false;
    aoFlag = false; 
   }   


//----
   return(0);
  }
//+------------------------------------------------------------------+
bool NewBar()
{
   static datetime dt = 0;
   
   if (Time[0] != dt)
   {
      dt = Time[0];
      return(true);
   }
   return(false);
}
      
int OpenOrder(int direction)
{
   int Ticket;
   double Lots, TP;
   
   if(direction == LONG_VALUE)
   {
    TP = Open[0] - Low[1];
    Lots = calcLots(TP);
    Ticket = OrderSend(Symbol(),OP_BUY,Lots,Ask,(Ask-Bid)/Point,Bid-TP,Ask+TP,ExpertName,MagicNumber,0,Green);
    if (Ticket == -1) Print("Failed to place Buy order, error = ",GetLastError());
   } else
   {
    TP = High[1] - Open[0];
    Lots = calcLots(TP);
    Ticket = OrderSend(Symbol(),OP_SELL,Lots,Bid,(Ask-Bid)/Point,Ask+TP,Bid-TP,ExpertName,MagicNumber,0,Green);
    if (Ticket == -1) Print("Failed to place Sell order, error = ",GetLastError());
   }
   return(Ticket);
}

int CloseOrder(int Ticket)
{
  OrderSelect(Ticket, SELECT_BY_TICKET);
   if(OrderType()==OP_BUY)
   {
    OrderClose(Ticket,OrderLots(),Bid,3,Green);
    if (GetLastError() != 0)
    {
     Print("Failed to close ticket (",OrderTicket(),"), Error: ",GetLastError());
     return(Ticket);
    }
   }
   if(OrderType()==OP_SELL)
   {
    OrderClose(Ticket,OrderLots(),Ask,3,Red);
    if (GetLastError() != 0)
    {
     Print("Failed to close ticket (",OrderTicket(),"), Error: ",GetLastError());
     return(Ticket);
    }
   }
  return(0);
}

double calcLots(double reward)
{
   reward = reward/Point;
   double lot_min =MarketInfo(Symbol(),MODE_MINLOT);
   double lot_max =MarketInfo(Symbol(),MODE_MAXLOT);
   double lot_step=MarketInfo(Symbol(),MODE_LOTSTEP);
   
   if (reward < 1) return (lot_min);  //guard against divide by zero error
   
   double risk = AccountBalance() * RiskPercent;
   double vol =  risk / (reward*MarketInfo(Symbol(), MODE_TICKVALUE));

   if (useFixedLot) vol = lotSize;
   
   vol=NormalizeDouble(vol/lot_step,0)*lot_step;
   
   if(vol<lot_min) vol=lot_min;
   if(vol>lot_max) vol=lot_max;

   return(vol);
}

bool checkSignal(double signal[])
{
 if (signal[1] > signal[2] && signal[2] < signal[3]) return(true);
 if (signal[1] < signal[2] && signal[2] > signal[3]) return(true);
 return(false);
}

bool checkSAR(double signal[])
{
 if (signal[1] < (Open[1]+Close[1])/2 && signal[2] > (Open[2]+Close[2])/2) return(true);
 if (signal[1] > (Open[1]+Close[1])/2 && signal[2] < (Open[2]+Close[2])/2) return(true);
 return(false);
}