//+------------------------------------------------------------------+
//|                                        Tradable Correlations.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, smjones"
#property link      "sjcoinc2000@yahoo.com"

#property indicator_chart_window

extern int     CorrelationPeriods = 50;
extern int     CorrelationTimeFrame = 1440;
extern double  PositiveAbove = 75;
extern double  NegativeBelow = -75;
extern bool    ShowOnlyCandS = false;
extern double  StochThreshold = 80;
extern int     StochTimeFrame = 5;
extern int     K = 100;
extern int     D = 1;
extern int     S = 1;
extern int     FontSize = 10;
extern bool    SortByColumns = true;
extern int     Columns = 3;
extern int     Rows = 22;
extern int     X_Spacing = 300;
extern int     Y_Spacing = 17;
extern color   PositiveColor = Aqua;
extern color   NegativeColor = Red;
extern color   TitleColor = Yellow;

//datetime cor_once = 0;
string m="",title,T;
string s[26],temp_p[676],temp_n[676],pc[676],nc[676];
double c[26][26];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
      m = StringSubstr(Symbol(),6,StringLen(Symbol())-6);
      
      s[0]="AUDCAD"+m;  s[1]="AUDCHF"+m;  s[2]="AUDJPY"+m;  s[3]="AUDNZD"+m;  s[4]="AUDUSD"+m;
      s[5]="CADJPY"+m;  s[6]="CHFJPY"+m;  s[7]="EURAUD"+m;  s[8]="EURCAD"+m;  s[9]="EURCHF"+m;
      s[10]="EURGBP"+m; s[11]="EURJPY"+m; s[12]="EURNZD"+m; s[13]="EURUSD"+m; s[14]="GBPAUD"+m; 
      s[15]="GBPCAD"+m; s[16]="GBPCHF"+m; s[17]="GBPJPY"+m; s[18]="GBPNZD"+m; s[19]="GBPUSD"+m;
      s[20]="NZDCHF"+m; s[21]="NZDJPY"+m; s[22]="NZDUSD"+m; s[23]="USDCAD"+m; s[24]="USDCHF"+m;
      s[25]="USDJPY"+m;
      
      if ( CorrelationTimeFrame == 1 ) T = "M1";
      if ( CorrelationTimeFrame == 5 ) T = "M5";
      if ( CorrelationTimeFrame == 15 ) T = "M15";
      if ( CorrelationTimeFrame == 30 ) T = "M30";
      if ( CorrelationTimeFrame == 60 ) T = "H1";
      if ( CorrelationTimeFrame == 240 ) T = "H4";
      if ( CorrelationTimeFrame == 1440 ) T = "D1";
      if ( CorrelationTimeFrame == 10080 ) T = "W1";
      if ( CorrelationTimeFrame == 43200 ) T = "MN"; 
      
       
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
      Comment("");
      DeleteObject("Corr");
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
 
      string name_pos,name_neg,tempstrp,tempstrn;
      double tempvalue,tempstoch;
      int cnt = ArraySize(temp_p),pos=0,neg=0;
      for(int ii=0;ii<cnt;ii++)
         {
            temp_p[ii] = "";
            temp_n[ii] = "";
            pc[ii] = "";
            nc[ii] = "";
         }
      
   //if( cor_once != iTime(Symbol(),CorrelationTimeFrame,0) )
      //{         
       //cor_once = iTime(Symbol(),CorrelationTimeFrame,0);
       int count = ArraySize(s);
       for(int i=0;i<count;i++)
         {
            for(int n=0;n<count;n++)
               {
                  tempvalue = 100*cp(s[i],s[n],CorrelationTimeFrame,CorrelationPeriods);
                  if ( tempvalue < -100 ) 
                     tempvalue = 0;  //Currency pair not in list from broker 
                  tempstoch = stochdiff(s[i],s[n], StochTimeFrame, K, D, S); 
                  
                  c[i][n]= tempvalue;
                  if ( ShowOnlyCandS )
                     {
                        if ( MathAbs(tempstoch) < StochThreshold )
                        c[i][n]=0; 
                     }                  
                  if( c[i][n] >= PositiveAbove && c[i][n] < 100 )
                     {
                        temp_p[pos]= StringSubstr(s[i],0,6)+" | "+StringSubstr(s[n],0,6)+"   Cor: "+DoubleToStr(c[i][n],1)+"%"
                        +"   StoDiff:  "+DoubleToStr(tempstoch,0);
                        pos++;
                     }
                  if( c[i][n] <= NegativeBelow )
                     {
                        temp_n[neg]= StringSubstr(s[i],0,6)+" | "+StringSubstr(s[n],0,6)+"   Cor: "+DoubleToStr(c[i][n],1)+"%"
                        +"   StoDiff:  "+DoubleToStr(tempstoch,0);
                        neg++;
                     }       
               }// end for n  
                         
         }//end for i
   
       int pc_cnt=0;
       for(i=0;i<pos;i++)
         {
            tempstrp = StringSubstr(temp_p[i],9,6)+" | "+StringSubstr(temp_p[i],0,6);
            for(int b=0;b<pos;b++)
               {
                 if ( StringSubstr(temp_p[b],0,15) == tempstrp )
                  {
                     temp_p[b] = "";
                  }  
               }
            if ( temp_p[i] != "" )
               {
                  pc[pc_cnt] = temp_p[i];
                  pc_cnt++;
               }                         
         }
          
       int nc_cnt = 0;
       for(i=0;i<neg;i++)
         {
            tempstrn = StringSubstr(temp_n[i],9,6)+" | "+StringSubstr(temp_n[i],0,6);
            for(b=0;b<neg;b++)
               {
                 if ( StringSubstr(temp_n[b],0,15) == tempstrn )
                  {
                     temp_n[b] = "";
                  }  
               }
            if ( temp_n[i] != "" )
               {
                  nc[nc_cnt] = temp_n[i];
                  nc_cnt++;
               }                         
         }
       
       
         
       DeleteObject("Corr");        
       int  xspace=X_Spacing,yspace=Y_Spacing,xx=0,yy=0;  
       for( i=0;i<pc_cnt;i++ )
         {
            ObjectCreate("CorrPos"+DoubleToStr(i,0),OBJ_LABEL,0,0,0);
            ObjectSet("CorrPos"+DoubleToStr(i,0),OBJPROP_XDISTANCE,xx*xspace);
            ObjectSet("CorrPos"+DoubleToStr(i,0),OBJPROP_YDISTANCE,yy*yspace);
            ObjectSetText("CorrPos"+DoubleToStr(i,0), pc[i], FontSize, "Arial", PositiveColor);
            if ( SortByColumns )
               {
                  yy++;
                  if ( yy==Rows)
                     {
                        yy = 0;
                        xx++;
                     }  
               }
            else
               {   
                  xx++;
                  if ( xx==Columns ) 
                     {
                        xx = 0;
                        yy++;
                     }
               }               
         } // end for i
        
       if (SortByColumns )
         {
            yy=0;xx++; 
         }
       else
         {   
            xx=0;yy++;yy++;
         }     
       for( i=0;i<nc_cnt;i++ )
         {
            ObjectCreate("CorrNeg"+DoubleToStr(i,0),OBJ_LABEL,0,0,0);
            ObjectSet("CorrNeg"+DoubleToStr(i,0),OBJPROP_XDISTANCE,xx*xspace);
            ObjectSet("CorrNeg"+DoubleToStr(i,0),OBJPROP_YDISTANCE,yy*yspace);
            ObjectSetText("CorrNeg"+DoubleToStr(i,0), nc[i], FontSize, "Arial", NegativeColor);
            if ( SortByColumns )
               {
                  yy++;
                  if ( yy==Rows) 
                     {
                        yy = 0;
                        xx++;
                     }
               }
            else
               {
                  xx++;
                  if ( xx==Columns ) 
                     {
                        xx = 0;
                        yy++;
                     }
               }               
         } // end for i
         
       title = "Correlation Table "+T+"@ "+DoubleToStr(CorrelationPeriods,0)+" Periods > "+DoubleToStr(PositiveAbove,1)+"% And < "+DoubleToStr(NegativeBelow,1)+"%"; 
       ObjectCreate("CorrTitle",OBJ_LABEL,0,0,0);
       ObjectSet("CorrTitle",OBJPROP_XDISTANCE,225);
       ObjectSet("CorrTitle",OBJPROP_YDISTANCE,375);
       ObjectSetText("corrTitle",title,16,"Arial",TitleColor);  
        
      //}//end if cor_once
                         

      return(0);
  }
//+------------------------------------------------------------------+
//******************************************************************************
double   cp(string Symbol1,string Symbol2,int TimeFrame, int periods)
{
	//Comment( Symbol1,"  ",Symbol2,"  ",TimeFrame,"  ",periods);
	datetime closeTime1	= iTime(Symbol1,TimeFrame,0),
				closeTime2	= iTime(Symbol2,TimeFrame,0),
				closeTime	= MathMin(closeTime1,closeTime2);
	int		shift1		= iBarShift(Symbol1,TimeFrame,closeTime),
				shift2		= iBarShift(Symbol2,TimeFrame,closeTime);
	double	Co,
	         close1[],
				close2[];

	ArrayCopySeries(close1,MODE_CLOSE,Symbol1,TimeFrame);
	ArrayCopySeries(close2,MODE_CLOSE,Symbol2,TimeFrame);

	int bars = MathMin(ArraySize(close1)-shift1,ArraySize(close2)-shift2);
	if ( periods > 0 )
	     bars = periods;
   Co = Correlation(close1,close2,shift1,shift2,bars);
   
   return(Co);
}



//+------------------------------------------------------------------+
//| Correlation Coefficient R														|
//+------------------------------------------------------------------+
double Correlation(double x[], double y[], int x_shift = 0, int y_shift = 0, int count = -1)
{
	int n = MathMin(ArraySize(x)-x_shift,ArraySize(y)-y_shift);
	if(n>count && count>0)
		n=count;
	if(n<2)
		return(-2);

	double	sum_sq_x,
				sum_sq_y,
				sum_coproduct,
				mean_x = x[x_shift],
				mean_y = y[y_shift];

	for(int i = 0; i < n; i++)
	{
		double	sweep = i / (i+1.0),
					delta_x = x[i+x_shift] - mean_x,
					delta_y = y[i+y_shift] - mean_y;

		sum_sq_x += delta_x*delta_x * sweep;
		sum_sq_y += delta_y*delta_y * sweep;
    	sum_coproduct += delta_x*delta_y * sweep;
    	mean_x += delta_x / (i+1.0);
    	mean_y += delta_y / (i+1.0);
	}

	double	pop_sd_x = MathSqrt(sum_sq_x/n),
				pop_sd_y = MathSqrt(sum_sq_y/n),
				cov_x_y = sum_coproduct / n;

	if(pop_sd_x*pop_sd_y != 0.0)
		return(cov_x_y / (pop_sd_x*pop_sd_y));

	return(-3);
}

//*******************************************************************************
void DeleteObject(string char4)
   {
      string name;      
      int obj = ObjectsTotal();
      for ( int n=obj;n >= 0 ;n--)
         {
            name = ObjectName(n);
            char4 = StringSubstr(name,0,4);
            if ( char4 == "Corr" )
               ObjectDelete(name);   
         }
      return;
   }           

//********************************************************************************
double stochdiff(string symbol1,string symbol2, int timeframe, int k, int d, int s)
   {
      double diff,sto1,sto2;
      sto1 = iStochastic(symbol1,timeframe,k,d,s,0,0,0,0);
      sto2 = iStochastic(symbol2,timeframe,k,d,s,0,0,0,0);
      diff = sto1-sto2; 
      
      return(diff);
   }         