//+------------------------------------------------------------------+
//|                                                                  |
//|             RSI-R2.mq4 - Ver 1.0 @ 03/22/2007 by Bluto           |
//|                                                                  |
//| Added code to allow selection of currency pairs to trade         |
//| For each pair TradeXXXYYY was added as an input.                 |
//| When set to true that pair will be in the trade list             | 
//+------------------------------------------------------------------+


#property copyright "Bluto"
#property link      "None"
#include <stderror.mqh>
#include <stdlib.mqh>

extern double LotSize=0.5;
extern int    Slippage=3;
extern double StopLoss=0;
extern double TakeProfit=700;
extern double RiskPercent=2.0;
extern bool   UseMoneyMgmt=true;
extern double RSI_Overbought_Value = 85.0; 
extern double RSI_Oversold_Value = 15.0; 

// Boolean inputs to create trade list
extern bool   TradeEURUSD = true;
extern bool   TradeUSDJPY = true;
extern bool   TradeGBPUSD = true;
extern bool   TradeUSDCHF = true;
extern bool   TradeEURCHF = true;
extern bool   TradeAUDUSD = true;
extern bool   TradeUSDCAD = true;
extern bool   TradeNZDUSD = true;
extern bool   TradeEURGBP = true;
extern bool   TradeEURJPY = true;
extern bool   TradeGBPJPY = true;
extern bool   TradeCHFJPY = true;
extern bool   TradeGBPCHF = true;
extern bool   TradeEURAUD = true;
extern bool   TradeEURCAD = true;
extern bool   TradeAUDCAD = true;
extern bool   TradeAUDJPY = true;
extern bool   TradeNZDJPY = true;
extern bool   TradeAUDNZD = true;

int           MagicNumber=0;
int           ticket;
int           OpenBuyOrders=0;
int           OpenSellOrders=0;
int           i;
bool          Buy_Mode=false, Sell_Mode=false;
double        RSI_Day_1=0, RSI_Day_2=0, RSI_Day_3=0, SMA200_Day3=0;
double        MM_MinLotSize=0;
double        MM_MaxLotSize=0;
double        MM_LotStep=0;
double        MM_Decimals=0;
double        MM_OrderLotSize=0;
int           MM_AcctLeverage=0;
int           MM_CurrencyLotSize=0;

//pair array ( IBFX mini )
string pairs[] = { "EURUSDm","USDJPYm","GBPUSDm","USDCHFm","EURCHFm","AUDUSDm","USDCADm",
                   "NZDUSDm","EURGBPm","EURJPYm","GBPJPYm","CHFJPYm","GBPCHFm","EURAUDm",
                   "EURCADm","AUDCADm","AUDJPYm","NZDJPYm","AUDNZDm" };
string   TradeSymbol,CommentsPairs[];
int      Pair = -1;


int init()  {
if ( IsTesting() ) { if ( ArrayResize(pairs,1) != 0 )  pairs[0] = Symbol();   }  
ArrayCopy (CommentsPairs, pairs);
return(0); }

int deinit()   {  return(0);  }

// Determine if trade is in the list
// by checking boolean input for true
bool CheckTradeList(string mTradeSymbol)
{
  string myTradeSymbol = "";
 
  myTradeSymbol=StringSubstr(mTradeSymbol,0,6);

  if (myTradeSymbol=="AUDCAD" && TradeAUDCAD) return(true);
  if (myTradeSymbol=="AUDJPY" && TradeAUDJPY) return(true);
  if (myTradeSymbol=="AUDNZD" && TradeAUDNZD) return(true);
  if (myTradeSymbol=="AUDUSD" && TradeAUDUSD) return(true);
  if (myTradeSymbol=="CHFJPY" && TradeCHFJPY) return(true);
  if (myTradeSymbol=="EURAUD" && TradeEURAUD) return(true);
  if (myTradeSymbol=="EURCAD" && TradeEURCAD) return(true);
  if (myTradeSymbol=="EURCHF" && TradeEURCHF) return(true);
  if (myTradeSymbol=="EURGBP" && TradeEURGBP) return(true);
  if (myTradeSymbol=="EURJPY" && TradeEURJPY) return(true);
  if (myTradeSymbol=="EURUSD" && TradeEURUSD) return(true);
  if (myTradeSymbol=="GBPCHF" && TradeGBPCHF) return(true);   
  if (myTradeSymbol=="GBPJPY" && TradeGBPJPY) return(true);
  if (myTradeSymbol=="GBPUSD" && TradeGBPUSD) return(true);
  if (myTradeSymbol=="NZDJPY" && TradeNZDJPY) return(true);
  if (myTradeSymbol=="NZDUSD" && TradeNZDUSD) return(true);
  if (myTradeSymbol=="USDCHF" && TradeUSDCHF) return(true);
  if (myTradeSymbol=="USDJPY" && TradeUSDJPY) return(true);
  if (myTradeSymbol=="USDCAD" && TradeUSDCAD) return(true);
  return(false);
}

int start() {

//Select Pair from Array
Pair = (Pair+1) % ArraySize(pairs);
TradeSymbol = pairs[Pair];

// This code is used to bypass any trade not in tradelist
if (CheckTradeList(TradeSymbol) == false) return(0);

//Identify ibfx mini tradesymbol
if(iClose(TradeSymbol,1440,0)==0) { TradeSymbol=StringSubstr(TradeSymbol,0,6);  }

//TradeSymbol MagicNumber Assignment
if (TradeSymbol=="AUDCADm" || TradeSymbol=="AUDCAD") {MagicNumber=200001;}
if (TradeSymbol=="AUDJPYm" || TradeSymbol=="AUDJPY") {MagicNumber=200002;}
if (TradeSymbol=="AUDNZDm" || TradeSymbol=="AUDNZD") {MagicNumber=200003;}
if (TradeSymbol=="AUDUSDm" || TradeSymbol=="AUDUSD") {MagicNumber=200004;}
if (TradeSymbol=="CHFJPYm" || TradeSymbol=="CHFJPY") {MagicNumber=200005;}
if (TradeSymbol=="EURAUDm" || TradeSymbol=="EURAUD") {MagicNumber=200006;}
if (TradeSymbol=="EURCADm" || TradeSymbol=="EURCAD") {MagicNumber=200007;}
if (TradeSymbol=="EURCHFm" || TradeSymbol=="EURCHF") {MagicNumber=200008;}
if (TradeSymbol=="EURGBPm" || TradeSymbol=="EURGBP") {MagicNumber=200009;}
if (TradeSymbol=="EURJPYm" || TradeSymbol=="EURJPY") {MagicNumber=200010;}
if (TradeSymbol=="EURUSDm" || TradeSymbol=="EURUSD") {MagicNumber=200011;}
if (TradeSymbol=="GBPCHFm" || TradeSymbol=="GBPCHF") {MagicNumber=200012;}   
if (TradeSymbol=="GBPJPYm" || TradeSymbol=="GBPJPY") {MagicNumber=200013;}
if (TradeSymbol=="GBPUSDm" || TradeSymbol=="GBPUSD") {MagicNumber=200014;}
if (TradeSymbol=="NZDJPYm" || TradeSymbol=="NZDJPY") {MagicNumber=200015;}
if (TradeSymbol=="NZDUSDm" || TradeSymbol=="NZDUSD") {MagicNumber=200016;}
if (TradeSymbol=="USDCHFm" || TradeSymbol=="USDCHF") {MagicNumber=200017;}
if (TradeSymbol=="USDJPYm" || TradeSymbol=="USDJPY") {MagicNumber=200018;}
if (TradeSymbol=="USDCADm" || TradeSymbol=="USDCAD") {MagicNumber=200019;}
if (MagicNumber==0) {MagicNumber = 200999;}  

//Assign Symbol Bid/Ask & Point values
double bid=MarketInfo(TradeSymbol,MODE_BID);
double ask=MarketInfo(TradeSymbol,MODE_ASK);
double point=MarketInfo(TradeSymbol,MODE_POINT);

//----- Money Management & Lot Sizing Stuff.
MM_AcctLeverage = AccountLeverage();
MM_MinLotSize = MarketInfo(TradeSymbol,MODE_MINLOT);
MM_MaxLotSize = MarketInfo(TradeSymbol,MODE_MAXLOT);
MM_LotStep = MarketInfo(TradeSymbol,MODE_LOTSTEP);
MM_CurrencyLotSize = MarketInfo(TradeSymbol,MODE_LOTSIZE);

if(MM_LotStep == 0.01) {MM_Decimals = 2;}
if(MM_LotStep == 0.1) {MM_Decimals = 1;}

if(UseMoneyMgmt == true)  {
   MM_OrderLotSize = AccountEquity() * (RiskPercent * 0.01) / (MM_CurrencyLotSize / MM_AcctLeverage);
   MM_OrderLotSize = StrToDouble(DoubleToStr(MM_OrderLotSize,MM_Decimals));   }
   else  {  MM_OrderLotSize = LotSize;   }

if(MM_OrderLotSize < MM_MinLotSize) {MM_OrderLotSize = MM_MinLotSize;}
if(MM_OrderLotSize > MM_MaxLotSize) {MM_OrderLotSize = MM_MaxLotSize;}
         
//indicator variable value assignments
SMA200_Day3 = iMA(TradeSymbol,1440,200,0,0,0,1);
RSI_Day_1 = iRSI(TradeSymbol,1440,2,0,3);
RSI_Day_2 = iRSI(TradeSymbol,1440,2,0,2);
RSI_Day_3 = iRSI(TradeSymbol,1440,2,0,1);

//Buy Setup  
if(RSI_Day_1 < 65 && RSI_Day_2 < RSI_Day_1 && RSI_Day_3 < RSI_Day_2 &&
   iClose(TradeSymbol,1440,1) > SMA200_Day3) {  Buy_Mode=true; }
   else  {  Buy_Mode=false;   }
//Sell Setup   
if(RSI_Day_1 > 35 && RSI_Day_2 > RSI_Day_1 && RSI_Day_3 > RSI_Day_2 &&
   iClose(TradeSymbol,1440,1) < SMA200_Day3) {  Sell_Mode=true;   }
   else  {  Sell_Mode=false;  } 
//Long Position Closing Conditions
if(OpenBuyOrders == 1 && iRSI(TradeSymbol,1440,2,0,1) > RSI_Overbought_Value)   {
   CloseLongs(MagicNumber,bid);
   OpenBuyOrders = 0;  }
//Short Position Closing Conditions   
if(OpenSellOrders == 1 && iRSI(TradeSymbol,1440,2,0,1) < RSI_Oversold_Value) {
   CloseShorts(MagicNumber,ask);
   OpenSellOrders = 0;   }

//----- Count number of existing open buy & sell orders; update trailing stops.
OpenBuyOrders=0;
OpenSellOrders=0; 

// Manage Paraolic SAR 
for(i=0;i<=OrdersTotal();i++) {
   OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
   if((OrderSymbol()==TradeSymbol) && (OrderMagicNumber()==MagicNumber))   {
      if(OrderType()==OP_BUY) {
         OpenBuyOrders++;
         if((iSAR(TradeSymbol,1440,0.02,0.2,1)>OrderStopLoss()) &&
            (bid>iSAR(TradeSymbol,1440,0.02,0.2,1)) &&
            (OrderOpenPrice()<iSAR(TradeSymbol,0,0.02,0.2,1)) &&
            (iSAR(TradeSymbol,0,0.02,0.2,1)>iSAR(TradeSymbol,0,0.02,0.2,2)))  {
            OrderModify(OrderTicket(),
                        OrderOpenPrice(),
                        iSAR(TradeSymbol,1440,0.02,0.2,1),
                        OrderTakeProfit(),0,Blue);
                        Print("Order # ",OrderTicket()," updated at ",Hour(),":",Minute(),":",Seconds());
                        return(0);  }  }
      if(OrderType()==OP_SELL)   {
         OpenSellOrders++;
         if((iSAR(TradeSymbol,1440,0.02,0.2,1)<OrderStopLoss()) &&
         (ask<iSAR(TradeSymbol,1440,0.02,0.2,1)) &&
         (OrderOpenPrice()>iSAR(TradeSymbol,0,0.02,0.2,1)) &&
         (iSAR(TradeSymbol,0,0.02,0.2,1)<iSAR(TradeSymbol,0,0.02,0.2,2)))  {
         OrderModify(OrderTicket(),
                     OrderOpenPrice(),
                     iSAR(TradeSymbol,1440,0.02,0.2,1),
                     OrderTakeProfit(),0,Blue);
                     Print("Order # ",OrderTicket()," updated at ",Hour(),":",Minute(),":",Seconds());
                     return(0);  }  }  }  }
//----- Generic order handler.
//----- If we have a new buy signal, close existing sell orders; if we have a new sell signal, 
//      close existing buy orders; reset order counters.
//----- Next, create new buy or sell order.
if(Buy_Mode==true && OpenBuyOrders==0)   {
   if(OpenSellOrders > 0)  {
      CloseShorts(MagicNumber,ask);
      OpenSellOrders = 0;  }
   if(OpenBuyOrders == 0)  {  
      ticket = OpenPendingOrder(OP_BUY,MM_OrderLotSize,ask,Slippage,bid,
                                StopLoss,TakeProfit,"RSI-R2 mp",MagicNumber,0,Lime);
      if(ticket<0)   {
         Print("OrderSend failed with error #",GetLastError());
         return(0);  }
      else  {
         OpenBuyOrders++; }  }  }
if(Sell_Mode==true && OpenSellOrders==0) {
   if(OpenBuyOrders > 0)   {
      CloseLongs(MagicNumber,bid);
      OpenBuyOrders = 0;   }  
   if(OpenSellOrders == 0) {
      ticket = OpenPendingOrder(OP_SELL,MM_OrderLotSize,bid,Slippage,ask,
                                StopLoss,TakeProfit,"RSI-R2 mp",MagicNumber,0,HotPink);
      if(ticket<0)   {
         Print("OrderSend failed with error #",GetLastError());
         return(0);  }
      else  {
         OpenSellOrders++;   }  }  }
//On Chart Comment function call (displays pair data) 
CommentAll(SMA200_Day3, RSI_Day_1, RSI_Day_2, RSI_Day_3);
return(0);  }//end of Start()

//----- Comments
void CommentAll(double SMA200_Day3, double RSI_Day_1, double RSI_Day_2, double RSI_Day_3) {
string Comments = "";
int i, next = (Pair+1) % ArraySize(pairs);
   
CommentsPairs[Pair] = StringConcatenate(TradeSymbol,": ","Last Close ",iClose(TradeSymbol,1440,1),
                      " 200SMA(",SMA200_Day3,") ","RSI(1) ",RSI_Day_1," RSI(2) ",RSI_Day_2," RSI(3) ",
                      RSI_Day_3," Monthly Tick Count: ",iVolume(TradeSymbol,43200,0));

CommentsPairs[next] = ">" + CommentsPairs[next];

for(i=0; i < ArraySize(CommentsPairs); i++)  Comments = StringConcatenate(Comments,"\n",CommentsPairs[i]);

if(!IsTesting())Comment(/*CommentHeader,*/"Last Tick: ",TimeToStr(CurTime(),TIME_DATE|TIME_SECONDS),"\n",
                        Comments);    }// end CommentAll()

//----- Order Processing Functions
void CloseLongs(int MagicNumber, double bid) {
 int trade;
 for(trade=OrdersTotal()-1;trade>=0;trade--) {
   if(OrderSelect(trade,SELECT_BY_POS,MODE_TRADES)==false)  continue;
   if(OrderSymbol()!=TradeSymbol||OrderMagicNumber()!=MagicNumber)   continue;
   if(OrderSymbol()==TradeSymbol&&OrderMagicNumber()==MagicNumber)   {
      if(OrderType()==OP_BUY) {
         OrderClose(OrderTicket(),OrderLots(),bid,Slippage,Blue); }  }  }  }//end CloseLongs

void CloseShorts(int MagicNumber, double ask)   {
 int trade;
 for(trade=OrdersTotal()-1;trade>=0;trade--) {
   if(OrderSelect(trade,SELECT_BY_POS,MODE_TRADES)==false)  continue;
   if(OrderSymbol()!=TradeSymbol||OrderMagicNumber()!=MagicNumber)   continue;
   if(OrderSymbol()==TradeSymbol&&OrderMagicNumber()==MagicNumber)   {
      if(OrderType()==OP_SELL)   {
         OrderClose(OrderTicket(),OrderLots(),ask,Slippage,Red);  }  }  }  }//end CloseShorts

int OpenPendingOrder(int pType,double pLots,double pLevel,int sp,double pr,int sl,int tp,string pComment,
                     int pMagic,datetime pExpiration,color pColor)   {
  double bid=MarketInfo(TradeSymbol,MODE_BID);
  double ask=MarketInfo(TradeSymbol,MODE_ASK);
  double point=MarketInfo(TradeSymbol,MODE_POINT);
  int ticket=0;
  int err=0;
  int c = 0;
  int NumberOfTries = 10;
  switch (pType)  {
   case OP_BUY:
      for(c = 0 ; c < NumberOfTries ; c++)   {  
         RefreshRates();
         ticket=OrderSend(TradeSymbol,OP_BUY,pLots,ask,sp,StopLong(bid,sl,point),TakeLong(bid,tp,point),
                          pComment,pMagic,pExpiration,pColor);
         if (ticket > 0) break;
         err=GetLastError();
         if(err==0)  {  break;   }
         else  {  if(err==4 || err==137 ||err==146 || err==136)   {     //Busy errors
                     Sleep(5000);
                     continue;   }
                  else  {     //normal error
                     Print("Error Code= ", err);
                     break;   }  }  } 
      break;
   case OP_SELL:
      for(c = 0 ; c < NumberOfTries ; c++)   {
         RefreshRates();
         ticket=OrderSend(TradeSymbol,OP_SELL,pLots,bid,sp,StopShort(ask,sl,point),TakeShort(ask,tp,point),
                          pComment,pMagic,pExpiration,pColor);
         if (ticket > 0) break;
         err=GetLastError();
         if(err==0)  {  break;   }
         else  {  if(err==4 || err==137 ||err==146 || err==136)   {     //Busy errors
                     Sleep(5000);
                     continue;   }
                  else  {     //normal error
                     Print("Error Code= ", err);
                     break;   }  }  } 
      break;   } 
return(ticket);   }//end OpenPendingOrder  

double StopLong(double price,int stop,double point)   {
   if(stop==0) return(0);
   else  return(price-(stop*point));   }//end StopLong

double StopShort(double price,int stop,double point)  {
   if(stop==0) return(0);
   else  return(price+(stop*point));   }//end StopShort

double TakeLong(double price,int take,double point)   {
   if(take==0) return(0);
   else  return(price+(take*point));   }//end TakeLong

double TakeShort(double price,int take,double point)  {
   if(take==0) return(0);
   else  return(price-(take*point));   }//end TakeShort

// *  *  *  *  *  *  *  *  END OF CODE *  *  *  *  *  *  *  *