//+------------------------------------------------------------------+
//|                           RSI EA.mq4                             |
//|                 Copyright © 2015, David Currey                   |
//+------------------------------------------------------------------+
extern int MAGICMA = 4562000;
extern string Hlp0 = "TradingMode: Autotrading=0, Advisory Only=1, Discretionary Trading=2";
extern int TradingMode = 0;
extern string Hlp1 = "Leave FixedLotSize=0 for LotSize based on Equity";
extern double FixedLotSize = 0;
extern double MaximumRiskPercentage = 2;
extern int StopLoss = 20;
extern string Hlp2 = "Increase in Wager after losses, example 1.5 = 50% increase";
extern double StopLossMultiple = 1.0;
extern string Hlp3 = " 0 = Fixed StopLoss, 1 = Trailing Stop Loss";
extern int TrailingStopLoss = 1;
extern string Hlp4 = "SetStopLossToBreakEvenPips: example 30 = protect loss at 30 pip gain";
extern int SetStopLossToBreakEvenPips = 0;
extern int TakeProfit = 50;
extern string Hlp5 = "RSI Periods";
extern int RSIPeriods = 14;
extern string Hlp6 = "RSI High Level Cross Down";
extern int TopLevel = 70;
extern string Hlp7 = "RSI Low Level Cross Up";
extern int BottomLevel = 30;
extern string Hlp8 = "USD=0, EUR=1, AUD=2, GBP=3, CHF=4, CAD=5, NZD=6";
extern int BaseCurrency = 1;
extern string Hlp9 = "Base Currency/First of Pair exchange rate for testing";
extern double RelatedRate = 1;
double WagerValue;
double PrevWagerValue;
double WagerLots;
double NormalWager;
double StopLossPrice;
double SwingStopLossPrice;
double PrevStopLossPrice;
double PrevEquity;
double TakeWinPrice;
int SwingStopLoss;
double CurrProfitTarget;
double PointValue;
double BaseRate;
double PrevOpen;
int limitbuys;
int buys;
int sells;
int res;
int Spread;
int i;
int Modified;
int BreakEvenCompleted;
string BaseCurrencyString;
string RelatedCurrencyString1;
string RelatedCurrencyString2;
string Message;
string Message2;
bool NewBar;
//+------------------------------------------------------------------+
//| Start function                                                   |
//+------------------------------------------------------------------+
void start()
    {
    CalculateCurrentOrders();
    if (limitbuys == 0)
       {
       CheckNewBar();
       if (buys != 0 || sells != 0)
          { 
          CheckForModify();
          CheckForClose();
          }
       if (NewBar == true && buys == 0 && sells == 0) CheckForOpen();
       }
    }
//+------------------------------------------------------------------+
//| Check for new bar                                  |
//+------------------------------------------------------------------+
void CheckNewBar()                              
  {                                             
   static datetime NewTime=0;                  
   NewBar=false;                               
   if(NewTime!=Time[0])                        
     {
      NewTime=Time[0];                         
      NewBar=true;                                
     }
  }
//+------------------------------------------------------------------+
//| Check for open order conditions                                  |
//+------------------------------------------------------------------+
void CheckForOpen()
    {
    if (iRSI(NULL,0,RSIPeriods,PRICE_CLOSE,1) > BottomLevel && iRSI(NULL,0,RSIPeriods,PRICE_CLOSE,2) <= BottomLevel)
       {
       if (TradingMode != 0)
          {
          PlaySound("alert.wav");
          Message2 = StringConcatenate("RSI Cross ALERT - BUY ",Symbol()," - ",Period(),"min at ",TimeToString(TimeCurrent(),TIME_MINUTES));
          res = MessageBox(Message,Message2,MB_OKCANCEL);
          if (TradingMode == 1) return;
          if (TradingMode == 2 && res != 2) return;
          }
       if (IsTesting()) ObjectsDeleteAll();
       WagerLots = LotsOptimized();
       res=OrderSend(Symbol(),OP_BUY,WagerLots,Ask,0,0,0,"RSI Cross",MAGICMA,0,Green);
       if (res > -1) Modified = 0;
       PrevEquity = AccountEquity();
       return;
       }
    if (iRSI(NULL,0,RSIPeriods,PRICE_CLOSE,1) < TopLevel && iRSI(NULL,0,RSIPeriods,PRICE_CLOSE,2) >= TopLevel)
       {
       if (TradingMode != 0)
          {
          PlaySound("alert.wav");
          Message2 = StringConcatenate("RSI Cross ALERT - SELL ",Symbol()," - ",Period(),"min at ",TimeToString(TimeCurrent(),TIME_MINUTES));
          res = MessageBox(Message,Message2,MB_OKCANCEL);
          if (TradingMode == 1) return;
          if (TradingMode == 2 && res != 2) return;
          }
       if (IsTesting()) ObjectsDeleteAll();
       WagerLots = LotsOptimized();
       res=OrderSend(Symbol(),OP_SELL,WagerLots,Bid,0,0,0,"RSI Cross",MAGICMA,0,Green);
       if (res > -1) Modified = 0;
       PrevEquity = AccountEquity();
       return;
       }
    }
//+------------------------------------------------------------------+
//| Check for modify order conditions                                |
//+------------------------------------------------------------------+
void CheckForModify()
  {
  for (i=0;i<OrdersTotal();i++)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if (OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
         {
         if (OrderStopLoss() == 0)
            {
            if (OrderType()==OP_BUY) 
               {
               StopLossPrice = Bid - (StopLoss * PointValue);
               if (TakeProfit > 1000) TakeProfit = 1000;
               if (TakeProfit != 0) TakeWinPrice = Ask + (TakeProfit * PointValue); 
               res = OrderModify(OrderTicket(),OrderOpenPrice(),StopLossPrice, TakeWinPrice, 0,clrMaroon);
               if (res > -1) 
                  {
                  CurrProfitTarget = WagerLots * Close[0] / PointValue / 10000 * 50;
                  PrevStopLossPrice = StopLossPrice;
                  BreakEvenCompleted = 0;
                  Modified = 1;
                  return;
                  }
               }
            if (OrderType()==OP_SELL) 
               {
               StopLossPrice = Ask + (StopLoss * PointValue);
               if (TakeProfit > 1000) TakeProfit = 1000;
               if (TakeProfit != 0) TakeWinPrice = Bid - (TakeProfit * PointValue);   
               res = OrderModify(OrderTicket(),OrderOpenPrice(),StopLossPrice, TakeWinPrice, 0,clrMaroon);
               if (res > -1) 
                  {
                  CurrProfitTarget = WagerLots * Close[0]  / PointValue / 10000 * 50;
                  PrevStopLossPrice = StopLossPrice;
                  BreakEvenCompleted = 0;
                  Modified = 1;
                  return;
                  }
               }
            else Modified = 1;
            }

         if (Modified == 1)
            {
            Spread = Ask - Bid;
            if (OrderType()==OP_BUY && SetStopLossToBreakEvenPips != 0 
            && Close[0] - OrderOpenPrice() - Spread >= SetStopLossToBreakEvenPips * PointValue
            && BreakEvenCompleted == 0)
               {
               StopLossPrice = OrderOpenPrice() + Spread + PointValue;
               res = OrderModify(OrderTicket(),OrderOpenPrice(),StopLossPrice, TakeWinPrice, 0, clrMaroon);
               if (res > -1) 
                  {
                  CurrProfitTarget = OrderProfit() + (WagerLots * Close[0] / PointValue / 10000 * 50);
                  BreakEvenCompleted = 1;
                  PrevStopLossPrice = StopLossPrice;
                  }
               }
            if (OrderType()==OP_SELL && SetStopLossToBreakEvenPips != 0 
            && OrderOpenPrice() - Close[0] - Spread >= SetStopLossToBreakEvenPips * PointValue
            && BreakEvenCompleted == 0)
               {
               StopLossPrice = OrderOpenPrice() - Spread - PointValue;
               res = OrderModify(OrderTicket(),OrderOpenPrice(),StopLossPrice, TakeWinPrice, 0, clrMaroon);
               if (res > -1) 
                  {
                  CurrProfitTarget = OrderProfit() + (WagerLots * Close[0] / PointValue / 10000 * 50);
                  BreakEvenCompleted = 1;
                  PrevStopLossPrice = StopLossPrice;
                  }
               }
            }   
         if (Modified == 1 && TrailingStopLoss==1)
            {
            if (OrderProfit() > CurrProfitTarget && ((OrderType()==OP_BUY)|| (OrderType()==OP_SELL))) 
               {
               if (OrderType()==OP_BUY) 
                  {
                  StopLossPrice = Bid - (StopLoss * PointValue);
                  if (StopLossPrice > PrevStopLossPrice) 
                  res = OrderModify(OrderTicket(),OrderOpenPrice(),StopLossPrice, TakeWinPrice, 0, clrMaroon);
                  PrevStopLossPrice = StopLossPrice;
                  }
               if (OrderType()==OP_SELL)
                  {
                  StopLossPrice = Ask + (StopLoss * PointValue);
                  if (StopLossPrice < PrevStopLossPrice) 
                  res = OrderModify(OrderTicket(),OrderOpenPrice(),StopLossPrice, TakeWinPrice, 0, clrMaroon);
                  PrevStopLossPrice = StopLossPrice;
                  }
               if (res > -1) CurrProfitTarget = OrderProfit() + (WagerLots * Close[0] / PointValue / 10000 * 50);
               } 
            }
         }
      }
   }   
//+------------------------------------------------------------------+
//| Close Positions                                                  |
//+------------------------------------------------------------------+
void CheckForClose()
    {
       for(i=0;i<OrdersTotal();i++)
       {
       if (OrderType()==OP_BUY && OrderMagicNumber()==MAGICMA
       && iRSI(NULL,0,RSIPeriods,PRICE_CLOSE,1) < TopLevel && iRSI(NULL,0,RSIPeriods,PRICE_CLOSE,2) >= TopLevel)
          {
          res = OrderClose(OrderTicket(),OrderLots(),Bid,1,clrMaroon);
          if (res > -1) return;
          }
       if (OrderType()==OP_SELL && OrderMagicNumber()==MAGICMA 
       && iRSI(NULL,0,RSIPeriods,PRICE_CLOSE,1) > BottomLevel && iRSI(NULL,0,RSIPeriods,PRICE_CLOSE,2) <= BottomLevel)
          {
          res = OrderClose(OrderTicket(),OrderLots(),Ask,1,clrMaroon);
          if (res > -1) return;
          }
       }
    }
//+------------------------------------------------------------------+
//| Calculate optimal lot size                                       |
//+------------------------------------------------------------------+
double LotsOptimized()
    {
    PointValue = .0001;
    if(Symbol() == "AUS200") PointValue = 1;
    if(Symbol() == "SPX200") PointValue = .1;
    if(StringFind(Symbol(),"JPY") > 0) PointValue = .01;
    if(StringFind(Symbol(),"XAU") > 0) PointValue = .1;
    if(StringFind(Symbol(),"GOLD") > 0) PointValue = .1;
    if(StringFind(Symbol(),"XAG") > 0) PointValue = .01;
    if(StringFind(Symbol(),"SILVER") > 0) PointValue = .01;
    WagerValue=AccountEquity()*MaximumRiskPercentage/100;
    if(AccountEquity() < PrevEquity && StopLossMultiple > 1) 
      {
      WagerValue = PrevWagerValue * StopLossMultiple;
      if (WagerValue > AccountEquity() * .2) WagerValue=NormalizeDouble(AccountEquity()*MaximumRiskPercentage/100,2); 
      }
    if(BaseCurrency == 0) BaseCurrencyString = "USD";
    if(BaseCurrency == 1) BaseCurrencyString = "EUR";
    if(BaseCurrency == 2) BaseCurrencyString = "AUD";
    if(BaseCurrency == 3) BaseCurrencyString = "GBP";
    if(BaseCurrency == 4) BaseCurrencyString = "CHF";
    if(BaseCurrency == 5) BaseCurrencyString = "NZD";
    if(BaseCurrency == 6) BaseCurrencyString = "CAD";
    RelatedCurrencyString1 = "";
    RelatedCurrencyString2 = "";
    if (StringFind(Symbol(),BaseCurrencyString) == -1) 
      {
      RelatedCurrencyString1 = StringConcatenate(StringSubstr(Symbol(),0,3),BaseCurrencyString);
      RelatedCurrencyString2 = StringConcatenate(BaseCurrencyString,StringSubstr(Symbol(),0,3));
      }
    if(Symbol() == "XAUUSD" || Symbol() == "XAGUSD" || Symbol() == "GOLD" || Symbol() == "SILVER")  
      {
      RelatedCurrencyString1 = StringConcatenate("USD",BaseCurrencyString);
      RelatedCurrencyString2 = StringConcatenate(BaseCurrencyString,"USD");
      }
    BaseRate = 1;
    if (StringFind(Symbol(),BaseCurrencyString) == 0) BaseRate = Close[1];
    if (StringFind(Symbol(),BaseCurrencyString) == 3) BaseRate = 1/Close[1];
    if (RelatedCurrencyString1 != "" && iClose(RelatedCurrencyString1,PERIOD_M1,0)!= 0) 
    RelatedRate = iClose(RelatedCurrencyString1,PERIOD_M1,0);
    if (RelatedCurrencyString2 != "" && iClose(RelatedCurrencyString2,PERIOD_M1,0)!= 0) 
    RelatedRate = 1/iClose(RelatedCurrencyString2,PERIOD_M1,0);
    WagerLots = NormalizeDouble(WagerValue * BaseRate * RelatedRate / StopLoss / AccountLeverage() * 10,2);
    if(FixedLotSize != 0) WagerLots = FixedLotSize;
    PrevWagerValue = WagerValue;
    return(WagerLots);
    }
//+------------------------------------------------------------------+
//| Calculate open positions                                         |
//+------------------------------------------------------------------+
void CalculateCurrentOrders()
    {
    buys = 0;
    sells = 0;
    for(i=0;i<OrdersTotal();i++)
       {
       if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
       if (OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
          {
          if(OrderType()==OP_BUY) buys++;
          if(OrderType()==OP_SELL) sells++;
          }
       }
     limitbuys = 0;
     for(i=0;i<OrdersTotal();i++)
       {
       if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
       if (OrderMagicNumber()==99999)
          {
          if(OrderType()==OP_BUYLIMIT) limitbuys++;
          }
       }
   }
//+------------------------------------------------------------------+