//+------------------------------------------------------------------+
//|                                        5 Pips System.mq4         |
//|                                   Copyright © 2014, David Currey |
//|                                                                  |
//+------------------------------------------------------------------+
extern int MAGICMA = 123450;
extern double LotSize = 0;
extern double MaximumRiskPercentage = 2;
extern int ShortMA = 5;
extern int Shift = 2;
extern int MinBreakofSMA = 3;
extern int MaxCandlesforResult = 4;
extern int LongMA = 200;
extern int RSICalcPeriods = 8;
extern int TopRSILevel = 70;
extern int BottomRSILevel = 30;
extern int ATRLookback = 5;
extern int MinATRPips = 5;
extern int PresetStopLoss = 0;        
extern int StopWin = 5;         
extern int TradingHoursStart = 0; 
extern int TradingHoursEnd = 0;
extern int NewsHour1 = 0;
extern int NewsMinute1 = 0;
extern int NewsHour2 = 0;
extern int NewsMinute2 = 0;
extern int NewsHour3 = 0;
extern int NewsMinute3 = 0;
extern int AvoidMinutesBeforeNews = 10;
extern int AvoidMinutesAfterNews = 30; 
extern string Message = "5 Pip System";
string Comment1;
double StopLoss;
double HA2Previous;
double HA1Previous;
double HACurrent;
double CurrentFastMA;
double CurrentSlowMA;
double PrevFastMA;
double TakeWinPrice;
double CurrentProfitTarget;
double StopLossPrice;
double CurrentMain;
double PreviousMain;
double CurrentRSI;
double PreviousRSI;
double TradeTime;
double CurrentTime;
int StartHour1;
int EndHour1;
int StartMinute1;
int EndMinute1;
int StartHour2;
int EndHour2;
int StartMinute2;
int EndMinute2;
int StartHour3;
int EndHour3;
int StartMinute3;
int EndMinute3;
int Modified;
int TopRSI;
int BottomRSI;
double Wager;
//+------------------------------------------------------------------+
//| Calculate open positions                                         |
//+------------------------------------------------------------------+
int CalculateCurrentOrders(string symbol)
  {
   int buys=0,sells=0;
//----
   for(int i=0;i<OrdersTotal();i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
        {
         if((OrderType()==OP_BUY) || (OrderType()==OP_BUYLIMIT))  buys++;
         if((OrderType()==OP_SELL) || (OrderType()==OP_SELLLIMIT)) sells++;
        }
     }

//---- return orders volume
 
   if(buys>0) return(buys);
   else       return(-sells);
  }
//+------------------------------------------------------------------+
//| Calculate optimal lot size                                       |
//+------------------------------------------------------------------+
double LotsOptimized()
  {
   double lot;
   //---- select lot size based on equity and projected stop loss
   if (LotSize == 0) lot=NormalizeDouble(AccountEquity() * MaximumRiskPercentage / Close[0] / 100000 ,2);
   if (LotSize != 0) lot = LotSize;
   return(lot);
  }
//+------------------------------------------------------------------+
//| Check RSI Cross of top and bottom levels                                |
//+------------------------------------------------------------------+
void CheckForRSI()
  {
   for(int i=0;i<10;i++)
     {
     CurrentRSI = NormalizeDouble(iRSI(Symbol(),0,RSICalcPeriods,PRICE_CLOSE,i+1),7);
     PreviousRSI = NormalizeDouble(iRSI(Symbol(),0,RSICalcPeriods,PRICE_CLOSE,i),7);
     if(PreviousRSI <= BottomRSILevel && CurrentRSI > BottomRSILevel)
         {
         BottomRSI = 1;
         TopRSI = 0;
         return;
         }
     if(PreviousRSI >= TopRSILevel && CurrentRSI < TopRSILevel)
         {
         TopRSI = 1;
         BottomRSI = 0;
         return;
         }
     }    
  }
//+------------------------------------------------------------------+
//| Check for open order conditions                                  |
//+------------------------------------------------------------------+
void CheckForOpen()
  {
  int res;
  // calculate Heiken Ashi Prices
  HA2Previous = (Open[2]+High[2]+Low[2]+Close[2])/4;
  HA1Previous = (Open[1]+High[1]+Low[1]+Close[1])/4;
  HACurrent = Open[0];
  CurrentFastMA = NormalizeDouble(iMA(Symbol(),0,ShortMA,Shift,MODE_EMA,PRICE_CLOSE,1),7);
  PrevFastMA = NormalizeDouble(iMA(Symbol(),0,ShortMA,Shift,MODE_EMA,PRICE_CLOSE,2),7);
  CurrentSlowMA = NormalizeDouble(iMA(Symbol(),0,LongMA,0,MODE_EMA,PRICE_CLOSE,0),7);
  Comment1 = StringConcatenate(Symbol()," ",Message);
 
    // ---- buy conditions HAPrice moves above FastMA and is above SlowMA and RSI has given an up signal within last 10 periods and ATR is => Min Pips 
    if ((HA1Previous > CurrentFastMA ) && (HA2Previous <= PrevFastMA) && (HACurrent > CurrentSlowMA) && (BottomRSI == 1) && (iATR(Symbol(),0,ATRLookback,0) >=  MinATRPips/10000))
       {

       if (PresetStopLoss == 0) StopLoss = (Close[0] - Low[2]) * 10000;
       if (PresetStopLoss != 0) StopLoss = PresetStopLoss;
       // also reject trades with very small last 2 candles
       if (StopLoss < 5) return;
       
       // insufficient break of SMA
       if (MinBreakofSMA != 0 && (Close[1] - CurrentFastMA) * 10000  < MinBreakofSMA) return;

       Wager = LotsOptimized();
       res=OrderSend(Symbol(),OP_BUY,Wager,Ask,1,0,0,Comment1,MAGICMA,0,Green);
       Modified = 0;
       TradeTime = datetime(TimeCurrent());
       return;
       }

    // ---- sell conditions HAPrice moves below FastMA and is below SlowMA and RSI has given an down signal within last 10 periods and ATR is => Min Pips 
    if ((HA1Previous < CurrentFastMA ) && (HA2Previous >= PrevFastMA) && (HACurrent < CurrentSlowMA) && (TopRSI == 1) && (iATR(Symbol(),0,ATRLookback,0) >=  MinATRPips/10000))
       {
 
       if (PresetStopLoss == 0) StopLoss = (High[2] - Close[0]) * 10000;
       if (PresetStopLoss != 0) StopLoss = PresetStopLoss;

       // also reject trades with very small last 2 candles
       if (StopLoss < 5) return;

       // insufficient break of SMA
       if (MinBreakofSMA != 0 &&  (CurrentFastMA - Close[1]) * 10000  < MinBreakofSMA) return;

       Wager = LotsOptimized();
       res=OrderSend(Symbol(),OP_SELL,Wager,Bid,1,0,0,Comment1,MAGICMA,0,Green);
       Modified = 0;
       TradeTime = datetime(TimeCurrent());
       return;
       }

   }
//+------------------------------------------------------------------+
//| Check for modify order conditions                                 |
//+------------------------------------------------------------------+
void CheckForModify()
  {
  int res;

     for(int i=0;i<OrdersTotal();i++)
         {
         if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)        break;
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
         {
         
 
         // Add StopLoss to original filled order 
         if (Modified==0) 
            {
            if(OrderType()==OP_BUY) StopLossPrice = Bid - (StopLoss * Point * 10);
            if(OrderType()==OP_BUY) TakeWinPrice = Ask + (StopWin * Point * 10);
            if(OrderType()==OP_SELL) StopLossPrice = Ask + (StopLoss * Point * 10);
            if(OrderType()==OP_SELL) TakeWinPrice = Bid - (StopWin * Point * 10);
            res = OrderModify(OrderTicket(),OrderOpenPrice(),StopLossPrice, TakeWinPrice, 0,Red);
            CurrentProfitTarget = Wager * Close[0] * 50;
            if (res > -1) Modified = 1;
            } // end of modified = 0
            
         // set trailing StopLoss 
         if (Modified == 1)
            {
            if (OrderProfit() > CurrentProfitTarget) 
               {
               // set the StopLoss to (current price - stop win)
               if (OrderType()==OP_BUY) StopLossPrice = Bid - (StopLoss * Point * 10);
               if (OrderType()==OP_SELL) StopLossPrice = Ask + (StopLoss * Point * 10);
               Print("StopLossPrice ",StopLossPrice);
               res = OrderModify(OrderTicket(),OrderOpenPrice(),StopLossPrice, TakeWinPrice, 0, Red);
               // Set Profit Target to Current Profit + 5%
               if (res > -1)
                 {
                 CurrentProfitTarget = CurrentProfitTarget + (Wager * Close[0] * 50);
                 break;
                 }
               } // end of order profit
            } // end of modified = 1
         } // end of qualifying orders
         } // end of for/next
  } // end of function         
//+------------------------------------------------------------------+
//| Check for close order conditions                                 |
//+------------------------------------------------------------------+
void CheckForClose()
  {
  int i;
  int res;
  if (MaxCandlesforResult == 0) return;
  CurrentTime = datetime(TimeCurrent());
  if ((CurrentTime - TradeTime) / PeriodSeconds() < MaxCandlesforResult) return;
  for (i = OrdersTotal()-1; i >= 0; i--) 
     { 
     res = OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
     if(OrderSymbol() == Symbol() && OrderMagicNumber() == MAGICMA) 
        { 
        res = OrderClose(OrderTicket(),OrderLots(),Bid,1,Red);
        }
     } 
  }
//+------------------------------------------------------------------+
//| Start function                                                   |
//+------------------------------------------------------------------+
void start()
  {
   //---- check for history and trading
 
   if(Bars<100 || IsTradeAllowed()==false) return;

   //---- calculate open orders by current symbol

   if(CalculateCurrentOrders(Symbol())==0)
       {
       // Check for Trading Hours
       if (TradingHoursStart !=0 && Hour() < TradingHoursStart) return;
       if (TradingHoursEnd !=0 && Hour() > TradingHoursEnd) return;

       // Avoid News
       if (NewsHour1 != 0)
         {
         StartHour1 = NewsHour1;
         StartMinute1 = NewsMinute1 - AvoidMinutesBeforeNews;
         if (StartMinute1 < 0)
           {
           StartMinute1 = StartMinute1 + 60;
           StartHour1 = StartHour1 - 1;
           if (StartHour1 < 0) StartHour1 = StartHour1 + 24;
           }
         EndHour1 = NewsHour1; 
         EndMinute1 = NewsMinute1 + AvoidMinutesAfterNews; 
         if (EndMinute1 > 59)
           {
           EndMinute1 = EndMinute1 - 60;
           EndHour1 = EndHour1 + 1;
           }
         if (EndHour1 > 23) EndHour1 = EndHour1 - 24;
         if (Hour() >= StartHour1 && Minute() >= StartMinute1)
           {
           if (Hour() == EndHour1 && Minute() <= EndMinute1) return; 
           }
         }

       if (NewsHour2 != 0)
         {
         StartHour2 = NewsHour2;
         StartMinute2 = NewsMinute2 - AvoidMinutesBeforeNews;
         if (StartMinute2 < 0)
           {
           StartMinute2 = StartMinute2 + 60;
           StartHour2 = StartHour2 - 1;
           if (StartHour2 < 0) StartHour2 = StartHour2 + 24;
           }
         EndHour2 = NewsHour2; 
         EndMinute2 = NewsMinute2 + AvoidMinutesAfterNews; 
         if (EndMinute2 > 59)
           {
           EndMinute2 = EndMinute2 - 60;
           EndHour2 = EndHour2 + 1;
           }
         if (EndHour2 > 23) EndHour2 = EndHour2 - 24;
         if (Hour() >= StartHour2 && Minute() >= StartMinute2)
           {
           if (Hour() == EndHour2 && Minute() <= EndMinute2) return; 
           }
         }

       if (NewsHour3 != 0)
         {
         StartHour3 = NewsHour3;
         StartMinute3 = NewsMinute3 - AvoidMinutesBeforeNews;
         if (StartMinute3 < 0)
           {
           StartMinute3 = StartMinute3 + 60;
           StartHour3 = StartHour3 - 1;
           if (StartHour3 < 0) StartHour3 = StartHour3 + 24;
           }
         EndHour3 = NewsHour3; 
         EndMinute3 = NewsMinute3 + AvoidMinutesAfterNews; 
         if (EndMinute3 > 59)
           {
           EndMinute3 = EndMinute3 - 60;
           EndHour3 = EndHour3 + 1;
           }
         if (EndHour3 > 23) EndHour3 = EndHour2 - 24;
         if (Hour() >= StartHour3 && Minute() >= StartMinute3)
           {
           if (Hour() == EndHour3 && Minute() <= EndMinute3) return; 
           }
         }

       CheckForRSI();
       CheckForOpen();
       }
    else 
       CheckForModify();
       CheckForClose();
  }
//+------------------------------------------------------------------+

