//+------------------------------------------------------------------+
//|                                     smCorrelation MultiPairs.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010.04.16, SwingMan"
#property link      ""

#property indicator_chart_window

//---- extern inputs
//+------------------------------------------------------------------+
extern string PairList1 = "AUDCAD,AUDCHF,AUDJPY,AUDUSD,CADCHF,CADJPY,CHFJPY";
extern string PairList2 = "EURAUD,EURCAD,EURGBP,EURJPY,EURUSD";
extern string PairList3 = "GBPAUD,GBPCHF,GBPJPY,GBPUSD,NZDJPY,NZDUSD,USDCAD,USDCHF,USDJPY";
/*
extern string PairList1 = "AUDJPY,AUDUSD,CADJPY,CHFJPY";
extern string PairList2 = "EURAUD,EURGBP,EURJPY,EURUSD";
extern string PairList3 = "GBPJPY,GBPUSD,USDCHF,USDJPY";
*/
extern int Length_Calculation = 50;
extern int Calculation_Interval = PERIOD_M30;
extern double Correlation_Limit = 70;
//+------------------------------------------------------------------+
string TimeFrameList = "60,1440";
int Price = PRICE_CLOSE;

#define IndicatorName "smCorrelation MultiPairs"

//---- buffers
string Pair[50];
int iTimeFrame[10];
double Corr1[50], Corr2[50];

//---- variables
string sIndicatorName;
string symbolA, symbolB;
datetime thisTime, oldTime;
string txtTFrame1, txtTFrame2, txtCalcInterval;

//---- Text parameters ----------------
int Corner_LeftUp  = 0;
int Corner_RightUp = 1;
int Corner_LeftDn  = 2;
int Corner_RightDn = 3;

//---- colors
color colorTitle         = DodgerBlue;
color colorTime          = White;
color colorPlusIndi      = Green;
color colorMinusIndi     = Red;
color colorPlusSignal    = DeepSkyBlue;
color colorMinusSignal   = Magenta;
color colorNeutralSignal = SandyBrown;

color colorCorrOK  = Green;
color colorCorrNOK = Red;

//---- distances ----------------
int xText = 75;
int xArrow = 60;
int xValue1 = 40;
int xValue2 =  2;
int yFirstRow  = 15;
int yStep = 12;
int xx, yy;

int rowTextHeight = 9;
int rowValueHeight = 11;

//---- variables
int nTitles = 50;
int NumberSymbols, NumberTimeFrames;
string SymbolSuffix;
int iWindow, iCorner;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   sIndicatorName = IndicatorName + " (" + symbolA + ", " + Length_Calculation + ") ";
   IndicatorShortName(sIndicatorName); 
   IndicatorDigits(1);  
   
   //---- initialisations
   iWindow = 0;
   iCorner = Corner_RightUp;
   //-- symbols
   SymbolSuffix  = Get_SymbolSuffix(Symbol());
   NumberSymbols = 0;
   Get_PairListNames(PairList1);
   Get_PairListNames(PairList2);
   Get_PairListNames(PairList3);
   //-- time frames 
   NumberTimeFrames = 0;
   Get_TimeFrameListValues();
   txtTFrame1 = Get_sPeriod(iTimeFrame[1]); 
   txtTFrame2 = Get_sPeriod(iTimeFrame[2]);
   txtCalcInterval = Get_sPeriod(Calculation_Interval);


   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{   
   //Comment("");
   Delete_ObjectNames("corr_");
   return(0);
}

//####################################################################
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{  
   int iBar = 0;      
   symbolA = Symbol();   
   
   thisTime = iTime(Symbol(),Calculation_Interval,0);
   if (thisTime != oldTime)
   {
      oldTime = thisTime;
      
      for(int i=1; i<=NumberSymbols; i++)   
      {
         if (Pair[i] != "") symbolB = Pair[i];
         double currentCorr1 = Get_Correlation(symbolA, symbolB, iBar, Length_Calculation, iTimeFrame[1]);
         double currentCorr2 = Get_Correlation(symbolA, symbolB, iBar, Length_Calculation, iTimeFrame[2]);
         Corr1[i] = currentCorr1;
         Corr2[i] = currentCorr2;
      }   
      Write_Correlations();
   }
   return(0);
}
//+------------------------------------------------------------------+


//###################################################################
//___________________________________________________________________
double Get_Correlation(string symbolA, string symbolB, int iBar, int length, int timeFrame)
{
//-- formula: http://en.wikipedia.org/wiki/Correlation_and_dependence
//-- Pearson correlation formula from: http://davidmlane.com/hyperstat/A51911.html
double sumA, sumB, avgA, avgB;
double corr2;
int i, j;
double arrayA[], arrayB[];
ArrayResize(arrayA,Bars);
ArrayResize(arrayB,Bars);
   //###################################################################
   //    SWINGMAN FORMULAS
   //###################################################################
   //---- initialize arrayA -----------------------------------------
   sumA = 0;
   int nI = 0;
   for (i=iBar; i<iBar+length; i++)
   {
      sumA += iClose(symbolA,timeFrame,i);
      nI++;
   }   
   avgA = sumA / length;   
     
   if (avgA != 0)
      for (i=iBar; i<iBar+length; i++)
         arrayA[i] = (iClose(symbolA,timeFrame,i) - avgA);
   
   double X2=0;
   for (i=iBar; i<iBar+length; i++)
      X2 += arrayA[i]*arrayA[i];
      
   //---- initialize arrayB -----------------------------------------
   sumB = 0;
   for (i=iBar; i<iBar+length; i++)
      sumB += iClose(symbolB,timeFrame,i);
   avgB = sumB / length;   
     
   if (avgB != 0)
      for (i=iBar; i<iBar+length; i++)
         arrayB[i] = (iClose(symbolB,timeFrame,i) - avgB);

   double Y2;
   for (i=iBar; i<iBar+length; i++)
      Y2 += arrayB[i]*arrayB[i];   
         
      
   //---- correlation -----------------------------------------------
   double sumXY=0;
   for (i=iBar; i<iBar+length; i++)
      sumXY += (arrayA[i]) * (arrayB[i]);

   double val5 = MathSqrt(X2 * Y2);
   if (val5 != 0)
      corr2 = sumXY / val5;
//----   
   return(corr2*100);
}



//####################################################################
//####################################################################
//####################################################################
//+------------------------------------------------------------------+
//| Get TimeFrame List Values
//+------------------------------------------------------------------+
void Get_TimeFrameListValues()
{
   int i,j,k;
   string CurTimeFrame;
   NumberTimeFrames = 0;
   
   for (i=0, j=0, k=1; i<nTitles && k>0;)
   {
      k=StringFind(TimeFrameList,",",j);
      if (k==0) CurTimeFrame=StringSubstr(TimeFrameList,j,0);
      else CurTimeFrame=StringSubstr(TimeFrameList,j,k-j);   
        
      if (CurTimeFrame != "")
      {  
         NumberTimeFrames++;
         iTimeFrame[NumberTimeFrames] = StrToInteger(CurTimeFrame);
      }
      i++;
          
      j=StringFind(TimeFrameList,",",j)+1;
      if (j==0) break;
   }
   return;
}

//####################################################################
//+------------------------------------------------------------------+
//|      Get PairList Names
//+------------------------------------------------------------------+
void Get_PairListNames(string PairsList)
{
   int i,j,k;
   string CurSymbol, CurSymbolSuff;
   double dClose;   
   
   for (i=0, j=0, k=1; i<nTitles && k>0;)
   {
      k=StringFind(PairsList,",",j);
      if (k==0) 
           CurSymbol=StringSubstr(PairsList,j,0);
      else CurSymbol=StringSubstr(PairsList,j,k-j);
      //---- set uppercase for the names in the extern parameter list
      CurSymbol = Set_SymbolUppercase(CurSymbol);      
      if (CurSymbol != "") {
         CurSymbolSuff = CurSymbol + SymbolSuffix;
         //---- 1. check if CurSymbolSuff is allowable ------------------
         //---- check suffix and current close
         if (SymbolSuffix != "")
         {
            //---- check if CurSymbol is allowable
            dClose = iClose(CurSymbolSuff,Period(),0);      
            if (dClose > 0.0) {
               i++;
               NumberSymbols++;
               Pair[NumberSymbols]=CurSymbolSuff;            
            } 
            else
            {    
               //---- check if CurSymbol is allowable
               dClose = iClose(CurSymbol,Period(),0);      
               if (dClose > 0.0) {
                  i++;
                  NumberSymbols++;
                  Pair[NumberSymbols]=CurSymbol;            
               }
            }
         }
         else
         //---- 2. check if CurSymbol is allowable ----------------------
         //---- check only current close
         {
            dClose = iClose(CurSymbol,Period(),0);      
            if (dClose > 0.0) {
               i++;
               NumberSymbols++;
               Pair[NumberSymbols]=CurSymbol;            
            }
         }
         j=StringFind(PairsList,",",j)+1;
         if (j==0) break;
      }
   }
   return;
}

               //#####################################################
               //             WRITE CORRELATIONS
               //#####################################################
void Write_Correlations()
{  
string name0, name1, name2;
string text0, text1, text2;
color  colr0, colr1, colr2;
   //---- Titles ----------------------------------------------------
   //--
   yy = yFirstRow;
   xx = xValue2;
   name0 = "corr_" + yy + "_" + xx;
   text0 = "Correlations " + symbolA;
   colr0 = colorTitle;
   SetLabelObject(name0, text0, colr0, xx, yy);
   //--
   yy = yy + yStep;
   name0 = "corr_" + yy + "_" + xx;
   text0 = Length_Calculation + "  Bars" + "; every " + txtCalcInterval;
   SetLabelObject(name0, text0, colr0, xx, yy);
   //--
   yy = yy + yStep;
   name0 = "corr_" + yy + "_" + xx;
   text0 = "Last calc. bar: " + TimeToStr(thisTime,TIME_MINUTES);
   SetLabelObject(name0, text0, colr0, xx, yy);
   //--
   yy = yy + yStep;   
   name1 = "corr_" + yy + "_" + xValue1;
   text1 = "["+txtTFrame1+"]";   
   name2 = "corr_" + yy + "_" + xValue2;
   text2 = "["+txtTFrame2+"]";
   //colr0 = Maroon;
   SetLabelObject(name1, text1, colr0, xValue1, yy);
   SetLabelObject(name2, text2, colr0, xValue2, yy);
   yy = yy + 2;
   
   //---- Correlations ----------------------------------------------
   for(int i=1; i<=NumberSymbols; i++)   
   {
      yy = yy + yStep;   
      //--      
      name0 = "corr_" + yy + "_" + xText;
      text0 = Pair[i];
      colr0 = colorTitle;
      
      //-- correlation 1 ............................................
      name1 = "corr_" + yy + "_" + xValue1;
      if (Corr1[i] >= 99.999) {
         text1 = "...  ";
         colr1 = colorTitle;
      }
      else
      {
         text1 = DoubleToStr(Corr1[i],1);
         if (MathAbs(Corr1[i]) <= Correlation_Limit) 
              colr1 = colorCorrOK;
         else colr1 = colorCorrNOK;
      }
      //-- correlation 2 ............................................
      name2 = "corr_" + yy + "_" + xValue2;
      if (Corr2[i] >= 99.999) {
         text2 = "...  ";
         colr2 = colorTitle;
      }
      else
      {
         text2 = DoubleToStr(Corr2[i],1);
         if (MathAbs(Corr2[i]) <= Correlation_Limit) 
              colr2 = colorCorrOK;
         else colr2 = colorCorrNOK;
      }
      
      //-- write correlations .......................................
      //SetLabelObject(name0, text0, colr0, xText, yy);
      SetLabel_PairNamen(name0, text0, colr0, xText, yy-2);
      SetLabelObject(name1, text1, colr1, xValue1, yy);
      SetLabelObject(name2, text2, colr2, xValue2, yy);
   } 

   return;     
}     

               //#####################################################
               //             OBJECTS
               //#####################################################
//+------------------------------------------------------------------+
//| Set Label Object
//+------------------------------------------------------------------+
void SetLabelObject(string sName, string sText, color dColor, int xx, int yy)
{
   ObjectDelete(sName);
   ObjectCreate(sName, OBJ_LABEL, iWindow, 0, 0);
        //ObjectSetText(sName,sText,rowTextHeight, "Courier New", dColor);
        ObjectSetText(sName,sText,rowTextHeight, "Arial Bold", dColor);
        ObjectSet(sName, OBJPROP_CORNER, iCorner);
        ObjectSet(sName, OBJPROP_XDISTANCE, xx);
        ObjectSet(sName, OBJPROP_YDISTANCE, yy);
   return;     
}

//+------------------------------------------------------------------+
//| Set Label Object Values
//+------------------------------------------------------------------+
void SetLabel_PairNamen(string sName, string sText, color dColor, int xx, int yy)
{
   ObjectDelete(sName);
   ObjectCreate(sName, OBJ_LABEL, iWindow, 0, 0);
        ObjectSetText(sName,sText,rowValueHeight, "Courier New", dColor);
        //ObjectSetText(sName,sText,rowTextHeight, "Arial Bold", dColor);
        ObjectSet(sName, OBJPROP_CORNER, iCorner);
        ObjectSet(sName, OBJPROP_XDISTANCE, xx);
        ObjectSet(sName, OBJPROP_YDISTANCE, yy);
   return;     
}


//+------------------------------------------------------------------+
//| Set Arrow Object
//+------------------------------------------------------------------+
void SetArrowObject(string sName, int ArrowCode, int iHeight, color dColor, int xx, int yy)
{
   ObjectDelete(sName);
   ObjectCreate(sName, OBJ_LABEL, iWindow, 0, 0);
   ObjectSetText(sName,CharToStr(ArrowCode),iHeight, "Wingdings", dColor);
        ObjectSet(sName, OBJPROP_CORNER, iCorner);
        ObjectSet(sName, OBJPROP_XDISTANCE, xx);
        ObjectSet(sName, OBJPROP_YDISTANCE, yy);
   return;     
}


//+------------------------------------------------------------------+
//| Delete Object Names
//+------------------------------------------------------------------+
void Delete_ObjectNames(string sName)
{
   int nObjects = ObjectsTotal();
   for (int i=nObjects; i>=0; i--)
   {
      string sObjectName = ObjectName(i);
      if (StringFind(sObjectName, sName, 0) != -1)
         ObjectDelete(sObjectName);
   }
   return;
}

//+------------------------------------------------------------------+
//    Get sPeriod
//+------------------------------------------------------------------+
string Get_sPeriod(int timeframe)
{
   if (timeframe == PERIOD_M1) return("M1");
   if (timeframe == PERIOD_M5) return("M5");
   if (timeframe == PERIOD_M15) return("M15");
   if (timeframe == PERIOD_M30) return("M30");
   if (timeframe == PERIOD_H1) return("H1");
   if (timeframe == PERIOD_H4) return("H4");
   if (timeframe == PERIOD_D1) return("D1");
   if (timeframe == PERIOD_W1) return("W1");
   if (timeframe == PERIOD_MN1) return("MN1");
}

//+------------------------------------------------------------------+
//    Get Symbol Suffix
//+------------------------------------------------------------------+
string Get_SymbolSuffix(string sSymbol)
{
   int Len = StringLen(sSymbol);
   if (Len <= 6) return("");
   
   int iChar = StringGetChar(sSymbol, Len-1);
   
   string sChar = "x";
   sChar = StringSetChar(sChar,0,iChar);
   
   string sSuffix = StringSubstr(sSymbol,6,Len-5);  
   return(sSuffix);
}

//+------------------------------------------------------------------+
//    Set Symbol Uppercase
//+------------------------------------------------------------------+
string Set_SymbolUppercase(string sText)
{
   int Len = StringLen(sText);
   for (int i=0; i<Len; i++) {
      if (i < 6) 
      {
         int iChar = StringGetChar(sText, i);
         if (iChar >= 97 && iChar <=122) 
            sText = StringSetChar(sText, i, iChar - 32);         
      }
   }
   return(sText);
}