//+------------------------------------------------------------------+
#define strEAname "RSI dipbuyer MA V1.1"
#define nSystemID    101
//|                                               Paul Hampton-Smith |
//+------------------------------------------------------------------+

// This is a simplified version of the RSI-R2 EA written by Bluto. Many thanks to 
// him for sharing his ideas
//
// It trades all FXDD offerings on one EA. The only function provided by the chart on which it 
// is running is to supply tick events.

#include <Stdlib.mqh>

extern double dblLots = 0.1;
extern int nRSIperiod = 2;
extern int nTrendPeriod = 200;
extern int nRSIlongEntry = 65; // below this to enter long. 100 minus this value for short
extern int nRSIlongExit = 75; // above this to exit long. 100 minus this value for short
extern int nStochLongEntry = 20; // above this to exit long. 100 minus this value for short

extern int nStopLoss = 500;
extern int nTakeProfit = 0;

string strSymbol = "";
int nDigits = 0;
double dblBid = 0.0;
double dblAsk = 0.0;
double dblPoint = 0.0;

// FXDD offerings
string strSymbols[] = { "USDJPY","EURUSD","GBPUSD","USDCHF","USDCAD","AUDUSD",
          "EURGBP","EURJPY","GBPJPY","EURCHF",/*"USDMXN",*/"CHFJPY","GBPCHF",
          "EURAUD","EURCAD","AUDCAD","AUDJPY","NZDUSD","AUDNZD","CADJPY" };
string   strComments[];

int init()
{
	ArrayCopy(strComments,strSymbols);
	if (IsTesting())
	{
		// can't use strategy tester on anything other than chart Symbol()
		strSymbol = Symbol();
		ArrayResize(strComments,1);
	}
}


int start()
{
	LoadSymbol();
	LoadMarketInfo();
	
	double dblMA = iMA(strSymbol,PERIOD_D1,nTrendPeriod,0,MODE_SMA,PRICE_CLOSE,1);
	double RSI1 = iRSI(strSymbol,PERIOD_D1, nRSIperiod,PRICE_CLOSE,1);
	double RSI2 = iRSI(strSymbol,PERIOD_D1, nRSIperiod,PRICE_CLOSE,2);
	double RSI3 = iRSI(strSymbol,PERIOD_D1, nRSIperiod,PRICE_CLOSE,3);

	CheckExit(RSI1);
	CheckEntry(dblMA, RSI1, RSI2, RSI3);
	CommentAll(dblMA, RSI1, RSI2, RSI3);

   return(0);  
}
      

int OpenOrders()
{
   int nCount = 0;
   for ( int nPosition=0 ; nPosition<OrdersTotal() ; nPosition++ )
   {
      OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES);
      if ( OrderSymbol()==strSymbol &&
         ( OrderType() == OP_BUY || OrderType() == OP_SELL ) &&
         OrderMagicNumber() == nSystemID )
      {
         nCount++;
      }
   }
   return(nCount);
}


void CheckExit(double RSI1)
{
   for ( int nPosition=0 ; nPosition<OrdersTotal() ; nPosition++ )
   {
      OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES);
      if( OrderSymbol()==strSymbol && OrderMagicNumber()==nSystemID)
      {
      	switch (OrderType())
      	{
      	case OP_BUY:
//	         if ( iClose(strSymbol,PERIOD_D1,1)-OrderOpenPrice() > 0 || RSI1 > nRSIlongExit )
	         if ( RSI1 > nRSIlongExit )
            {
           		OrderClose(OrderTicket(),OrderLots(),dblBid,3,Violet);
            }
            break;
      	case OP_SELL:
//           	if ( OrderOpenPrice() - iClose(strSymbol,PERIOD_D1,1) > 0 || RSI1 < 100-nRSIlongExit )
         	if ( RSI1 < 100-nRSIlongExit )
           	{
					OrderClose(OrderTicket(),OrderLots(),dblAsk,3,Violet);
            }
           	break;
         }
      }
   }
}


void CheckEntry(double dblMA, double RSI1, double RSI2, double RSI3)
{
	double dblClose = iClose(strSymbol,PERIOD_D1,1);
	if ( dblClose > dblMA && 
		RSI3 < nRSIlongEntry && 
		RSI2 < RSI3 && 
		RSI1 < RSI2 &&
		iStochastic(strSymbol,PERIOD_D1,2,2,1,MODE_SMA,PRICE_CLOSE,MODE_MAIN,1) < nStochLongEntry)
	{
		if (OpenOrders() == 0) 
		{
			MyOrderSend(OP_BUY);
		}
	}

	if ( dblClose < dblMA &&
		RSI3 > 100-nRSIlongEntry && 
		RSI2 > RSI3 && 
		RSI1 > RSI2 &&
		iStochastic(strSymbol,PERIOD_D1,2,2,1,MODE_SMA,PRICE_CLOSE,MODE_MAIN,1) > 100-nStochLongEntry)
	{
   	if (OpenOrders() == 0) 
   	{
   		MyOrderSend(OP_SELL);
		}
   }
}

int MyOrderSend(int cmd)
{
	// uses global strSymbol
	
	// defaults
	int nSlippage = 3;
	color clrBuy = Green;
	color clrSell = Red;

	double dblStopLoss = 0.0, dblTakeProfit = 0.0;
	int nTicket;

	switch(cmd)
	{
		case OP_BUY:
			if (nStopLoss > 0) dblStopLoss = NormalizeDouble(dblAsk-nStopLoss*dblPoint,nDigits);
			if (nTakeProfit > 0) dblTakeProfit = NormalizeDouble(dblBid+nTakeProfit*dblPoint,nDigits);
			nTicket = OrderSend(strSymbol,OP_BUY,dblLots,dblAsk,nSlippage,dblStopLoss,dblTakeProfit,strEAname,nSystemID,0,clrBuy);
			Print(ErrorDescription(GetLastError())); 
			return(nTicket);
	
		case OP_SELL:
			if (nStopLoss > 0) dblStopLoss = NormalizeDouble(dblBid+nStopLoss*dblPoint,nDigits);
			if (nTakeProfit > 0) dblTakeProfit = NormalizeDouble(dblAsk-nTakeProfit*dblPoint,nDigits);
			nTicket = OrderSend(strSymbol,OP_SELL,dblLots,dblBid,nSlippage,dblStopLoss,dblTakeProfit,strEAname,nSystemID,0,clrSell);
			Print(ErrorDescription(GetLastError())); 
			return(nTicket);
	
		default:
			Print("MyOrderSend(): invalid cmd");
	}			
}

void LoadSymbol()
{
	if (IsTesting()) return;

	static int nSymbol = 0;

	// with each tick, cycle through each pair 
	strSymbol = strSymbols[nSymbol];
	if (nSymbol < ArraySize(strSymbols)-1)
	{
		nSymbol++;
	}
	else
	{
		nSymbol = 0;
	}
}

void LoadMarketInfo()
{
	nDigits = MathRound(MarketInfo(strSymbol,MODE_DIGITS));		
	dblBid = NormalizeDouble(MarketInfo(strSymbol,MODE_BID),nDigits);		
	dblAsk = NormalizeDouble(MarketInfo(strSymbol,MODE_ASK),nDigits);		
	dblPoint = NormalizeDouble(MarketInfo(strSymbol,MODE_POINT),nDigits);		
}

void CommentAll(double dblLinRegSlope, double RSI1, double RSI2, double RSI3) 
{
	string strWholeComment = "";
	for (int i = 0 ; i < ArraySize(strSymbols) ; i++)
	{
		if (strSymbol == strSymbols[i])
		{	
			strComments[i] = StringConcatenate(strSymbol,": ","Last Close ",iClose(strSymbol,PERIOD_D1,1)," MA(",nTrendPeriod,") ", dblLinRegSlope,
						" RSI(",nRSIperiod,",3) ",NormalizeDouble(RSI3,1), 
						" RSI(",nRSIperiod,",2) ",NormalizeDouble(RSI2,1), 
						" RSI(",nRSIperiod,",1) ",NormalizeDouble(RSI1,1));
			strWholeComment = StringConcatenate(strWholeComment,strComments[i],"    <<<\n"); 
		}
		else
		{
			strWholeComment = StringConcatenate(strWholeComment,strComments[i],"\n"); 
		}
	}
	Comment(strWholeComment);
}


