^L_Correlation

Download script
Author: Copyright � 2008, lotos4u
^L_Correlation

This script is a financial analysis tool designed to measure the relationship between two different trading instruments (such as two different currency pairs) to see how closely they move in tandem. In financial markets, this is known as correlation analysis.

Core Functionality

The primary purpose of this tool is to calculate a correlation coefficient. This value tells you whether two assets are moving in the same direction, opposite directions, or if their movements are completely unrelated.

The logic follows these specific steps:

1. Data Selection Modes The tool allows you to choose how the price data is interpreted. You can compare the instruments based on:

  • Closing Prices: The standard price at the end of a period.
  • Price Range (Open to Close): This looks at the "movement" within a candle rather than just the final price.
  • Relative Price: The closing price compared against the high of that period, which helps normalize the data.

2. Time and Price Validation To ensure the accuracy of the calculation, the script performs two vital checks:

  • Time Synchronization: It ensures that it is comparing the same time periods for both instruments (e.g., making sure the "10:00 AM" price of Currency A is compared directly against the "10:00 AM" price of Currency B).
  • Price Validity: It verifies that the data points are valid and not empty before including them in the calculation.

3. Statistical Calculation The script looks back over a user-defined "radius" (a specific number of previous candles) to perform a statistical analysis:

  • It calculates the average price movement for both instruments.
  • It measures the "dispersion," which identifies how much each instrument deviates from its own average.
  • It determines the "covariation," which reveals how the two instruments move together relative to one another.
  • Finally, it produces a correlation value. Typically, a value close to 1.0 means they move perfectly together, -1.0 means they move in opposite directions, and 0 means there is no relationship.

4. Smoothing and Visualization Because raw correlation data can be jumpy or "noisy," the script includes an optional Moving Average (MA) feature. This smooths out the correlation line to make it easier for a human to read trends.

5. On-Screen Information The tool provides a real-time text label on your chart. This label displays the current average correlation between the two symbols and informs you of how many bars of data were used to reach that specific calculation, allowing for a quick glance at the strength of the relationship.

Price Data Components
Series array that contains close prices for each barSeries array that contains open prices of each barSeries array that contains the highest prices of each bar
Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1
4 Views
0 Downloads
0 Favorites
^L_Correlation
//+------------------------------------------------------------------+
//|                                               ^L_Correlation.mq4 |
//|                                        Copyright © 2008, lotos4u |
//|                                                lotos4u@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, lotos4u"
#property link      "lotos4u@gmail.com"

#define CLOSE_MODE 0
#define OPENCLOSE_MODE 1
#define CLOSE_RELATIVE_MODE 2
//#define OPENCLOSE_RELATIVE_MODE 3

#property indicator_separate_window
#property indicator_minimum -1
#property indicator_maximum 1
#property indicator_buffers 8

#property indicator_color1 Aqua
#property indicator_color2 Blue
#property indicator_color3 Red
#property indicator_color4 Chocolate
#property indicator_color5 MediumVioletRed
#property indicator_color6 DarkOrange
#property indicator_color7 Magenta
#property indicator_color8 Lime

#property indicator_width1 1
#property indicator_width2 2


#property indicator_level1 0.5
#property indicator_level2 0.0
#property indicator_level3 -0.5
#property indicator_levelcolor BlueViolet

#include <stderror.mqh>
#include <stdlib.mqh>


extern int Mode = CLOSE_RELATIVE_MODE;
extern string Pair = "USDCHF";
extern bool ShowCorrelation = false;
extern bool ShowMA = true;
extern int CorrelationRadius = 15;
extern int MA_Period = 10;
extern int ResultingBars = 0;

extern string FontName = "Verdana";
extern int FontSize = 10;
extern color FontColor = Black;

double Correlation[], CorrelationBuffer[], AverageCorrelationBuffer[];
double AverageX, AverageY, AverageXY, DispersionX, DispersionY, CovariationXY;
int CalculateCounter, ValidDataCounter;
string ShortName = "L_Correlation";



//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+

int init()
{
   ShortName = ShortName + " (" + Symbol() + "-" + Pair + ", " + Mode + ", " + CorrelationRadius + ", " + MA_Period + ")";
   IndicatorShortName(ShortName);
   
   SetIndexStyle(0, DRAW_LINE);
   SetIndexBuffer(0, CorrelationBuffer);
   SetIndexEmptyValue(0, 0.0);

   SetIndexStyle(1, DRAW_LINE);
   SetIndexBuffer(1, AverageCorrelationBuffer);
   SetIndexEmptyValue(1, 0.0);
   
   CalculateCounter = 0;
   ValidDataCounter = 0;
   
   return(0);
}


//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   CalculateCounter = 0;
   ValidDataCounter = 0;
   DeleteObjectsByPhrase(ShortName);
   return(0);
}


//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   double AverageCorrelation;
   int AverageLength;
   int window = WindowFind(ShortName);
   string ID = ShortName + " Label";
   if(ObjectCreate(ID, OBJ_LABEL, window, 0, 0))
   {
      ObjectSet(ID, OBJPROP_CORNER, 2);
      ObjectSet(ID, OBJPROP_XDISTANCE, 0);
      ObjectSet(ID, OBJPROP_YDISTANCE, FontSize);
   }

   if(CalculateCounter > 0 && Volume[0] > 1)return(0);

   
   int limit = Bars, counter = 0;

   ArrayResize(Correlation, limit);
   ArrayInitialize(Correlation, 0.0);
   ArraySetAsSeries(Correlation, true);

   for(int i = 0; i < limit; i++)
   {
      getAverages(i, CorrelationRadius);
      if(DispersionX*DispersionY > 0 && MathSqrt(DispersionX*DispersionY) > 0)
      {
         counter++;
         Correlation[i] = CovariationXY/MathSqrt(DispersionX*DispersionY);
      }
      else
      {
         Correlation[i] = 0.0;
      }
      if(ShowCorrelation)
         CorrelationBuffer[i] = Correlation[i];
   }
   
   for(i = 0; i < counter; i++)
   {
      AverageCorrelationBuffer[i] = iMAOnArray(Correlation, 0, MA_Period, 0, MODE_SMA, i);
   }
   
   AverageLength = MathMin(ResultingBars, counter);
   if(ResultingBars == 0)
      AverageLength = counter;
   AverageCorrelation = iMAOnArray(Correlation, 0, AverageLength, 0, MODE_SMA, 0);
   
   ObjectSetText(ID, Symbol() + " <-> " + Pair + "   " + DoubleToStr(AverageCorrelation, 2) + " (ïî " + AverageLength + " áàðàì)", FontSize, FontName, FontColor);

   CalculateCounter = MathMin(1, counter);
   return(0);
}


double getX(int shift)
{
   switch(Mode)
   {
      case CLOSE_MODE: return(iClose(Symbol(), 0, shift));
      case OPENCLOSE_MODE: return(iClose(Symbol(), 0, shift) - iOpen(Symbol(), 0, shift));
      case CLOSE_RELATIVE_MODE: return(iClose(Symbol(), 0, shift)/iHigh(Symbol(), 0, shift));
   }
}



double getY(int shift)
{
   switch(Mode)
   {
      case CLOSE_MODE: return(iClose(Pair, 0, shift));
      case OPENCLOSE_MODE: return(iClose(Pair, 0, shift) - iOpen(Pair, 0, shift));
      case CLOSE_RELATIVE_MODE: return(iClose(Pair, 0, shift)/iHigh(Pair, 0, shift));
   }
}



bool isValidTime(int shift)
{
   return(iTime(Symbol(), 0, shift) == iTime(Pair, 0, shift));
}




bool isValidPrice(int shift)
{
   return((iOpen(Symbol(), 0, shift) > 0.0) && (iOpen(Pair, 0, shift) > 0.0));
}



double getAverages(int start, int interval)
{
   double retVal = 0;
   ValidDataCounter = 0;
   AverageX = 0;
   AverageY = 0;
   AverageXY = 0;
   DispersionX = 0;
   DispersionY = 0;
   for(int i = 0; i < interval; i++)
   {
      if(isValidTime(start + i))
      {
         if(!isValidPrice(start + i))
         {
            Sleep(2000);
            if(!isValidPrice(start + i))
               continue;
         }
         ValidDataCounter++;
         AverageX += getX(start + i);
         AverageY += getY(start + i);
         AverageXY += getX(start + i)*getY(start + i);
      }
   }
   if(ValidDataCounter == 0)return;
   AverageX /= ValidDataCounter;
   AverageY /= ValidDataCounter;
   AverageXY /= ValidDataCounter;

   ValidDataCounter = 0;
   for(i = 0; i < interval; i++)
   {
      if(isValidTime(start + i))
      {
         if(!isValidPrice(start + i))
         {
            Sleep(2000);
            if(!isValidPrice(start + i))
               continue;
         }
         ValidDataCounter++;
         DispersionX += (getX(start + i) - AverageX)*(getX(start + i) - AverageX);
         DispersionY += (getY(start + i) - AverageY)*(getY(start + i) - AverageY);
      }
   }
   if(ValidDataCounter == 0)return;
   DispersionX /= ValidDataCounter;
   DispersionY /= ValidDataCounter;
   
   CovariationXY = AverageXY - AverageX*AverageY;
}





/////////////////////////////////////////////////////////
//Óäàëÿþòñÿ âñå îáúåêòû, â èìåíàõ êîòîðûõ ñîäåðæèòñÿ ñòðîêà
//Phrase (ðàñïîëîæåííàÿ â ïðîèçâîëüíîé ïîçèöèè)
/////////////////////////////////////////////////////////
void DeleteObjectsByPhrase(string Phrase)
{
   string ObjName;
   for(int i = ObjectsTotal()-1; i >= 0; i--)
   {
      ObjName = ObjectName(i);
      if(StringFind(ObjName, Phrase, 0) > -1) 
      { 
         ObjectDelete(ObjName);
      }
   }
}

Comments