//+------------------------------------------------------------------+
//|                                                    fozzy_1-0.mq4 |
//|             Copyright © 2006, Taylor Stockwell & Daniel Frieling |
//|                        stockwet@yahoo.com & tradeigel@gmail.com  |
//|                                                  Version: 2.0.0  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Taylor Stockwell & Daniel Frieling"
#property link      "stockwet@yahoo.com & tradeigel@gmail.com"

/* =============== Updates
:: 9-29-2006: Changed okToCheck to support trading only on 00 GMT, if the Use_00_GMT variable is set to 
              true. Otherwise, trades open on new bar.    
:: 9-30-2006: Added parameter to specify MA method. Uses EMA by default now.
:: 10-2-2006: Added ability to set SL according to ATR(10) method, as described by BeachBum
:: 10-3-2006: Added feature for taking partial profit out at a specified level. User specifies number of lots to take out.
              Currently, this feature only supports a single partial profit takeout. It looks to see if the order lots
              is equal to the Lots value. So, the EA can be "tricked" into taking additional partial profit by modifying the 
              Lots value to equal the current open order lots remaining and resetting the partial profit value.   
*/

//=============== VARS external
extern bool Use_BB_Filter = true; //Set to false if you want to take ALL crosses regardless of BB median line
extern bool Use_00_GMT = true;    //Only trade daily charts. Set to false if want to trade lower timeframes
extern double Lots = 2.0;         //Lots to trade with
extern double Take_Partial_Profit_Lots = 1.0;
extern int Take_Partial_Profit = 40; //Set to 0 to turn Partial Profit off.
extern int TakeProfit = 130;      //Where to take profit out at
extern bool Use_ATR_Stop = true;   //Set to true if set initial stop based on ATR(10) versus high/low prev bar.
extern double Use_ATR_Pct = 0.7;
extern int Init_Stop_Cushion = 0; //Stops set at previous high/low, plus a little cushion above or below
extern bool TrailingStop = true;  //Set to true if you want to use the trailing stop
extern int TrailingAct = 65;      //When to start trailing (BE + Trailing Step)
extern int TrailingStep = 25;     // How much to trail by
extern int Start_BE = 40;         // When to move to B/E
extern int MA_Method=MODE_EMA;
extern int    RSIPeriod = 8;      // RSI period to use
extern int    RSIMAPeriod = 8;    // MA on RSI period to use
extern int    BandsPeriod=20;     // Bollinger Bands period to use

//=============== VARS internal
int magic = 7984; //Magic number for system - same as topic ID at FF
int lastBars;
string EA_comment = "Fozzy Method v2.0";
double version=2.0;
int Slippage = 2;
//---- indicator parameters

int    BandsShift=0;
double BandsDeviations=2.0;


//=============== function: init
int init()
  {

    lastBars = Bars;
  }
  
double getATR()
{
  double atr=iATR(NULL,0,10,0);
  double atr_val = atr*Use_ATR_Pct;
  return(atr_val);
}

//=============== function: rsi1 (gets RSI of recently closed bar)
double rsi1()
{
  double rsival = iRSI(Symbol(),0,RSIPeriod,PRICE_CLOSE,1);
  return(rsival);
}

//=============== function: rsi2 (gets RSI of previously closed bar)
double rsi2()
{
  double rsival = iRSI(Symbol(),0,RSIPeriod,PRICE_CLOSE,2);
  return(rsival);
}



//=============== function: rsiMA1 (ma for rsi of recently closed bar)
double rsiMA1()
{
  double rsi[8];
  for(int i=0;i<RSIMAPeriod;i++)
  rsi[i]=iRSI(Symbol(),0, RSIPeriod, PRICE_CLOSE,i+1);
  double sma = iMAOnArray(rsi, 0,RSIMAPeriod,0,MA_Method,0);
  return(sma);
}

//=============== function: rsiMA2 (ma for rsi of previous bar)
double rsiMA2()
{
  double rsi[8];
  for(int i=0;i<RSIMAPeriod;i++)
  rsi[i]=iRSI(Symbol(),0, RSIPeriod, PRICE_CLOSE,i+2);   
  double sma = iMAOnArray(rsi,0,RSIMAPeriod,0,MA_Method,0);
  return(sma);
}

//=============== function: bands1 (gets BB value on the RSI array for recently closed bar)
double bands1()
{
  double rsi[20];
  for(int i=0;i<BandsPeriod;i++)
  rsi[i]=iRSI(Symbol(),0, RSIPeriod, PRICE_CLOSE,i+1);   
  double bb = iBandsOnArray(rsi,0,BandsPeriod,BandsDeviations,0,MODE_MAIN,0);
  return(bb);
}

//=============== function: getInitSL (returns Prev Bar Low / High +/- cusion amount)
double getInitSL(int direction, double price)
{
 double initSL;

 if(direction == 0)  // if going LONG is what we're aiming for
  {
    if(Use_ATR_Stop) initSL=price-getATR()-(Init_Stop_Cushion*Point);
    else initSL = iLow(Symbol(), 0, 1)-(Init_Stop_Cushion*Point);
  }
  else if(direction == 1)  // if going SHORT is what we're aiming for
  {
    if(Use_ATR_Stop) initSL=price+getATR()+(Init_Stop_Cushion*Point);
    else initSL = iHigh(Symbol(), 0, 1)+(Init_Stop_Cushion*Point);
  }
 return(initSL);
}


//=============== function: checkOpenTrade (Checks to see if a system trade is open.)
int checkOpenTrade()
{
  int totalorders = OrdersTotal(); // Calls a function to get all the open orders.
  bool orderFound;
  for(int j=0; j<totalorders;j++)
  {    
    OrderSelect(j, SELECT_BY_POS, MODE_TRADES);
    if(OrderMagicNumber() == magic && OrderSymbol() == Symbol())
    {
      orderFound=1;
      break;
    } 
    else
    {
      orderFound=0;
    } 
      
   }
   return(orderFound);
    //if(orderFound==1) return(1);
    //else return(0);
   // return(1);
}
   
   
//=============== function: okToCheck (Start trade at 00:00)
bool okToCheck()
{
//If Daily_Only is true, then trade at 00 GMT. This, however, prevents lower
//timeframes from being tested and traded.

if(Use_00_GMT)
  {
   if(Hour() == 0 && (Minute() >= 0 && Minute() <= 2))
     return(true);

   return(false);
  }
  else
  {
   bool barOK;
     if (lastBars != Bars && checkOpenTrade()==0) barOK = true;
     else barOK = false;

     return(barOK);
  }

}
//=============== function: getSignal (Indicates whether a valid signal has occurred)
int getSignal()
{
  if(okToCheck())
  {
    bool signal;
    signal = 0;
    
    //Checks to see where the rsi is relative the ma on the previous bar
    bool previous;
    if(rsi2() > rsiMA2()) previous=0;   //rsi above ma, bull signal
    else previous = 1;                  //rsi below ma, bear signal
    
    //Checks to see where the rsi is relative the ma on the last bar
    bool last;
    if(rsi1() > rsiMA1()) last=0;     //rsi above ma, bull signal
    else last = 1;                    //rsi below ma, bear signal
    
    // This checks to see where the RSI and MA lines are relative to the BB median line.
    // 0 = the ma and rsi are below the bb median line
    // 10 = the ma and rsi are above the bb median line
    // 5 = the ma and rsi are mixed - above and below the bb median line
    int checkBB=5;
    if(rsiMA1() < bands1()) checkBB=0;          //ma below bands, bull signal only - no bears
    else if(rsiMA1() > bands1()) checkBB = 10;  //ma above bands, bear signal only - no bulls
  
    //Checks if a new cross occurred, set the signal to 1.
    if(previous != last) signal=1;
    else signal = 0;
    
    
    //If a new cross occurred, handle remaining signal criteria and place trade.
    if(signal)
    {
      if(Use_BB_Filter == false) //ignore BB median line criteria
      {
        // If a new crossing above occured, sell trade
        if(last==1) openTrade(1);
        // If a new crossing above occured, buy trade
        else if(last==0) openTrade(0);
      }
      else
      {
        // If a new crossing above occured with MA and RSI below the median BB line, buy trade
        if(last==1 && checkBB == 10) openTrade(1);
        // If a new crossing above occured with MA and RSI above the median BB line, sell trade
        else if(last==0 && checkBB == 0) openTrade(0);
      }
      
    }
    
  }
  return(signal);
}
   


//=============== function: 0penTrade (Open 00:00 GMT candle, if criteria met)
bool openTrade(int direction)
{
 int ticket = -1;

 if(direction == 0) //Buy
   ticket = OrderSend(Symbol(), direction, Lots, Ask, Slippage, getInitSL(direction, Bid), Bid+TakeProfit*Point, EA_comment, magic);

 else
   if(direction == 1) //Sell
     ticket = OrderSend(Symbol(), direction, Lots, Bid, Slippage, getInitSL(direction, Ask), Ask-TakeProfit*Point, EA_comment, magic);

 if(ticket >= 0) // if order opened sucessfully
 {
   Print("Order sucessfully opened!");
   return(true);
 }
 else
 {
   Print("ERROR: <OrderSend> "+GetLastError());
   return(false);
 }
}


//--------------- function: trailing  (should be included in start() right at the beginning
int trailing()
{
//----------------- CHECK CLOSE/TRAILING STOP ORDERS
 int total = OrdersTotal();
 for(int cnt = 0; cnt < total; cnt++)
 {
   OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);

   if( (OrderType() <= OP_SELL) && (OrderSymbol() == Symbol()) && (OrderMagicNumber() == magic) )
   {
     double orderProfit = -1;

     if(OrderType() == OP_BUY)
     {
       orderProfit = (Bid - OrderOpenPrice()) / Point;
       if(Take_Partial_Profit != 0 && orderProfit >= Take_Partial_Profit && OrderLots() == Lots)
       {        
        OrderClose(OrderTicket(),Take_Partial_Profit_Lots, Bid, 0, LimeGreen);        
       }
            
       
       if(OrderStopLoss() < OrderOpenPrice())
       {
         // moving stop to B/E if profit > Start_BE

         if(orderProfit >= Start_BE)
           OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), 0, 0, Green);
         

       }

       if(TrailingStop)
       {
         if((Bid-OrderOpenPrice()) > (Point*TrailingAct))  // if you are 'TrailingAct' or higer in Profit
         {
           if((OrderStopLoss()) < (Bid-Point*TrailingStep))  // if S/L is lower than Bid-'TrailingStep'
           {
             OrderModify(OrderTicket(), OrderOpenPrice() ,Bid-Point*TrailingStep, 0, 0, GreenYellow);
             return(0);
           }
         }
       }
     }

     if(OrderType() == OP_SELL)
     {
       orderProfit = (OrderOpenPrice() - Ask) / Point;
       if(Take_Partial_Profit != 0 && orderProfit >= Take_Partial_Profit && OrderLots() == Lots)
       {        
        OrderClose(OrderTicket(),Take_Partial_Profit_Lots, Ask, 0, LimeGreen);       
       }
       if(OrderStopLoss() > OrderOpenPrice())
       {
         // moving stop to B/E if profit > Start_BE         
         if(orderProfit >= Start_BE)
           OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice(), 0, 0, Green);
       }

       if(TrailingStop)
       {
         if(OrderOpenPrice()-Ask>Point*TrailingAct)
         {
           if(OrderStopLoss()>Ask+Point*TrailingStep)
           {
             OrderModify(OrderTicket(), OrderOpenPrice(), Ask+Point*TrailingStep, 0, 0, Red);
             return(0);
           }
         }
       }
     }
   }
 }


 return(0);
}







//=============== function: deinit
int deinit()
  {
   return(0);
  }
  
  
//=============== function: start
int start()
  {
  bool testing = 0;
  if(testing)
  {
      Comment("Last RSI: ", rsi1(), 
    "\nLast RSI MA: ",rsiMA1(), 
    " \nPrev RSI MA: ", rsiMA2(), 
    " \nBands: ", bands1(),
    "\nOpenTrade: ",checkOpenTrade(),
    "\nStop by ATR Val: ",getATR());
  }
  trailing();
  
  if(checkOpenTrade() == 0) getSignal();
  else return(0);
  }

