//+------------------------------------------------------------------+
//|                                                      RSI_JPY.mq4 |
//|                             Copyright © 2009, zznbrm@hotmail.com |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, zznbrm@hotmail.com"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 White
#property indicator_color2 Red
#property indicator_level1 50
#property indicator_level2 70
#property indicator_level3 30
#property indicator_level4 90
#property indicator_level5 10
#property indicator_maximum 100
#property indicator_minimum 0

#define RSI_PRICE_CLOSE 1
#define RSI_PRICE_WEIGHTED 2

//---- input parameters
extern string estrDesc0 = "1=Close, 2=Weighted";
extern int eintRSIPrice = RSI_PRICE_WEIGHTED;
extern int eintRSIPeriod = 2;
extern int eintTF1 = PERIOD_M15;
extern int eintTF2 = PERIOD_H1;
extern int eintBarsBack = 100;
extern string estrDesc1 = "Enter date as yyyy.mm.dd hh:mm ";
extern string estrDate = "";
extern bool eblnAUD = true;
extern bool eblnCAD = true;
extern bool eblnCHF = true;
extern bool eblnEUR = true;
extern bool eblnGBP = true;
extern bool eblnNZD = true;
extern bool eblnUSD = true;

//---- indicator buffers
double gdblBuf1[];
double gdblBuf2[];

//---- global variables
string gstrShortName = "";
int    gintTF0 = 0;
int    gintTF1 = 0;
int    gintTF2 = 0;
bool   gblnRecompute = false;
bool   gblnLiveMode = true;
bool   gblnHistCompleted = false;
string gastrPair[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{    
   if ( UninitializeReason() > 0 )     
   {
      gblnRecompute = true;
      Print( "Recomputing all bars!!!!!" );
   }
   
   gintTF0 = Period();
   
   if ( eintTF1 == 0 )  gintTF1 = Period();
   else                 gintTF1 = eintTF1;
   
   if ( eintTF2 == 0 )  gintTF2 = Period();
   else                 gintTF2 = eintTF2;
   
   int inx = 0;
   int intCount = eblnAUD + eblnCAD + eblnCHF + eblnEUR + eblnGBP + eblnNZD + eblnUSD;
   ArrayResize( gastrPair, intCount );
   
   if ( eblnAUD )   { gastrPair[inx] = "AUDJPY";  inx++; }
   if ( eblnCAD )   { gastrPair[inx] = "CADJPY";  inx++; }
   if ( eblnCHF )   { gastrPair[inx] = "CHFJPY";  inx++; }
   if ( eblnEUR )   { gastrPair[inx] = "EURJPY";  inx++; }
   if ( eblnGBP )   { gastrPair[inx] = "GBPJPY";  inx++; }
   if ( eblnNZD )   { gastrPair[inx] = "NZDJPY";  inx++; }
   if ( eblnUSD )   { gastrPair[inx] = "USDJPY";  inx++; }
   
   if ( estrDate == "" )   gblnLiveMode = true;
   else                    gblnLiveMode = false;
           
   //---- name for DataWindow and indicator subwindow label
   gstrShortName = "RSI_JPY ( M" + gintTF1 + ", M" + gintTF2 + ", " + eintRSIPeriod + " )";
   IndicatorShortName( gstrShortName );
   
   SetIndexBuffer( 0, gdblBuf1 ); 
   SetIndexStyle( 0, DRAW_LINE );
   SetIndexLabel( 0, "JPY RSI (M" + gintTF1 + ", " + eintRSIPeriod + ")" );
   
   SetIndexBuffer( 1, gdblBuf2 ); 
   SetIndexStyle( 1, DRAW_LINE );
   SetIndexLabel( 1, "JPY RSI (M" + gintTF2 + ", " + eintRSIPeriod + ")" );
         
   IndicatorDigits( 5 );
 
   return( 0 );
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   return( 0 );
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{    
   if ( gblnLiveMode )     processLive();
   else
   {
      if ( !gblnHistCompleted )
      {
         processHistory();
         gblnHistCompleted = true;
      }
   }
       
   return( 0 );
}

//+------------------------------------------------------------------+
//| processLive                                                      |
//+------------------------------------------------------------------+
void processLive()
{
   int intCountedBars = IndicatorCounted();
   
   if ( gblnRecompute )
   {
      intCountedBars = 0;
      gblnRecompute = false;
   }
   
   if (intCountedBars < 0) return (-1);
   //if (intCountedBars > 0) intCountedBars--;
   //if (intCountedBars < 0) intCountedBars = 0;
   int intlimit = Bars - intCountedBars;
   
   if ( intlimit > eintBarsBack )   intlimit = eintBarsBack;
   
   for ( int jnx = intlimit; jnx >= 0; jnx-- )
   {
      //if ( gintTF0 == gintTF1 )   gdblBuf1[jnx] = getRSI( jnx );
      //else                        gdblBuf1[jnx] = getRSI_TF( gintTF1, jnx );
      gdblBuf1[jnx] = getRSI_TF( gintTF1, jnx );
      gdblBuf2[jnx] = getRSI_TF( gintTF2, jnx );
      //if ( gintTF0 == gintTF2 )   gdblBuf2[jnx] = getRSI( jnx );
      //else                        gdblBuf2[jnx] = getRSI_TF( gintTF2, jnx );  
   }
}

//+------------------------------------------------------------------+
//| processHistory                                                   |
//+------------------------------------------------------------------+
void processHistory()
{  
   datetime dtHistDate = StrToTime( estrDate );
   int intHistShift = iBarShift( Symbol(), Period(), dtHistDate, false );
   
   int intlimit = eintBarsBack + intHistShift;
   
   for ( int jnx = intlimit; jnx >= intHistShift; jnx-- )
   {
      //if ( gintTF0 == gintTF1 )   gdblBuf1[jnx] = getRSI( jnx );
      //else                        gdblBuf1[jnx] = getRSI_TF( gintTF1, jnx );
      
      //if ( gintTF0 == gintTF2 )   gdblBuf2[jnx] = getRSI( jnx );
      //else                        gdblBuf2[jnx] = getRSI_TF( gintTF2, jnx );  
      
      gdblBuf1[jnx] = getRSI_TF( gintTF1, jnx );
      gdblBuf2[jnx] = getRSI_TF( gintTF2, jnx );
   }
}

//+------------------------------------------------------------------+
//| getRSI                                                           |
//+------------------------------------------------------------------+
/*double getRSI( int intShift )
{
   int intPairShift;
   double dblTotal = 0.0;
   double dblCurr = 0.0;     
   datetime dtCurrTFTime = Time[intShift];
      
   for ( int inx = 0; inx < ArraySize( gastrPair ); inx++ )
   {
      intPairShift = iBarShift( gastrPair[inx], gintTF0, dtCurrTFTime, false );
      dblCurr = 100.0 - iRSI( gastrPair[inx], gintTF0, eintRSIPeriod, PRICE_WEIGHTED, intPairShift );
      dblTotal += dblCurr;         
   }
   
   double dblRSI = dblTotal / ArraySize( gastrPair );
     
   return( dblRSI );
}*/

//+------------------------------------------------------------------+
//| getRSI_TF                                                        |
//+------------------------------------------------------------------+
double getRSI_TF( int intRsiTF, int intShift )
{
   datetime dtCurrTFTime = Time[intShift];
   int intHighTFShift = iBarShift( Symbol(), intRsiTF, dtCurrTFTime, false );
   datetime dtHighTFTime = iTime( Symbol(), intRsiTF, intHighTFShift );
   int intStartShift = iBarShift( Symbol(), gintTF0, dtHighTFTime, false );
   int intCurrTFBarCount = intStartShift - intShift + 1;
   double dblCurr = 0.0;
   double dblTotal = 0.0;
   double dblRSI = 0.0;
   double adblPrice[100];

   ArraySetAsSeries( adblPrice, true );
      
   for ( int inx = 0; inx < ArraySize( gastrPair ); inx++ )
   {
      ArrayInitialize( adblPrice, 0.0 );
      dblCurr = 0.0;
      
      // Get the previous bar values
      for ( int jnx = 1; jnx < 100; jnx++ )
      {
         // Get the weighted price for the previous higher timeframe candle   
         adblPrice[jnx] = getWeightedPrice( gastrPair[inx], intRsiTF, dtHighTFTime, jnx );
      }
      
      // Get the weighted price for the current higher timeframe candle, but
      // only up to the close of the current chart candle
      adblPrice[0] = getWeightedPriceCurr( gastrPair[inx], dtCurrTFTime, intCurrTFBarCount );
 
      // Get the RSI value
      dblCurr = iRSIOnArray( adblPrice, 0, eintRSIPeriod, 0 );
      dblTotal += dblCurr;         
   }
  
   dblRSI = 100.0 - ( dblTotal / ArraySize( gastrPair ) );
     
   return( dblRSI ); 
}

//+------------------------------------------------------------------+
//| getWeightedPrice                                                 |
//+------------------------------------------------------------------+
double getWeightedPrice( string strPair, int intTF, datetime dtTime, int intShift )
{
   double dblPrice, dblHigh, dblLow;
   int intStart = iBarShift( strPair, intTF, dtTime, false );
   double dblClose = iClose( strPair, intTF, intStart+intShift );
   
   if ( eintRSIPrice == RSI_PRICE_WEIGHTED )
   {
      dblHigh = iHigh( strPair, intTF, intStart+intShift );
      dblLow = iLow( strPair, intTF, intStart+intShift );
   
      dblPrice = ( dblClose + dblClose + dblHigh + dblLow ) / 4;
   }
   else
   {
      dblPrice = dblClose;
   }
   
   return( dblPrice );
}

//+------------------------------------------------------------------+
//| getWeightedPriceCurr                                             |
//+------------------------------------------------------------------+
double getWeightedPriceCurr( string strPair, datetime dtTime, int intCount )
{
   int intHighShift, intLowShift;
   double dblPrice, dblHigh, dblLow;
   int intShift = iBarShift( strPair, gintTF0, dtTime, false );
   double dblClose = iClose( strPair, gintTF0, intShift );
   
   if ( eintRSIPrice == RSI_PRICE_WEIGHTED )
   {
      intHighShift = iHighest( strPair, gintTF0, MODE_HIGH, intCount, intShift );
      intLowShift = iLowest( strPair, gintTF0, MODE_LOW, intCount, intShift );
      
      dblHigh = iHigh( strPair, gintTF0, intHighShift );
      dblLow = iLow( strPair, gintTF0, intLowShift );
   
      dblPrice = ( dblClose + dblClose + dblHigh + dblLow ) / 4;
   }
   else
   {
      dblPrice = dblClose;
   }
   
   return( dblPrice );
}